> ## Documentation Index
> Fetch the complete documentation index at: https://docs.healos.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Going to production

> A checklist to work through before your integration touches real patients

Work through this list before you point an integration at the organization
that holds your real patients. Each item links to the page with the details.

> [!WARNING]
>
> Use the API with real patient data only under a signed **business associate
> agreement (BAA)** with HealOS. Contact your HealOS account team to put one in
> place before you go live.

## 1. Keys

* [ ] **One key per environment.** HealOS has no sandbox, so your test
  environment uses a key from a separate [test organization](https://docs.healos.ai/test-mode.md) and
  production uses a key from your real organization. Never share one key
  between them.
* [ ] **Check the organization on startup.** Call
  [`GET /me`](https://docs.healos.ai/authentication#check-your-key) when your service starts and
  stop if `data.org.name` isn't the organization you expect.
* [ ] **Keep keys on your server.** Store them in a secrets manager or
  environment variables. Never put a key in source code, a browser or mobile
  app, logs, tickets or chat. See [Store keys safely](https://docs.healos.ai/security.md#store-keys-safely).
* [ ] **Call `https://` only.** A request to `http://` sends the key
  unencrypted before it is redirected.
* [ ] **Create the key from an admin who will stay.** A key works only while
  the admin who created it is still an admin of the organization. If that
  person leaves or is made a non-admin, the key returns `401`.

## 2. Scopes, expiry and rotation

* [ ] **Least privilege.** Give the key only the [scopes](https://docs.healos.ai/authentication.md#scopes)
  the integration uses. A job that reads notes needs `notes:read` and nothing
  else. Don't use `*` (full access) in production.
* [ ] **Set an expiry** and track it: `GET /me` returns `data.key.expires_at`.
  Alert well before that date. An expired key returns `401`.
* [ ] **Practice a rotation** before you need one: create the new key, deploy
  it, then revoke the old one. See [Rotate a key](https://docs.healos.ai/security.md#rotate-a-key).
* [ ] **Know how to revoke.** If a key leaks, revoke it at once in
  **Account Settings → API Keys** and tell
  [support@healos.ai](mailto:support@healos.ai). See
  [If a key leaks](https://docs.healos.ai/security.md#if-a-key-leaks).

## 3. Rate limits

* [ ] **Stay under the limits.** About 60 requests a minute per key, about 10
  eligibility checks a minute per key, and one prior-auth status check every
  10 minutes per organization. See [Rate limiting](https://docs.healos.ai/rate-limiting.md).
* [ ] **Handle `429`.** Wait for the number of seconds in the `Retry-After`
  header, then retry with exponential backoff and some random jitter. Don't
  retry in a tight loop.
* [ ] **Watch `X-RateLimit-Remaining`** on every response and slow down
  before it reaches 0.

```python theme={null}
import random
import time

import requests


def get_with_backoff(http, url, max_attempts=5, **kwargs):
    """GET with backoff on 429. Use it for reads, not for paid or create calls."""
    for attempt in range(max_attempts):
        res = http.get(url, timeout=30, **kwargs)
        if res.status_code != 429:
            return res
        wait = int(res.headers.get("Retry-After", 2 ** attempt))
        time.sleep(wait + random.uniform(0, 1))
    return res
```

## 4. Safe creates with `external_id`

* [ ] **Send your own id** as `external_id` when you create patients,
  appointments and documents. It is unique in the organization.
* [ ] **Treat `409` as "already done".** Creating the same `external_id`
  again returns `409` with `existing.id`; use that record instead of creating
  another.
* [ ] **Look records up by your id** with `?external_id=` instead of storing
  every HealOS id. See [External IDs](https://docs.healos.ai/making-requests.md#external-ids).

## 5. Paid and AI calls: don't retry blindly

Most `POST` requests are not idempotent: a retry after a timeout can do the
work twice. These cost money or plan usage on every call:

| Call | Cost of each call | Safe retry |
| - | - | - |
| `POST /benefits/eligibility-checks` | A **billable** payer request | Retry only `502`, `503` or `504`, after a wait. After a timeout or `500`, [list recent checks](https://docs.healos.ai/api-reference/benefits/list-eligibility-checks.md) first |
| `POST /notes/from-text`, `POST /notes/from-audio` | One **Scribe session** from your plan | Don't retry after `202`. After a timeout, wait a few minutes and list the patient's notes (`GET /notes?patient_id=`) before sending again |
| `POST /patients/{patientId}/notes/from-documents` | AI note generation | Don't retry after `202` |
| `POST /sessions/{sessionId}/notes/regenerate` | AI note generation | Send an `Idempotency-Key` header; a retry with the same key for the same session doesn't start a second run |

* [ ] **Handle `402`.** Note generation returns `402` when the organization
  has no Scribe sessions left. Retrying won't help; alert a person.
* [ ] **Check the Safety box** on each endpoint's page in the
  [API Reference](https://docs.healos.ai/api-reference.md) before you add a retry. See
  [Retrying safely](https://docs.healos.ai/errors.md#retrying-safely).

## 6. Follow `202` jobs instead of re-posting

Note generation answers `202` with a `session_id` and `status: "queued"`. The
note follows within about a minute.

* [ ] **Store the `session_id`** from the `202` and follow it. Never send the
  request again to "check" on it.
* [ ] **Prefer webhooks:** `NOTE_CREATED`, `NOTE_REGENERATED` and, for
  uploads, `DOCUMENT_STATUS_CHANGED`. Protect your endpoint with HTTPS and a
  secret header. See [Webhooks](https://docs.healos.ai/webhooks.md).
* [ ] **Or poll gently:** `GET /sessions/{sessionId}/notes` every 10 seconds,
  and a document's `status` every few seconds, with a time limit after which
  you alert a person.

## 7. Logs and PHI

* [ ] **Log ids, not content.** Log HealOS ids, your `external_id` values,
  `session_id`, the endpoint and the HTTP status. Never log names, dates of
  birth, note text, transcripts or eligibility results.
* [ ] **Never log the key.** To tell keys apart in logs, use
  `data.key.prefix` from `GET /me`.
* [ ] **Store responses as PHI** with the same protection as the rest of your
  patient data. See [Handling PHI from the API](https://docs.healos.ai/security.md#handling-phi-from-the-api).
* [ ] **Keep keys and patient data out of AI tools,** including the docs
  search and assistant.

## 8. Before you switch over

* [ ] Your BAA with HealOS is signed.
* [ ] Your client ignores unknown response fields and enum values, so
  additive changes don't break it. See [Versioning and deprecation](https://docs.healos.ai/versioning.md).
* [ ] You branch on the HTTP status and `code`, not on the `error` text. See
  [Error catalog](https://docs.healos.ai/errors.md).
* [ ] Every flow has passed end to end in your test organization with made-up
  data.
* [ ] Someone on your team follows the [Changelog](https://docs.healos.ai/changelog.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.