HealthSherpa Quotes API
The Quotes API from HealthSherpa — 1 operation(s) for quotes.
Documentation
Documentation
https://one.healthsherpa.com/docs.html
APIReference
https://one.healthsherpa.com/docs.html
The Quotes API from HealthSherpa — 1 operation(s) for quotes.
openapi: 3.1.0
info:
title: HealthSherpa Public Enrollment Sessions Quotes API
version: 0.1.0
description: 'Machine-readable contract for the currently available public HealthSherpa endpoints: GET /v1/ping, GET /v1/reference/counties, GET /v1/reference/issuers, GET /v1/reference/providers, POST /v1/quotes, the approval-gated POST /v1/enrollment-sessions, and the approval-gated direct enrollment endpoints GET /v1/enrollments, POST /v1/enrollments, PUT /v1/enrollments/{enrollment_id}, GET /v1/enrollments/{enrollment_id}, POST /v1/enrollments/{enrollment_id}/cancellations, POST /v1/enrollments/{enrollment_id}/terminations, POST /v1/enrollments/{enrollment_id}/submissions, GET /v1/enrollments/{enrollment_id}/payment_redirect, and POST /v1/enrollments/{enrollment_id}/supporting_documentation. Object schemas remain additive and clients should ignore response fields they do not recognize.
Most HealthSherpa-owned errors follow the unified `ErrorResponse` schema: `{ "error": { "code": string, "message": string, "details"?: object } }`. The direct enrollment endpoints instead return service failures as a top-level `errors[]` array: `{ "errors": [ { "code": string, "message": string, "field"?: string } ] }`. Edge-generated failures (API Gateway and WAF, before a request reaches the service) always use the unified `ErrorResponse` envelope, including on the direct enrollment endpoints — most notably a missing or invalid API key (`403 forbidden`).'
servers:
- url: https://api.one.healthsherpa.com
description: Production
security:
- ApiKeyAuth: []
tags:
- name: Quotes
paths:
/v1/quotes:
post:
tags:
- Quotes
summary: Search plans for one coverage type
description: Returns a homogeneous list of quote results for exactly one coverage_type. Send one request for one market and one coverage_type at a time.
operationId: createQuote
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/QuoteRequest'
example:
context:
product: aca
exchange: on_exchange
coverage_family: medical
coverage_type: medical
plan_year: 2026
location:
zip_code: '30301'
fips_code: '13121'
state: GA
household:
household_size: 1
annual_income: 52000
effective_date: '2026-05-01'
applicants:
- member_id: applicant-1
age: 40
date_of_birth: '1986-05-01'
relationship: primary
uses_tobacco: false
pregnant: false
blind_or_disabled: false
native_american: false
sort:
field: premium
direction: asc
page:
number: 1
size: 20
responses:
'200':
description: Quotes returned successfully.
content:
application/json:
schema:
$ref: '#/components/schemas/QuoteResponse'
'400':
$ref: '#/components/responses/BadRequest'
'403':
$ref: '#/components/responses/Forbidden'
'413':
$ref: '#/components/responses/PayloadTooLarge'
'415':
$ref: '#/components/responses/UnsupportedMediaType'
'429':
$ref: '#/components/responses/RateLimited'
'500':
$ref: '#/components/responses/InternalError'
'502':
$ref: '#/components/responses/BadGateway'
'503':
$ref: '#/components/responses/ServiceUnavailable'
'504':
$ref: '#/components/responses/GatewayTimeout'
components:
schemas:
QuoteRequest:
type: object
additionalProperties: true
required:
- context
- location
- household
description: Canonical quote request for new integrations. Legacy `include` input is accepted for backward compatibility but ignored.
properties:
context:
$ref: '#/components/schemas/QuoteContext'
location:
$ref: '#/components/schemas/LocationInput'
household:
$ref: '#/components/schemas/HouseholdQuoteInput'
filters:
$ref: '#/components/schemas/QuoteFilters'
sort:
$ref: '#/components/schemas/SortInput'
page:
$ref: '#/components/schemas/PageInput'
include:
deprecated: true
description: Deprecated and ignored. Accepted for backward compatibility.
PageInput:
type: object
additionalProperties: true
properties:
number:
type: integer
minimum: 1
default: 1
size:
type: integer
minimum: 1
maximum: 500
default: 20
MedicalFilters:
type: object
additionalProperties: true
properties:
metal_levels:
type: array
items:
type: string
enum:
- bronze
- expanded_bronze
- silver
- gold
- platinum
- catastrophic
plan_types:
type: array
items:
type: string
enum:
- hmo
- ppo
- epo
- pos
- indemnity
hsa_eligible:
type: boolean
standardized_only:
type: boolean
ErrorResponse:
type: object
description: 'Canonical error envelope returned by HealthSherpa-owned API endpoint, infrastructure filter, and backend service failures. The direct enrollment endpoints return their own service failures using `EnrollmentErrorsResponse` (`errors[]`), but edge-generated failures on those endpoints (API Gateway and WAF, e.g. a missing or invalid API key) still use this `ErrorResponse` envelope. Clients should treat `error.code` as the stable programmatic identifier and surface `error.message` to humans. Recognized codes include:
- `unauthorized` (401) - backend runtime authentication failure when a request reaches a runtime that performs its own authentication
- `forbidden` (403) - missing/invalid/unauthorized API key at the API edge, or edge policy deny
- `invalid_request` (400) - request body or parameter validation failed
- `not_found` (404) - resource or route not found
- `payload_too_large` (413) - request body exceeded edge limits
- `unsupported_media_type` (415) - unsupported Content-Type
- `rate_limited` (429) - edge rate-limiting
- `service_unavailable` (503) - the edge is failing to reach the backend, or an upstream catalog/quoting/lookup service is unavailable
- `bad_gateway` (502) - the edge received an invalid response from the backend
- `gateway_timeout` (504) - the edge did not receive a timely response from the backend
- `internal_error` (500) - unexpected server error'
additionalProperties: true
required:
- error
properties:
error:
type: object
additionalProperties: true
required:
- code
- message
properties:
code:
type: string
description: Stable, machine-readable identifier for the error class (see ErrorResponse description for recognized values). Clients should branch on this field rather than on `message` or HTTP status alone.
message:
type: string
description: Human-readable explanation of the error, suitable for logging or surfacing to an end user.
details:
type: object
description: Optional per-field validation details. Keys are dotted/indexed paths (e.g. `household.applicants[0].age`) and values are arrays of full-sentence error messages.
additionalProperties:
type: array
items:
type: string
SortInput:
type: object
additionalProperties: true
properties:
field:
type: string
direction:
type: string
enum:
- asc
- desc
QuoteResponseMeta:
type: object
additionalProperties: true
required:
- page_number
- page_size
- result_count
- warnings
properties:
page_number:
type: integer
page_size:
type: integer
result_count:
type: integer
warnings:
type: array
description: Non-fatal advisories for the request. Includes an include deprecation warning when legacy `include` is supplied.
items:
type: string
PlanQuoteResult:
type: object
additionalProperties: true
required:
- plan_id
- coverage_family
- coverage_type
- name
- api_enrollable
- context
- issuer
- pricing
- documents
- details
- release
properties:
plan_id:
type: string
variant_id:
type: string
external_plan_id:
type: string
coverage_family:
type: string
coverage_type:
type: string
name:
type: string
display_name:
type: string
api_enrollable:
type: boolean
description: Whether this quoted plan passes the known plan, carrier, and state pre-create gates for direct off-exchange API enrollment at quote time. `true` means the plan can be used with the direct off-exchange enrollment API. `false` means use quote/display only or another enrollment path. This is not consumer ACA eligibility and does not guarantee successful submission after applicant and carrier validation.
context:
type: object
additionalProperties: true
required:
- product
- exchange
- coverage_family
- coverage_type
properties:
product:
type: string
enum:
- aca
- ichra
exchange:
type: string
enum:
- on_exchange
- off_exchange
coverage_family:
type: string
enum:
- medical
- ancillary
coverage_type:
type: string
enum:
- medical
- dental
- vision
- supplemental_other
plan_year:
type: integer
minimum: 2020
issuer:
type: object
additionalProperties: true
required:
- issuer_id
- name
properties:
issuer_id:
type: string
name:
type: string
state:
type: string
nullable: true
pattern: ^[A-Z]{2}$
description: Two-letter US state code where the issuer is licensed.
payment_phone:
type: string
nullable: true
description: Phone number for member premium-payment inquiries.
customer_service_phone:
type: string
nullable: true
description: Phone number for general customer-service inquiries.
network:
type: object
additionalProperties: true
nullable: true
properties:
network_id:
type: string
name:
type: string
type:
type: string
nullable: true
network_url:
type: string
format: uri
nullable: true
pricing:
type: object
additionalProperties: true
required:
- gross_premium
- currency
properties:
gross_premium:
type: number
ehb_premium:
type: number
max_aptc:
type: number
subsidy_applied:
type: number
net_premium:
type: number
currency:
type: string
enum:
- USD
billing_period:
type: string
enum:
- monthly
documents:
type: object
additionalProperties: true
description: Canonical document slots. Carrier-specific source URLs are mapped into these stable fields.
properties:
sbc_url:
type: string
format: uri
nullable: true
description: Summary of Benefits and Coverage document URL.
formulary_url:
type: string
format: uri
nullable: true
brochure_url:
type: string
format: uri
nullable: true
network_url:
type: string
format: uri
nullable: true
payment_url:
type: string
format: uri
nullable: true
description: Issuer-hosted page for making a premium payment.
availability:
type: object
additionalProperties: true
description: Resolved geographic availability lineage produced after county-first location resolution.
properties:
state:
type: string
pattern: ^[A-Z]{2}$
service_area_id:
type: string
nullable: true
rating_area:
type: string
nullable: true
details:
type: object
additionalProperties: true
required:
- type
properties:
type:
type: string
enum:
- medical
- dental
- vision
- supplemental_other
metal_level:
type: string
description: Present for medical quote results.
enum:
- bronze
- expanded_bronze
- silver
- gold
- platinum
- catastrophic
plan_type:
type: string
description: Present for medical quote results.
enum:
- hmo
- ppo
- epo
- pos
- indemnity
hsa_eligible:
type: boolean
nullable: true
description: Present for medical quote results.
is_standardized:
type: boolean
nullable: true
description: Whether the plan follows a CMS- or state-defined standardized design. Present for medical quote results.
adult_dental:
type: boolean
nullable: true
description: Whether the medical plan embeds adult dental coverage. Present for medical quote results.
child_dental:
type: boolean
nullable: true
description: Whether the medical plan embeds pediatric (child) dental coverage. Present for medical quote results.
deductible_individual:
type: number
nullable: true
description: Individual annual deductible (USD). Present for medical quote results.
deductible_family:
type: number
nullable: true
description: Family annual deductible (USD). Present for medical quote results.
moop_individual:
type: number
nullable: true
description: Individual maximum out-of-pocket (USD). Present for medical quote results.
moop_family:
type: number
nullable: true
description: Family maximum out-of-pocket (USD). Present for medical quote results.
csr_level:
type: string
nullable: true
enum:
- off_exchange
- standard
- csr_zero_cost
- csr_limited
- csr73
- csr87
- csr94
- csr77
description: 'CMS CSR variation derived from the 2-digit HIOS variant suffix. Source: PlanAttributes PUF CSRVariationType.'
primary_care_summary:
type: string
nullable: true
description: Cost-share summary for a primary-care visit (e.g. "$25 Copay").
specialist_summary:
type: string
nullable: true
description: Cost-share summary for a specialist visit.
urgent_care_summary:
type: string
nullable: true
description: Cost-share summary for an urgent-care visit.
generic_rx_summary:
type: string
nullable: true
description: Cost-share summary for generic prescription drugs.
release:
type: object
additionalProperties: true
required:
- release_id
properties:
release_id:
type: string
plan_year:
type: integer
QuoteFilters:
type: object
additionalProperties: true
properties:
issuer_ids:
type: array
items:
type: string
premium_min:
type: number
minimum: 0
premium_max:
type: number
minimum: 0
effective_date:
type: string
format: date
network_types:
type: array
items:
type: string
medical:
$ref: '#/components/schemas/MedicalFilters'
QuoteContext:
type: object
additionalProperties: true
required:
- product
- exchange
- coverage_family
- coverage_type
properties:
product:
type: string
enum:
- aca
- ichra
exchange:
type: string
enum:
- on_exchange
- off_exchange
coverage_family:
type: string
enum:
- medical
- ancillary
coverage_type:
type: string
enum:
- medical
- dental
- vision
- supplemental_other
plan_year:
type: integer
minimum: 2020
LocationInput:
type: object
additionalProperties: true
required:
- zip_code
- fips_code
properties:
zip_code:
type: string
pattern: ^[0-9]{5}$
fips_code:
type: string
pattern: ^[0-9]{5}$
state:
type: string
pattern: ^[A-Z]{2}$
description: Quoteable state code for one of the 50 states or DC.
HouseholdQuoteInput:
type: object
additionalProperties: true
required:
- applicants
- household_size
properties:
applicants:
type: array
minItems: 1
items:
$ref: '#/components/schemas/ApplicantInput'
annual_income:
type: number
minimum: 0
household_size:
type: integer
minimum: 1
effective_date:
type: string
format: date
ApplicantInput:
type: object
additionalProperties: true
required:
- member_id
- age
- relationship
- uses_tobacco
properties:
member_id:
type: string
minLength: 1
description: Caller-supplied applicant identifier. Use a stable value from your system, such as `applicant-1`; this is not the applicant relationship. Send `relationship` separately as `primary`, `spouse`, or `dependent`.
age:
type: integer
minimum: 0
date_of_birth:
type: string
format: date
relationship:
type: string
enum:
- primary
- spouse
- dependent
uses_tobacco:
type: boolean
gender:
type: string
enum:
- female
- male
- other
- unknown
description: Optional applicant gender for quote flows that use gender in marketplace screening.
pregnant:
type: boolean
blind_or_disabled:
type: boolean
native_american:
type: boolean
QuoteResponse:
type: object
additionalProperties: true
required:
- plans
- meta
properties:
plans:
type: array
items:
$ref: '#/components/schemas/PlanQuoteResult'
meta:
$ref: '#/components/schemas/QuoteResponseMeta'
responses:
Forbidden:
description: The API key is missing, invalid, not authorized for this API, or the request was blocked at the API edge. Public API requests may receive this edge-generated response before the backend can return a runtime 401. When a request reaches the backend, 403 may also mean the developer account or integration is not in the state required for that operation. For `POST /v1/enrollment-sessions`, that operation documents its own flow-scoped 403 requirements (both flows require approved on-exchange enrollment access, plus `agent_assisted` OAuth link vs `self_service` deeplink agent ID) instead of using this shared response reference.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error:
code: forbidden
message: The supplied API key is missing, invalid, or not authorized for this API.
InternalError:
description: An unexpected error occurred.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error:
code: internal_error
message: An unexpected error occurred.
RateLimited:
description: Rate limit exceeded. Clients should back off and retry after the delay advertised in the Retry-After header.
headers:
Retry-After:
description: Number of seconds the client should wait before retrying.
schema:
type: integer
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error:
code: rate_limited
message: Request rate limit exceeded. Please slow down and retry shortly.
GatewayTimeout:
description: The API edge did not receive a timely response from the backend.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error:
code: gateway_timeout
message: The API edge did not receive a timely response from the backend. Please try again later.
UnsupportedMediaType:
description: The request `Content-Type` is not supported by the endpoint.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error:
code: unsupported_media_type
message: The request Content-Type is not supported by this endpoint.
ServiceUnavailable:
description: The API is temporarily unable to serve the request. This may be returned by the API edge when the backend is unhealthy, or by the backend when an upstream catalog, quoting, or lookup service is unavailable.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error:
code: service_unavailable
message: The service is temporarily unavailable. Please try again later.
BadGateway:
description: The API edge received an invalid response from the backend.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error:
code: bad_gateway
message: The API edge received an invalid response from the backend. Please try again later.
BadRequest:
description: 'Request validation failed. The response body''s `error.details` map contains per-field messages when the backend produced the error; edge-generated 400s omit `details`.
A malformed `Idempotency-Key` header is also rejected here with `code: idempotency_key_invalid`.'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error:
code: invalid_request
message: Validation failed.
details:
zip_code:
- ZIP code must be 5 digits
PayloadTooLarge:
description: The request body exceeded the maximum size accepted by the API edge.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error:
code: payload_too_large
message: The request payload exceeded the maximum allowed size.
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: x-api-key