HealthSherpa Enrollment Sessions API

The Enrollment Sessions API from HealthSherpa — 1 operation(s) for enrollment sessions.

OpenAPI Specification

healthsherpa-enrollment-sessions-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: HealthSherpa Public Enrollment Sessions 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: Enrollment Sessions
paths:
  /v1/enrollment-sessions:
    post:
      tags:
      - Enrollment Sessions
      summary: Start an enrollment session
      description: 'Returns URLs to continue enrollment in a browser-mediated HealthSherpa flow. This endpoint always returns deep links and does not create direct enrollment application records.


        Both agent-assisted and consumer self-service use cases are supported. Set `context.flow` to `agent_assisted` for an agent walking a client through enrollment, or to `self_service` for a consumer enrolling themselves. The `campaign.*` block and the top-level `plan_id` field are only accepted in self-service flows.


        The entire `context` object and every field inside it is required so partners declare product, exchange, coverage, plan year, flow, and locale on every request rather than relying on hidden defaults. In `self_service`, supply at least one of `location.state` or top-level `plan_id`. In `agent_assisted`, `location.state` is required.'
      operationId: createEnrollmentSession
      parameters:
      - name: Idempotency-Key
        in: header
        required: false
        description: 'Optional partner-supplied request identifier (1–255 chars, `A-Z`, `a-z`, `0-9`, `-`, `_`). Scoped by API key and retained for 24 hours.


          - First call: processed normally; the response is captured.

          - Replay (same key + same body): returns the original response verbatim with `Idempotent-Replay: true`.

          - Same key + different body: `422 idempotency_mismatch`.

          - Concurrent retry while the first call is still in flight: `409 idempotency_in_progress`.

          - `429` responses are not stored, so partners can back off and retry transparently.

          - `5xx` responses **are** stored. Retrying a 5xx with the same Idempotency-Key could risk duplicate work, so partners who believe a 5xx was transient must generate a fresh Idempotency-Key to retry.'
        schema:
          type: string
          pattern: ^[A-Za-z0-9_\-]{1,255}$
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EnrollmentSessionRequest'
            example:
              external_id: crm-lead-abc-123
              context:
                product: aca
                exchange: on_exchange
                coverage_family: medical
                coverage_type: medical
                plan_year: 2026
                flow: self_service
                locale: en-US
              plan_id: 12345NY0010001
              location:
                zip_code: '10001'
                fips_code: '36061'
                state: NY
              household:
                annual_income: 42000
                household_size: 1
                applicants:
                - relationship: primary
                  first_name: Jane
                  last_name: Doe
                  email: jane@example.com
                  phone_number: '5551234567'
                  date_of_birth: '1990-01-01'
                  sex: female
                  uses_tobacco: false
      responses:
        '200':
          description: Enrollment session started successfully.
          headers:
            X-Request-Id:
              description: HealthSherpa ONE request id for tracing and support.
              schema:
                type: string
            Idempotent-Replay:
              description: Present and set to `true` only when this response is being replayed from a prior call that supplied the same `Idempotency-Key` and request body.
              schema:
                type: string
                enum:
                - 'true'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EnrollmentSessionResponse'
              example:
                external_id: crm-lead-abc-123
                links:
                  shopping_url: https://healthsherpa.com/public/shop?external_id=crm-lead-abc-123&fip_code=36061&household_income=42000&household_size=1&people%5Bprimary%5D%5Bage%5D=36&people%5Bprimary%5D%5Bgender%5D=female&people%5Bprimary%5D%5Btobacco%5D=false&state=NY&user_type=consumer&year=2026&zip_code=10001
                  client_apply_url: https://healthsherpa.com/public/apply?external_id=crm-lead-abc-123&fip_code=36061&household_income=42000&household_size=1&people%5Bprimary%5D%5Bage%5D=36&people%5Bprimary%5D%5Bgender%5D=female&people%5Bprimary%5D%5Btobacco%5D=false&plan_hios_id=12345NY0010001&state=NY&user_type=consumer&year=2026&zip_code=10001
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: 'Returned when this API key is not authorized to call this endpoint, or when the developer''s HealthSherpa Marketplace setup is not in the state the requested flow needs.


            - `context.flow = "agent_assisted"` requires approved on-exchange enrollment access (`onExchangeEnrollmentRequestApprovalStatus = "approved"`) and a healthy HealthSherpa Marketplace OAuth link (account approved, integration `active`, on-exchange capability `ready`, and the access token unexpired or refreshable). The OAuth-linked HealthSherpa Marketplace agent must also belong to an agency that is approved for enrollment deeplink URL generation. If HealthSherpa cannot generate `shopping_url` or `client_apply_url` because the agent account or agency is not approved for deeplink access, the API returns `403 forbidden` and does not treat the result as retryable service unavailability.

            - `context.flow = "self_service"` requires approved on-exchange enrollment access (`onExchangeEnrollmentRequestApprovalStatus = "approved"`) and a configured deeplink agent ID.


            Both flows require approved on-exchange enrollment access. The self-service gate does not consult the OAuth link, and the agent-assisted gate does not consult the deeplink agent ID. Each flow only fails when the configuration it actually uses is not satisfied.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                notAuthorized:
                  value:
                    error:
                      code: forbidden
                      message: This API key is not authorized to access this endpoint.
                agentDeeplinksNotEnabled:
                  value:
                    error:
                      code: forbidden
                      message: Enrollment deeplinks are not available for this HealthSherpa Marketplace agent yet. Confirm the agent account is part of an agency and that the agency has been approved for deeplink access. Contact HealthSherpa support for help enabling this configuration.
        '409':
          $ref: '#/components/responses/IdempotencyInProgress'
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '415':
          $ref: '#/components/responses/UnsupportedMediaType'
        '422':
          $ref: '#/components/responses/IdempotencyMismatch'
        '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:
    EnrollmentSessionResponseLinks:
      type: object
      additionalProperties: true
      required:
      - shopping_url
      - client_apply_url
      properties:
        shopping_url:
          type: string
          format: uri
          description: HealthSherpa public shop URL (https://healthsherpa.com/public/shop?...).
        client_apply_url:
          type: string
          format: uri
          description: HealthSherpa public apply URL (https://healthsherpa.com/public/apply?...). Always present for enrollment-session responses.
    EnrollmentSessionLocation:
      type: object
      additionalProperties: false
      description: Routing geography plus optional street address. `zip_code`, `fips_code`, and `state` route the request; `address_line_1`, `address_line_2`, and `city` are used by the agent-assisted enrollment flow only and ignored on self-service deep links.
      properties:
        zip_code:
          type: string
          pattern: ^[0-9]{5}$
        fips_code:
          type: string
          pattern: ^[0-9]{5}$
          description: Five-digit county FIPS code. Mapped to the deep link's legacy `fip_code` parameter.
        state:
          type: string
          description: Two-letter US state code (50 states plus DC).
          pattern: ^[A-Za-z]{2}$
        address_line_1:
          type: string
          description: First line of the street address (number and street). Used in the agent-assisted enrollment flow.
          maxLength: 50
        address_line_2:
          type: string
          description: Optional second line of the street address (apartment, suite). Used in the agent-assisted enrollment flow.
          maxLength: 50
        city:
          type: string
          description: City of the street address. Used in the agent-assisted enrollment flow; ignored on self-service deep links.
          maxLength: 50
    EnrollmentSessionClient:
      type: object
      additionalProperties: false
      deprecated: true
      description: 'DEPRECATED legacy contact block. Every property here has a 1:1 replacement on `household.applicants[]` and is preferred when both are supplied: `first_name` → `household.applicants[primary].first_name`, `last_name` → `household.applicants[primary].last_name`, `email` → `household.applicants[primary].email`, `phone_number` → `household.applicants[primary].phone_number`. Each field that is still supplied here surfaces a `deprecated_field` entry in the response''s `warnings[]` array. The block remains accepted for backwards compatibility but may be removed at any time; migrate to the applicant-level fields.'
      properties:
        first_name:
          type: string
          deprecated: true
          description: DEPRECATED. Send as `household.applicants[primary].first_name` instead.
          maxLength: 50
        last_name:
          type: string
          deprecated: true
          description: DEPRECATED. Send as `household.applicants[primary].last_name` instead.
          maxLength: 50
        email:
          type: string
          deprecated: true
          description: DEPRECATED. Send as `household.applicants[primary].email` instead.
          maxLength: 50
        phone_number:
          type: string
          deprecated: true
          description: DEPRECATED. Send as `household.applicants[primary].phone_number` instead.
          maxLength: 50
    EnrollmentSessionEnrollment:
      type: object
      additionalProperties: false
      description: Accepts `hra`. Other enrollment subobjects (`special_enrollment_period`, `communication_preferences`) are not supported and are rejected with `400 invalid_request`.
      properties:
        hra:
          $ref: '#/components/schemas/EnrollmentSessionEnrollmentHra'
    EnrollmentSessionHousehold:
      type: object
      additionalProperties: false
      description: '`household_size` must be at least 1. Applicants can include at most one `primary` and one `spouse`.'
      properties:
        annual_income:
          type: number
          minimum: 0
        household_size:
          type: integer
          minimum: 1
        someone_has_employer_coverage:
          type: boolean
        applicants:
          type: array
          items:
            $ref: '#/components/schemas/EnrollmentSessionApplicant'
    EnrollmentSessionEnrollmentHra:
      type: object
      additionalProperties: false
      required:
      - amount
      description: When supplied, `amount` is required and must be greater than or equal to 0. `0` means the consumer declined available HRA funding; a positive value means funding was accepted. `frequency` is required when `amount > 0` and is omitted from the deep link when `amount == 0`.
      properties:
        amount:
          type: number
          minimum: 0
        frequency:
          type: string
          enum:
          - annually
          - monthly
          - quarterly
          - one_time
    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
    EnrollmentSessionApplicantIncomeSource:
      type: object
      additionalProperties: false
      required:
      - amount
      description: One income line attributed to this applicant. `amount` is required so the enrollment flow receives usable income information.
      properties:
        employer:
          type: string
          description: Employer or payer attributed to this income line.
          maxLength: 50
        amount:
          type: number
          description: Annual income from this source in dollars.
          minimum: 0
    EnrollmentSessionResponse:
      type: object
      additionalProperties: true
      required:
      - links
      description: Response envelope. Fields may be null when the request omits optional inputs (for example, `external_id`). Clients must tolerate new top-level keys appearing additively over time. `warnings` is emitted only when the request used a deprecated field; clients should treat its absence as 'no warnings'.
      properties:
        external_id:
          type: string
          nullable: true
          description: Echoed from the request when supplied; otherwise null.
        links:
          $ref: '#/components/schemas/EnrollmentSessionResponseLinks'
        warnings:
          type: array
          description: Non-fatal warnings about the request. Today only the legacy `client.*` contact block emits warnings — one entry per deprecated field that was supplied. The key is omitted entirely when there are no warnings. Clients that want to detect deprecations programmatically should branch on `warnings[].code`.
          items:
            $ref: '#/components/schemas/EnrollmentSessionResponseWarning'
    EnrollmentSessionContext:
      type: object
      additionalProperties: false
      required:
      - product
      - exchange
      - coverage_family
      - coverage_type
      - plan_year
      - flow
      - locale
      properties:
        product:
          type: string
          enum:
          - aca
        exchange:
          type: string
          enum:
          - on_exchange
        coverage_family:
          type: string
          enum:
          - medical
        coverage_type:
          type: string
          enum:
          - medical
        plan_year:
          type: integer
          minimum: 2020
          maximum: 2099
        flow:
          type: string
          enum:
          - agent_assisted
          - self_service
          description: Mapped to the deep link's `user_type` (`agent_assisted` -> `agent`, `self_service` -> `consumer`).
        locale:
          type: string
          enum:
          - en-US
          - es-MX
          description: '`es-MX` enables the Spanish flow via the deep link''s `ljs` parameter.'
    EnrollmentSessionRequest:
      type: object
      additionalProperties: false
      required:
      - context
      description: POST /v1/enrollment-sessions request body. Unsupported fields anywhere in the body are rejected with `400 invalid_request`. In `self_service`, supply at least one of `location.state` or top-level `plan_id`. In `agent_assisted`, `location.state` is required and `plan_id` is not accepted.
      properties:
        external_id:
          type: string
          description: Partner-supplied identifier echoed in the response and used for CRM correlation. Strongly recommended; must not contain PII.
        plan_id:
          type: string
          description: Plan ID (HIOS ID). Available only for the `self_service` flow, where it identifies the plan for the generated apply link. Invalid for `agent_assisted` — requests carrying `plan_id` with `context.flow` set to `agent_assisted` are rejected with `400 invalid_request`.
        notes:
          type: string
          description: Free-form note for the assisting agent. Used only in the agent-assisted enrollment flow; ignored on self-service deep links. Capped at 500 characters; longer values are rejected with `400 invalid_request`.
          maxLength: 500
        providers:
          type: array
          description: Provider identifiers (NPI strings) the household cares about. Used by the agent-assisted enrollment flow and added to the self-service `shopping_url` as a network filter (shop only; not added to `client_apply_url`).
          items:
            type: string
            description: Ten-digit National Provider Identifier (NPI).
            pattern: ^[0-9]{10}$
        context:
          $ref: '#/components/schemas/EnrollmentSessionContext'
        client:
          $ref: '#/components/schemas/EnrollmentSessionClient'
        location:
          $ref: '#/components/schemas/EnrollmentSessionLocation'
        household:
          $ref: '#/components/schemas/EnrollmentSessionHousehold'
        enrollment:
          $ref: '#/components/schemas/EnrollmentSessionEnrollment'
        campaign:
          $ref: '#/components/schemas/EnrollmentSessionCampaign'
    EnrollmentSessionResponseWarning:
      type: object
      additionalProperties: true
      required:
      - code
      - field
      - message
      description: One non-fatal warning about a single request field. New `code` values may be introduced additively over time; clients should treat unknown codes as 'log and continue'.
      properties:
        code:
          type: string
          description: Stable, machine-readable warning category. Currently only `deprecated_field` is emitted (when the request uses a `client.*` contact field that has been replaced by a `household.applicants[]` equivalent).
        field:
          type: string
          description: Dotted request path of the field this warning is about (for example, `client.email`).
        message:
          type: string
          description: Human-readable explanation. For deprecation warnings, includes the suggested replacement field path.
    EnrollmentSessionCampaign:
      type: object
      additionalProperties: false
      description: 'Marketing attribution. Only accepted when `context.flow` is `self_service`; sending any field with `flow: "agent_assisted"` is rejected with `400 invalid_request`.'
      properties:
        cid:
          type: string
        utm_source:
          type: string
        utm_medium:
          type: string
        utm_campaign:
          type: string
        utm_term:
          type: string
        utm_content:
          type: string
        display_phone_number:
          type: string
          pattern: ^\D?(\d{3})\D?\D?(\d{3})\D?(\d{4})$
          description: Phone number HealthSherpa renders in the page header. Must be a 10-digit US phone number (any of `8005551234`, `800-555-1234`, `800.555.1234`, `(800) 555-1234` are accepted); `+1`-prefixed and non-10-digit values are rejected with `400 invalid_request`. Forwarded to the deep link's `call` parameter unchanged.
    EnrollmentSessionApplicantIchra:
      type: object
      additionalProperties: false
      properties:
        offered:
          type: boolean
        offered_cafeteria:
          type: boolean
        employee_amount:
          type: number
          minimum: 0
        family_amount:
          type: number
          minimum: 0
    EnrollmentSessionApplicantPrescription:
      type: object
      additionalProperties: false
      description: Medication identification used for Rx-matched plan ranking. At least one of `id` or `rx_norm_identifier` must be supplied; entries with neither are rejected with `400 invalid_request`.
      properties:
        id:
          type: string
          description: HealthSherpa medication catalog identifier.
        duration:
          type: integer
          description: Days-of-supply per fill (informational; not used to filter plans).
          minimum: 0
        rx_norm_identifier:
          type: string
          description: RxNorm CUI for the medication.
    EnrollmentSessionApplicant:
      type: object
      additionalProperties: false
      required:
      - relationship
      description: '`date_of_birth` and `age` are mutually exclusive on the same applicant, and `date_of_birth` must not be in the future. `sex` accepts `male` and `female`. `first_name` / `last_name` are accepted on every applicant so non-primary members can carry their own identity for the agent-assisted enrollment flow. `email` and `phone_number` are accepted only on the applicant whose `relationship` is `primary` — supplying them on a spouse or dependent is rejected.'
      properties:
        relationship:
          type: string
          enum:
          - primary
          - spouse
          - dependent
        first_name:
          type: string
          description: Given name. Used by the agent-assisted enrollment flow only; ignored on self-service deep links. Helps prefill household member names in the flow.
          maxLength: 50
        last_name:
          type: string
          description: Family name. Used by the agent-assisted enrollment flow only; ignored on self-service deep links. Helps prefill household member names in the flow.
          maxLength: 50
        email:
          type: string
          description: Email for the primary applicant. Used in the agent-assisted enrollment flow and lead lookup. Replaces the deprecated `client.email`; only accepted when `relationship` is `primary`.
          pattern: ^[^@\s]+@[^@\s]+\.[^@\s]+$
          maxLength: 50
        phone_number:
          type: string
          description: Phone number for the primary applicant. Used in the agent-assisted enrollment flow. Replaces the deprecated `client.phone_number`; only accepted when `relationship` is `primary`. Permissive shape — digits with optional spaces, dots, parentheses, hyphens, and a leading `+` (7–50 characters); HealthSherpa normalizes the phone number during the flow.
          pattern: ^[0-9\s().+\-]{7,50}$
        date_of_birth:
          type: string
          format: date
        age:
          type: integer
          minimum: 0
          maximum: 130
        sex:
          type: string
          enum:
          - male
          - female
        uses_tobacco:
          type: boolean
        pregnant:
          type: boolean
        parent_caretaker:
          type: boolean
        rejected_by_medicaid_or_chip:
          type: boolean
        unemployment:
          type: boolean
        has_existing_coverage:
          type: boolean
        ichra:
          $ref: '#/components/schemas/EnrollmentSessionApplicantIchra'
        prescriptions:
          type: array
          description: Medications this applicant takes. Used by the agent-assisted enrollment flow only; ignored on self-service deep links. Nested under the applicant rather than carrying an `applicant_index` linkage field.
          items:
            $ref: '#/components/schemas/EnrollmentSessionApplicantPrescription'
        income_sources:
          type: array
          description: Income lines attributed to this applicant. Used by the agent-assisted enrollment flow only; ignored on self-service deep links. When any applicant supplies `income_sources`, the per-applicant entries replace the household-level `annual_income` aggregation for the agent-assisted flow; `annual_income` continues to drive the self-service deep link regardless.
          items:
            $ref: '#/components/schemas/EnrollmentSessionApplicantIncomeSource'
  responses:
    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.
    IdempotencyInProgress:
      description: A previous request with the same `Idempotency-Key` is still being processed by the API. The partner should wait briefly and retry. The response is not produced by the upstream service — the in-flight request from the first call will succeed or fail on its own.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: idempotency_in_progress
              message: A request with this Idempotency-Key is already being processed. Retry once it completes.
    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.
    IdempotencyMismatch:
      description: The `Idempotency-Key` has been used before within the 24-hour retention window, but the current request body is not byte-for-byte identical to the original. To resolve, either resubmit the exact original payload or generate a fresh `Idempotency-Key` for the new request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            err

# --- truncated at 32 KB (32 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/healthsherpa/refs/heads/main/openapi/healthsherpa-enrollment-sessions-api-openapi.yml