Candid Health · OpenAPI Overlay 1.0.0

API Evangelist enhancements for Candid Health

10 actions 10 updates update extends openapi/_original/candid-health-openapi.yml
Generated by API Evangelist Written by API Evangelist tooling for Candid Health's API. It is a proposal applied on top of the contract, not a document Candid Health publishes.
View Overlay File View on GitHub Overlay Specification

What the actions change

x-apievangelist-providerx-apievangelist-enrichedx-provider-namex-provider-websitex-documentationx-published-specx-authenticationx-rate-limit

Targets 3

$.info
$.servers
$.components.securitySchemes.OAuthScheme

OpenAPI Overlay

Raw ↑
overlay: 1.0.0
info:
  title: API Evangelist enhancements for Candid Health
  version: 1.0.0
extends: openapi/_original/candid-health-openapi.yml
x-generated: '2026-08-15'
x-method: generated
x-source: >-
  Derived from the artifacts in this repo — conventions/, authentication/,
  rate-limits/, errors/, lifecycle/, sandbox/, conformance/ — each of which was
  searched from Candid's own documentation. This overlay adds the runtime semantics
  Candid documents in prose but does not express in its OpenAPI. It never mutates
  the harvested spec.
actions:

  - target: $.info
    description: >-
      Name the document and its owner. The published spec ships info.title
      "API Reference" with no contact, licence or terms, which makes it
      unattributable once it is downloaded away from docs.joincandidhealth.com.
    update:
      x-apievangelist-provider: candid-health
      x-apievangelist-enriched: '2026-08-15'
      x-provider-name: Candid Health
      x-provider-website: https://candidhealth.com/
      x-documentation: https://docs.joincandidhealth.com/
      x-published-spec:
        json: https://docs.joincandidhealth.com/openapi.json
        yaml: https://docs.joincandidhealth.com/openapi.yaml
        api_catalog: https://docs.joincandidhealth.com/.well-known/api-catalog

  - target: $.info
    description: >-
      Record the authentication mechanism the spec does not describe. The spec declares
      OAuthScheme as plain `http bearer`, so nothing in the document tells a client where
      the token comes from or how long it lives.
    update:
      x-authentication:
        grant: client_credentials
        token_endpoint: https://api.joincandidhealth.com/api/auth/v2/token
        token_format: JWT (Auth0-issued)
        token_lifetime_hours: 5
        public_key: https://candidhealth.auth0.com/pem
        scopes: none
        credentials_are_environment_scoped: true
        token_reuse_required: true
        note: >-
          Minting a token per request triggers HTTP 429 on the token endpoint itself.
          Cache and reuse the token for its full lifetime.
        detail: authentication/candid-health-authentication.yml

  - target: $.info
    description: Publish the rate limit, which appears nowhere in the spec.
    update:
      x-rate-limit:
        scope: per-ip
        limit: 1000
        window_seconds: 10
        strategy: rolling-window
        exhaustion_status: 429
        response_headers: none
        retry_after: not sent
        note: >-
          Per-IP rather than per-key: every tenant behind one NAT egress shares a bucket,
          and no RateLimit-* header is returned, so remaining budget is unobservable.
        detail: rate-limits/candid-health-rate-limits.yml

  - target: $.info
    description: >-
      Publish the error envelope. Every 4xx/5xx response in the spec is typed, but the
      shared branching rule — read errorName, not the status code — is documented only in prose.
    update:
      x-error-envelope:
        format: vendor-discriminated-envelope
        media_type: application/json
        rfc9457: false
        discriminator: errorName
        shape: '{ errorName: <single-value enum string>, content: <typed object|array> }'
        note: >-
          Branch on errorName. HTTP 404 alone carries three distinct named errors across
          the 251 operations.
        catalog: errors/candid-health-problem-types.yml

  - target: $.info
    description: >-
      State plainly that there is no idempotency contract. This is the single most
      consequential absence for an automated claims integration and the spec is silent on it.
    update:
      x-idempotency:
        supported: false
        header: null
        substitute: client-supplied external_id / charge_external_id on create
        duplicate_behaviour: >-
          HTTP 409 (EncounterExternalIdUniquenessError, ChargeExternalIdConflictError,
          EntityConflictError) — the original response is NOT replayed.
        risk: >-
          A POST /api/encounters/v4 that times out mid-flight can create a second claim.
          Always set external_id and treat 409 as "already exists", then read back.
        detail: conventions/candid-health-conventions.yml

  - target: $.info
    description: Publish the pagination contract as machine-readable metadata.
    update:
      x-pagination:
        style: cursor
        request_params: [page_token, limit]
        response_envelope: ResourcePage
        response_fields: [items, next_page_token, prev_page_token]
        bidirectional: true
        incremental_sync:
          endpoints: '*/updates/scan'
          param: since

  - target: $.info
    description: >-
      Publish the lifecycle model. The spec carries `deprecated: true` on zero of its 251
      operations even though Candid documents a three-state endpoint lifecycle in its docs,
      so a machine reading the spec cannot tell a deprecated endpoint from a supported one.
    update:
      x-lifecycle:
        versioning: path-segment
        parallel_versions_live: true
        states: [beta, available, deprecated]
        state_expressed_in_spec: false
        sunset_header: false
        deprecation_header: false
        notice_channel: email opt-in list
        policy: https://docs.joincandidhealth.com/api-principles/breaking-changes
        status_page: https://status.joincandidhealth.com
        detail: lifecycle/candid-health-lifecycle.yml

  - target: $.servers
    description: >-
      Annotate the server list. The published spec mixes two host families, four
      environment names and two localhost entries with no machine-readable indication of
      which is production or which service family answers on which host.
    update:
      x-server-guidance:
        production:
          core: https://api.joincandidhealth.com
          pre_encounter: https://pre-api.joincandidhealth.com
        sandbox:
          core: https://api-staging.joincandidhealth.com
          pre_encounter: https://pre-api-staging.joincandidhealth.com
          phi_allowed: false
        host_split: >-
          Pre-encounter services (patients, coverages, appointments, eligibility-checks,
          images, lists, notes, tags) answer on pre-api*; every other service answers on api*.
        undocumented_entries:
          - https://sandbox-api.joincandidhealth.com
          - https://sandbox-pre-api.joincandidhealth.com
          - https://staging-api.joincandidhealth.com
          - https://staging-pre-api.joincandidhealth.com
          - http://localhost:4000
          - http://localhost:5050
        note: >-
          Only the api / api-staging and pre-api / pre-api-staging pairs are documented on
          the environments page. The remaining six entries are internal generator
          environments that leaked into the public document; two of them are non-routable.
        detail: sandbox/candid-health-sandbox.yml

  - target: $.components.securitySchemes.OAuthScheme
    description: >-
      Keep the declared type intact (an overlay must not break the contract) but attach the
      OAuth facts, so a reader of the scheme can find the token endpoint.
    update:
      x-oauth2-equivalent:
        flow: clientCredentials
        tokenUrl: https://api.joincandidhealth.com/api/auth/v2/token
        scopes: {}
        note: >-
          Declared as `http bearer` in the published spec. The grant really is OAuth 2.0
          client credentials (RFC 6749 §4.4); declaring it as an oauth2 securityScheme with
          a clientCredentials flow would let generated clients acquire tokens automatically.

  - target: $.info
    description: Record the standards posture measured in conformance/.
    update:
      x-conformance:
        healthcare: [X12 837, X12 835, X12 270/271, NPI, CPT/HCPCS, ICD-10]
        fhir: false
        compliance: [SOC 2 Type 2, SOC 2 Type 1, SOC 1 Type 1, HIPAA BAA]
        rfc9727_api_catalog: true
        rfc9457_problem_details: false
        rfc8594_sunset: false
        rfc9116_security_txt: false
        webhooks: false
        detail: conformance/candid-health-conformance.yml