HealthSherpa Quotes API

The Quotes API from HealthSherpa — 1 operation(s) for quotes.

OpenAPI Specification

healthsherpa-quotes-api-openapi.yml Raw ↑
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