# Docs for AI agents Source: https://docs.healos.ai/ai-agents Machine-readable docs for coding assistants, and the HealOS MCP server for AI agents These docs are published in forms that AI coding assistants and agents can read directly. | What | Where | Use it for | | - | - | - | | `llms.txt` | [docs.healos.ai/llms.txt](https://docs.healos.ai/llms.txt) | An index of every page with a one-line summary | | `llms-full.txt` | [docs.healos.ai/llms-full.txt](https://docs.healos.ai/llms-full.txt) | Every page in one file | | Markdown pages | Add `.md` to any page URL, for example [docs.healos.ai/quickstart.md](https://docs.healos.ai/quickstart.md) | One page as plain Markdown | | OpenAPI spec | The **Copy page** menu on any [API Reference](/api-reference) page | Generating a typed client | | Docs search (MCP) | `https://docs.healos.ai/mcp` | Letting an MCP client search these docs | Every page also has a **Copy page** menu to copy it as Markdown or open it in ChatGPT or Claude. > [!NOTE] > > The docs MCP server searches **these docs**. It does not call the HealOS API > and never sees your data. ## Use HealOS from an AI agent (MCP) `healos mcp` runs an [MCP](https://modelcontextprotocol.io) server on your computer, so Claude Desktop, Claude Code, Cursor and other MCP clients can read your HealOS data through the HealOS API. It is part of the [HealOS CLI](/cli) and uses the key you signed in with, with that key's scopes, rate limits and audit log. > [!NOTE] > > `healos mcp` ships in the next release of `@healos/cli` on npm. The > configs below work once that release is out; check with > `npx @healos/cli@latest mcp --help`. ### Set it up 1. Sign in once, so the key is stored in your Keychain (or a file only you can read) instead of in the agent's config: ```bash theme={null} npx @healos/cli login ``` The key is read-only unless you ask for more scopes. See [Sign in](/cli#sign-in). 2. Add the server to your client: in Claude Desktop, **Settings → Developer → Edit Config** (`claude_desktop_config.json`); in Cursor, `~/.cursor/mcp.json` (or `.cursor/mcp.json` in a project). ```json Claude Desktop theme={null} { "mcpServers": { "healos": { "command": "npx", "args": ["-y", "@healos/cli", "mcp"] } } } ``` ```json Cursor theme={null} { "mcpServers": { "healos": { "command": "npx", "args": ["-y", "@healos/cli", "mcp"] } } } ``` ```bash Claude Code theme={null} claude mcp add healos -- npx -y @healos/cli mcp ``` Add `"--profile", ""` to `args` to use another saved profile. Pin a version you have tested (`@healos/cli@`) if you don't want updates picked up automatically. ### What the agent can do By default every tool is **read-only**: patients, patient documents (status only), appointments, providers, notes, sessions, templates, eligibility checks, payer search, prior-auth requests, events and workflows, the EHR action catalog and connections, and the key itself (`whoami`). A tool only appears when the key has its scope. To let the agent change data, add flags to `args`: | Flag | Adds | Also needs | | - | - | - | | `--allow-writes` | `create_patient`, `update_patient`, `create_appointment`, `update_appointment`, `assign_session_patient` | The key's write scope | | `--allow-writes --allow-paid` | `run_eligibility_check`, `generate_note_from_text`, `regenerate_session_note`, `generate_note_from_documents`, `extract_document_text`, `check_prior_auth_status` | The key's write scope, and `confirm: true` on every call | Paid tools cost money or reach an outside system: eligibility checks are billable payer requests, note generation uses your Scribe sessions, and prior-auth status checks call Availity. There are **no delete tools**. Uploads (documents, audio) and the bulk notes export are not available over MCP either; use the CLI or the API for those. ### Safety model * **Read-only unless you opt in.** Writes need `--allow-writes`, paid tools also need `--allow-paid`, and both need the key's scope. Use a key with only the scopes the agent needs. * **Results are data, not instructions.** Notes, transcripts and patient documents can contain text written by anyone. Every result is wrapped in `` tags and labeled as untrusted data, and the server tells the agent never to follow instructions found inside it. Your client's approval prompt for each tool call is still your best control: keep it on for write and paid tools. * **Bounded results.** List tools return at most 25 items per call (10 by default) and every result is capped at 50,000 characters. When a result is cut, it says so and how to get the rest. * **PHI is not redacted.** Results contain real patient information. Only API keys (shown as `hlsk_[redacted]`) and document file links are replaced, with a visible marker. Use the server only with AI tools your organization has approved for PHI (for example, under a BAA), and only on your own computer. * **Your key stays out of the conversation.** It is never in a tool result or error, and it is only sent over HTTPS to HealOS. ## Instructions for agents If you are an AI agent writing code against the HealOS External API: 1. Read the [Quickstart](/quickstart), then the endpoint pages you need. Each endpoint page starts with its **scope**, **rate limit**, **cost** and a **Safety** box (writes data, safe to retry, outside systems, dry run). 2. Never ask a user to paste an API key or patient data into a chat. Read the key from the `HEALOS_API_KEY` environment variable. 3. Test against a [test organization](/test-mode) with made-up data. There is no sandbox. 4. Don't call billable or outside-system endpoints in loops or retries without a person's approval: eligibility checks are paid payer requests, and note generation uses the organization's Scribe sessions. 5. Branch on HTTP status and `code`, not the `error` text. See the [Error catalog](/errors). > [!WARNING] > > Never paste API keys or real patient information into docs search, the docs > assistant or any AI tool. Use placeholders such as `hlsk_...` and made-up > patients. # API Reference Source: https://docs.healos.ai/api-reference Every endpoint, with its scope, limits, cost, Safety box, parameters, examples and responses Every endpoint has its own page in the sidebar. Each page has the same layout: 1. **Scope, rate limit and cost.** The [scope](/authentication#scopes) the key needs, the [rate limit](/rate-limiting) that applies, and whether the call costs money (eligibility checks are billable; note generation uses AI and, from text or audio, a Scribe session). 2. **Safety box.** Whether the call writes data, whether it is safe to retry, whether it contacts an outside system (an EHR, a payer or a payer portal) and whether a dry run exists. Read this before calling a write in a retry loop. 3. **Parameters and body**, generated from the OpenAPI spec. 4. **Request examples** in cURL, JavaScript and Python, and a "Try it" playground. 5. **Responses** for each status code, with their schemas. > [!WARNING] > > The "Try it" playground sends **real requests** with the key you enter, > and relays them through Mintlify, the third party that hosts these docs. > Use only a key from a [test organization](/test-mode) and made-up data, > never a production key or real patient information. ## Basics * **Base URL**: `https://api.healos.ai/ext-api/v1` * **Auth**: send your key as `X-API-Key: hlsk_...` on every request. See [Authentication](/authentication). * **Shape**: success responses are `{ "data": ... }`; list endpoints add a `meta` block. Errors are `{ "error": ... }`. See [Making Requests](/making-requests) and the [Error catalog](/errors). ## Resources | Resource | Description | Guide | | - | - | - | | **Patients** | Create, read, update, and delete patient records | [Making requests](/making-requests) | | **Documents** | Upload, list, and delete patient documents | [Webhooks: document upload flow](/webhooks#document-upload-flow) | | **Appointments** | Manage appointments with scheduling, recurrence, and status | [Appointments for a date range](/recipes/appointments-date-range) | | **Providers** | List the clinicians in your organization | [Authentication](/authentication) | | **Notes and sessions** | Generate, read, regenerate and bulk-export clinical notes | [Clinical notes](/clinical-notes) | | **Templates** | List the note templates you can generate with, and read one with its section instructions | [Templates](/templates) | | **Settings** | Read the key owner's Scribe note settings | [Templates](/templates) | | **Benefits** | Run eligibility checks and search payers | [Benefit verification](/benefits) | | **Prior auth** | Follow prior-auth requests and decisions | [Prior authorization](/prior-auth) | | **Receptionist** | Read AI Receptionist calls (summaries, outcomes, transcripts, extracted details and recordings) and manage the inbox tasks | [Receptionist call transcripts](/recipes/receptionist-call-transcripts) | | **Fax** | Read received faxes (extracted fields and the file) and sent faxes with their delivery status (read-only) | [Authentication](/authentication) | | **Webhooks** | Register and manage webhooks for note and document events | [Webhooks](/webhooks) | | **EHR** | Browse the EHR action catalog (read-only; actions can't be run through the API yet) and see which EHRs you have connected | [EHR actions](/ehr-actions/overview) | | **Account** | Check which organization and scopes a key has | [Authentication](/authentication#check-your-key) | # Describe the calling API key Source: https://docs.healos.ai/api-reference/account/describe-the-calling-api-key openapi/ext-api-v1.json GET /me The user and organization the key belongs to, its scopes and when it expires. Needs only a valid key. | Requirement | Detail | | - | - | | **Scope** | None. Any valid key can call it. | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Authentication](/authentication). Errors: [Error catalog](/errors). # Create an appointment Source: https://docs.healos.ai/api-reference/appointments/create-an-appointment openapi/ext-api-v1.json POST /appointments | Requirement | Detail | | - | - | | **Scope** | `appointments:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!NOTE] > > **Safety** > > * **Writes data:** Yes. Creates an appointment in HealOS. It is not sent to your EHR. > * **Safe to retry:** Only with `external_id`: a repeat with the same `external_id` returns `409` with the existing record instead of a duplicate. Without it, a retry creates a second record. > * **Contacts an outside system:** None > * **Dry run:** Not available. Guide: [Making requests](/making-requests). Errors: [Error catalog](/errors). # Delete an appointment Source: https://docs.healos.ai/api-reference/appointments/delete-an-appointment openapi/ext-api-v1.json DELETE /appointments/{appointmentId} | Requirement | Detail | | - | - | | **Scope** | `appointments:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!WARNING] > > **Safety** > > * **Writes data:** Yes. **Permanently** deletes the appointment. To keep a record, set `status` to `CANCELLED` with `PATCH` instead. > * **Safe to retry:** Yes. A repeat returns `404`. > * **Contacts an outside system:** None > * **Dry run:** Not available. Guide: [Making requests](/making-requests). Errors: [Error catalog](/errors). # Get appointment by ID Source: https://docs.healos.ai/api-reference/appointments/get-appointment-by-id openapi/ext-api-v1.json GET /appointments/{appointmentId} | Requirement | Detail | | - | - | | **Scope** | `appointments:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Making requests](/making-requests). Errors: [Error catalog](/errors). # List appointments Source: https://docs.healos.ai/api-reference/appointments/list-appointments openapi/ext-api-v1.json GET /appointments Paginated list of appointments. Pass `external_id=` to look up a single appointment by caller-supplied external_id (returns 404 if not found). | Requirement | Detail | | - | - | | **Scope** | `appointments:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Filter by one day with `date=YYYY-MM-DD` (a UTC calendar day). The `start_date` and `end_date` parameters are accepted but not applied today, so they return every appointment. To cover a range, query one day at a time. See [Appointments for a date range](/recipes/appointments-date-range). Guide: [Recipe: appointments for a date range](/recipes/appointments-date-range). Errors: [Error catalog](/errors). # Update an appointment Source: https://docs.healos.ai/api-reference/appointments/update-an-appointment openapi/ext-api-v1.json PATCH /appointments/{appointmentId} | Requirement | Detail | | - | - | | **Scope** | `appointments:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!NOTE] > > **Safety** > > * **Writes data:** Yes. Updates the fields you send. Changes stay in HealOS and are not sent to your EHR. > * **Safe to retry:** Yes. Sending the same body again gives the same result. > * **Contacts an outside system:** None > * **Dry run:** Not available. Guide: [Making requests](/making-requests). Errors: [Error catalog](/errors). # List audit events Source: https://docs.healos.ai/api-reference/audit/list-audit-events openapi/ext-api-v1.json GET /audit-events Your organization's API audit trail, newest first: one event per authenticated request (one per record when a request names two), with the key, route, record ids and status. Never request or response content. Events are kept for 90 days. | Requirement | Detail | | - | - | | **Scope** | `audit:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None. Reads your organization's API audit log in HealOS. > * **Dry run:** Not needed (read-only). Lists your organization's External API audit log, newest first: which API key called which route, on which record id, with what status. Rows hold ids and route templates only (`/patients/{patientId}`), never request bodies, query values or record contents. Every row belongs to the calling key's own organization. Narrow the list with `key_id`, `resource_type` and `resource_id`, or a `since` / `until` window. For the next (older) page, pass the previous page's `meta.next_cursor` as `cursor`. Rows can take a few seconds to appear: HealOS writes them in batches. From the CLI: `healos audit list`. Errors: [Error catalog](/errors). # Get an eligibility check Source: https://docs.healos.ai/api-reference/benefits/get-an-eligibility-check openapi/ext-api-v1.json GET /benefits/eligibility-checks/{checkId} One eligibility check with the payer's full normalized response. Requires the `benefits:read` scope. | Requirement | Detail | | - | - | | **Scope** | `benefits:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Benefit verification](/benefits). Errors: [Error catalog](/errors). # List eligibility checks Source: https://docs.healos.ai/api-reference/benefits/list-eligibility-checks openapi/ext-api-v1.json GET /benefits/eligibility-checks Your organization's eligibility checks, most recent first, including those run from the HealOS dashboard. Pass `patient_id` to list one patient's checks. Requires the `benefits:read` scope. | Requirement | Detail | | - | - | | **Scope** | `benefits:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Benefit verification](/benefits). Errors: [Error catalog](/errors). # Run an eligibility check Source: https://docs.healos.ai/api-reference/benefits/run-an-eligibility-check openapi/ext-api-v1.json POST /benefits/eligibility-checks Runs a real-time insurance eligibility and benefits check (X12 270/271) with the payer and stores the result in your organization's benefits history, where it also shows in the HealOS dashboard. Either pass `patient_id` for a patient already in HealOS, or pass `member_id`, `first_name`, `last_name` and `date_of_birth`. Requires the `benefits:write` scope. Each check is a billable payer request, so this endpoint is limited to 10 requests per minute per API key on top of the global limit, and by default to 1000 checks per organization per UTC day (`429` with `code: daily_cap_reached`). Responses usually take a few seconds; allow up to a minute when the payer is slow. | Requirement | Detail | | - | - | | **Scope** | `benefits:write` | | **Rate limit** | About 10 requests per minute per API key, on top of the shared limit of about 60 per minute. Approximate: don't rely on it to cap spend. | | **Cost** | **Billable.** Each request is a paid payer request. | > [!WARNING] > > **Safety** > > * **Writes data:** Yes. Saves the check and the payer's answer to your organization's benefits history. > * **Safe to retry:** No. Every request is a new, billable payer request. Retry only after a `502`, `503` or `504`, and wait first. > * **Contacts an outside system:** **Yes.** Sends the member's details to the payer (an X12 270/271 request through our clearinghouse). > * **Dry run:** Not available. Guide: [Recipe: run an eligibility check](/recipes/eligibility-check). Errors: [Error catalog](/errors). # Search payers Source: https://docs.healos.ai/api-reference/benefits/search-payers openapi/ext-api-v1.json GET /benefits/payers/search Find the `payer_id` to use on an eligibility check. Matches payer names and ids; queries shorter than 2 characters return an empty list. Requires the `benefits:read` scope. | Requirement | Detail | | - | - | | **Scope** | `benefits:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** Payer directory lookup only. No patient data is sent. > * **Dry run:** Not needed (read-only). Guide: [Benefit verification](/benefits). Errors: [Error catalog](/errors). # Delete a document Source: https://docs.healos.ai/api-reference/documents/delete-a-document openapi/ext-api-v1.json DELETE /patients/{patientId}/documents/{documentId} Delete a specific document for a patient. | Requirement | Detail | | - | - | | **Scope** | `documents:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!WARNING] > > **Safety** > > * **Writes data:** Yes. Removes the document from the patient. This cannot be undone through the API. > * **Safe to retry:** Yes. A repeat returns `404`. > * **Contacts an outside system:** None > * **Dry run:** Not available. Guide: [Making requests](/making-requests). Errors: [Error catalog](/errors). # Extract or retry document text extraction Source: https://docs.healos.ai/api-reference/documents/extract-or-retry-document-text-extraction openapi/ext-api-v1.json POST /patients/{patientId}/documents/{documentId}/extract Starts or retries text extraction for a patient document and returns the latest extraction status. On reaching a terminal state a `DOCUMENT_STATUS_CHANGED` webhook fires (if registered) — see the upload endpoint. Each call on a document that is not yet `completed` counts against your organization's daily document extraction limit, if one is set (per UTC day, shared with uploads); over it this endpoint returns `429` with `code: daily_cap_reached` and the reset time. A failed extraction still counts. | Requirement | Detail | | - | - | | **Scope** | `documents:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate). Each call on a document that is not yet `completed` counts against your organization's daily document extraction limit, if one is set (most organizations have none; shared with uploads); over it, `429` with `code: daily_cap_reached`. | | **Cost** | Free | > [!NOTE] > > **Safety** > > * **Writes data:** Yes. Starts or restarts text extraction and updates the document's extraction status. > * **Safe to retry:** Yes. A repeat runs extraction again on the same file and counts against the daily limit again (a call on a `completed` document does not). > * **Contacts an outside system:** None > * **Dry run:** Not available. Guide: [Webhooks](/webhooks). Errors: [Error catalog](/errors). # List patient documents Source: https://docs.healos.ai/api-reference/documents/list-patient-documents openapi/ext-api-v1.json GET /patients/{patientId}/documents Retrieve documents for a specific patient. Pass `external_id=` to look up a single document by caller-supplied external_id (returns 404 if not found). Use this to poll a document's extraction progress after upload: `status` moves `pending` → `processing` → `completed` (or `failed`), and `has_extracted_text`/`extracted_text_length` indicate whether extracted text is available (the text content itself is not returned). | Requirement | Detail | | - | - | | **Scope** | `documents:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Webhooks](/webhooks). Errors: [Error catalog](/errors). # Upload a document Source: https://docs.healos.ai/api-reference/documents/upload-a-document openapi/ext-api-v1.json POST /patients/{patientId}/documents Upload a document for a patient. Accepts PDF, JPEG, PNG, and DOCX files up to 10MB; the file content must match its extension, and the stored content type is the detected one. Pass an optional `external_id` form field to attach a caller-supplied identifier (immutable once set; unique per organization). **Text extraction runs asynchronously.** This endpoint returns as soon as the file is stored — it does not wait for extraction (which can take 10–30s for a PDF). The returned document is typically in `pending` status (extraction may occasionally finish before the response is built). Track progress by polling `GET /patients/{patientId}/documents` (pass `?external_id=` to fetch just this document) until its `status` is `completed` (`has_extracted_text` becomes `true`) or `failed`. Note: these endpoints report extraction status and availability (`status`, `has_extracted_text`, `extracted_text_length`) — the extracted text content itself is not returned. You can (re-)trigger extraction at any time with `POST /patients/{patientId}/documents/{documentId}/extract`. **Daily extraction limit.** If your organization has a daily document extraction limit, extraction counts against it (per UTC day, shared with the `/extract` endpoint); most organizations have none. Over the limit the upload still succeeds (`201`): the document is stored and stays `pending` with `extraction_deferred: true`, the response carries `extraction_deferred_until` (the next 00:00 UTC), and extraction runs automatically after that, counted against that day's limit. Uploads are never refused with `429` for this limit. Rarely, if extraction could not be queued, the upload still succeeds (`201`) but the response `message` omits "text extraction started" and the document stays `pending` with no work scheduled. Check the response `message`; if extraction was not started, call the `/extract` endpoint to trigger it (otherwise a poller would wait indefinitely). **Prefer webhooks over polling.** Register a `DOCUMENT_STATUS_CHANGED` outbound webhook to be notified the moment extraction reaches a terminal state — the event payload carries `document_id`, `external_id`, `status` (`completed`/`failed`), any `error`, and a `document_url` (a direct document lookup when `external_id` is set, otherwise the patient's document collection), so no polling loop is required. | Requirement | Detail | | - | - | | **Scope** | `documents:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate). Files up to 10 MB. If your organization has a daily document extraction limit (most have none), extraction counts against it, shared with `/extract`; over it the upload still succeeds and extraction is deferred to the next UTC day (`extraction_deferred: true`), never a `429`. | | **Cost** | Free | > [!NOTE] > > **Safety** > > * **Writes data:** Yes. Stores the file on the patient and starts text extraction. A `DOCUMENT_STATUS_CHANGED` webhook fires when extraction finishes. > * **Safe to retry:** Only with `external_id`: a repeat with the same `external_id` returns `409` with the existing record instead of a duplicate. Without it, a retry creates a second record. > * **Contacts an outside system:** None > * **Dry run:** Not available. Guide: [Webhooks](/webhooks). Errors: [Error catalog](/errors). # Get an EHR action Source: https://docs.healos.ai/api-reference/ehr/get-an-ehr-action openapi/ext-api-v1.json GET /ehr/actions/{actionName} One action's input and output schemas and safety contract, by its stable `.` name. | Requirement | Detail | | - | - | | **Scope** | `ehr:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None. Reads HealOS's catalog; your EHR is not contacted. > * **Dry run:** Not needed (read-only). > [!WARNING] > > This endpoint only **describes** EHR actions. Running them through the HealOS API is not available yet: there is no endpoint that executes an action. Look an action up by its stable `.` name, for example `athena.search_patients`. Guide: [EHR integrations](/ehr-actions/overview). Errors: [Error catalog](/errors). # List EHR actions Source: https://docs.healos.ai/api-reference/ehr/list-ehr-actions openapi/ext-api-v1.json GET /ehr/actions The catalog of actions HealOS supports per EHR, with input and output schemas and a safety contract for each. The catalog is the same for every organization. It describes actions only: running them through the API is not available yet. | Requirement | Detail | | - | - | | **Scope** | `ehr:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None. Reads HealOS's catalog; your EHR is not contacted. > * **Dry run:** Not needed (read-only). > [!WARNING] > > This endpoint only **describes** EHR actions. Running them through the HealOS API is not available yet: there is no endpoint that executes an action. The catalog is the same for every organization. Filter one EHR with `?ehr=athena`. Guide: [EHR integrations](/ehr-actions/overview). Errors: [Error catalog](/errors). # List your EHR connections Source: https://docs.healos.ai/api-reference/ehr/list-your-ehr-connections openapi/ext-api-v1.json GET /ehr/connections Every EHR in the catalog with whether your organization has it connected. Status only: never credentials, sessions or which user connected it. | Requirement | Detail | | - | - | | **Scope** | `ehr:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None. Reads your organization's connection status in HealOS; your EHR is not contacted. > * **Dry run:** Not needed (read-only). Returns, for each EHR in the catalog, only whether **the key's own organization** has it connected. It never returns credentials, sessions or which user connected it. Guide: [EHR integrations](/ehr-actions/overview). Errors: [Error catalog](/errors). # Download a received fax Source: https://docs.healos.ai/api-reference/fax/download-a-received-fax openapi/ext-api-v1.json GET /faxes/{faxId}/file The fax file itself (usually a PDF), streamed through the API; there is no public file URL. Another organization's fax is a 404, as is a fax whose stored file is missing. Requires the fax:read scope. | Requirement | Detail | | - | - | | **Scope** | `fax:read` (rolling out: not yet on `api.healos.ai`) | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). The file is streamed through the API; there is no public URL to share or cache. With the CLI: `healos fax download --out fax.pdf` (the file is created readable by you only). Errors: [Error catalog](/errors). # Get a received fax Source: https://docs.healos.ai/api-reference/fax/get-a-received-fax openapi/ext-api-v1.json GET /faxes/{faxId} One received fax with the fields HealOS extracted from it. Another organization's fax is a 404. Requires the fax:read scope. | Requirement | Detail | | - | - | | **Scope** | `fax:read` (rolling out: not yet on `api.healos.ai`) | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). The response contains PHI (extracted patient and clinical fields). Store it the way you store other patient records. Errors: [Error catalog](/errors). # Get a sent fax Source: https://docs.healos.ai/api-reference/fax/get-a-sent-fax openapi/ext-api-v1.json GET /faxes/outbound/{outboundFaxId} One sent fax and its stored delivery status. The status is what HealOS last recorded; this read never contacts the fax provider. Another organization's fax is a 404. Requires the fax:read scope. | Requirement | Detail | | - | - | | **Scope** | `fax:read` (rolling out: not yet on `api.healos.ai`) | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). The status is what HealOS last recorded; this read does not ask the fax provider again. Errors: [Error catalog](/errors). # List received faxes Source: https://docs.healos.ai/api-reference/fax/list-received-faxes openapi/ext-api-v1.json GET /faxes Faxes your organization received (and documents filed into the fax inbox), newest first. Summary fields only: GET /faxes/{faxId} has the extracted fields. Requires the fax:read scope. | Requirement | Detail | | - | - | | **Scope** | `fax:read` (rolling out: not yet on `api.healos.ai`) | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Errors: [Error catalog](/errors). # List sent faxes Source: https://docs.healos.ai/api-reference/fax/list-sent-faxes openapi/ext-api-v1.json GET /faxes/outbound Faxes your organization sent, newest first, with their stored delivery status. Requires the fax:read scope. | Requirement | Detail | | - | - | | **Scope** | `fax:read` (rolling out: not yet on `api.healos.ai`) | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Errors: [Error catalog](/errors). # Assign a patient to a session Source: https://docs.healos.ai/api-reference/notes/assign-a-patient-to-a-session openapi/ext-api-v1.json PATCH /sessions/{sessionId} Files the session and its notes under a patient in your organization. Use it for a session created without patient_id, or to correct a session's patient. A NOTE_UPDATED webhook fires for each of the session's notes. Refused with 409 when a note of this session was already sent to an EHR. Requires notes:write. | Requirement | Detail | | - | - | | **Scope** | `notes:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!NOTE] > > **Safety** > > * **Writes data:** Yes. Moves the session and its notes to the patient you send. A `NOTE_UPDATED` webhook fires for each note. > * **Safe to retry:** Yes. A repeat returns `patient_changed: false`. > * **Contacts an outside system:** None. Refused with `409` if a note of this session was already sent to an EHR; it never contacts the EHR. > * **Dry run:** Not available. Guide: [Clinical notes](/clinical-notes). Errors: [Error catalog](/errors). # Export clinical notes Source: https://docs.healos.ai/api-reference/notes/export-clinical-notes openapi/ext-api-v1.json GET /notes/export Every note matching the same filters as GET /notes, with full content, codes, transcript and patient context. `json` (default) and `csv` return at most 1000 notes (`meta.truncated`, or the `X-Result-Truncated` header on csv, says when more matched); `ndjson` streams the full set, one note per line. | Requirement | Detail | | - | - | | **Scope** | `notes:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Pick the format with `format`: `json` (default) and `csv` return at most 1000 notes (`meta.truncated`, or the `X-Result-Truncated` header on csv, says when more matched); `ndjson` streams every matching note, one per line. Narrow large pulls with `from` and `to`. The response holds full note content, transcripts and patient context: store it as PHI. Guide: [Clinical notes: export notes](/clinical-notes#export-notes). Errors: [Error catalog](/errors). # Generate a note from an audio file Source: https://docs.healos.ai/api-reference/notes/generate-a-note-from-an-audio-file openapi/ext-api-v1.json POST /notes/from-audio Uploads a recording of the visit (multipart/form-data), transcribes it and generates the clinical note asynchronously, the same as the dashboard's Upload audio. Accepts .wav, .mp3, .m4a, .mp4, .aac, .flac, .ogg and .webm up to 100 MB; long recordings are split and transcribed in parts. Returns 202 with the session id; a NOTE_CREATED webhook fires when the note is ready (or poll GET /sessions/{sessionId}). Requires notes:write. | Requirement | Detail | | - | - | | **Scope** | `notes:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate). Files up to 100 MB. | | **Cost** | Uses one Scribe session from your organization's plan (`402` when none are left). | > [!WARNING] > > **Safety** > > * **Writes data:** Yes. Stores the recording, creates a session, transcribes it and writes the note. A `NOTE_CREATED` webhook fires when it is ready. > * **Safe to retry:** No. Each request creates a new session. If you got a `202`, check the session instead of retrying. > * **Contacts an outside system:** None > * **Dry run:** Not available. Guide: [Clinical notes](/clinical-notes). Errors: [Error catalog](/errors). # Generate a note from text Source: https://docs.healos.ai/api-reference/notes/generate-a-note-from-text openapi/ext-api-v1.json POST /notes/from-text Creates a visit from typed text and generates its clinical note asynchronously, the same as the dashboard's Type note. Returns 202 with the session id; a NOTE_CREATED webhook fires when the note is ready (or poll GET /sessions/{sessionId}/notes). Requires notes:write. | Requirement | Detail | | - | - | | **Scope** | `notes:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Uses one Scribe session from your organization's plan (`402` when none are left). | > [!WARNING] > > **Safety** > > * **Writes data:** Yes. Creates a session and writes its clinical note with AI. A `NOTE_CREATED` webhook fires when it is ready. > * **Safe to retry:** **No**. Each request creates a new session. If you got a `202`, check the session instead of retrying. (`409` only means a request for this patient is being submitted at this moment.) > * **Contacts an outside system:** None > * **Dry run:** Not available. Guide: [Clinical notes](/clinical-notes). Errors: [Error catalog](/errors). # Generate a note from the patient's documents Source: https://docs.healos.ai/api-reference/notes/generate-a-note-from-the-patients-documents openapi/ext-api-v1.json POST /patients/{patientId}/notes/from-documents Creates a new session for the patient and queues generation of a clinical note from the patient's uploaded documents (text extraction must have completed for at least one document) — no recording or transcript needed. Returns 202 with the new session id; generation typically takes under a minute. Register a NOTE_CREATED outbound webhook to be notified when the note is ready, or poll GET /sessions/{sessionId}/notes. Requires the notes:write scope. Each call creates a new session: send an Idempotency-Key header to make a retry safe, or do not retry a request that already returned 202. | Requirement | Detail | | - | - | | **Scope** | `notes:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Runs AI note generation. | > [!WARNING] > > **Safety** > > * **Writes data:** Yes. Creates a session for the patient and writes a note from their documents with AI. A `NOTE_CREATED` webhook fires when it is ready. > * **Safe to retry:** No. Each request creates a new session and note. If you got a `202`, check the session instead of retrying. > * **Contacts an outside system:** None > * **Dry run:** Not available. Guide: [Recipe: patient, document, note](/recipes/document-to-note). Errors: [Error catalog](/errors). # Get a clinical note by ID Source: https://docs.healos.ai/api-reference/notes/get-a-clinical-note-by-id openapi/ext-api-v1.json GET /notes/{noteId} Full note (content + medical codes) with the session transcript and patient context embedded by default. Control embeds with the `include` query param. | Requirement | Detail | | - | - | | **Scope** | `notes:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Clinical notes](/clinical-notes). Errors: [Error catalog](/errors). # List clinical notes Source: https://docs.healos.ai/api-reference/notes/list-clinical-notes openapi/ext-api-v1.json GET /notes Paginated list of clinical notes authored by your organization's members. Lightweight items — use GET /notes/{noteId} for full content, codes, transcript, and patient context. A bulk dump is available at GET /notes/export (?format=json|csv|ndjson). | Requirement | Detail | | - | - | | **Scope** | `notes:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Clinical notes](/clinical-notes). Errors: [Error catalog](/errors). # List notes for a session Source: https://docs.healos.ai/api-reference/notes/list-notes-for-a-session openapi/ext-api-v1.json GET /sessions/{sessionId}/notes All clinical notes generated for a session, plus the session's transcript/summary and the patient context. Returns 404 if the session isn't owned by your organization. | Requirement | Detail | | - | - | | **Scope** | `notes:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Clinical notes](/clinical-notes). Errors: [Error catalog](/errors). # Regenerate the note for a session Source: https://docs.healos.ai/api-reference/notes/regenerate-the-note-for-a-session openapi/ext-api-v1.json POST /sessions/{sessionId}/notes/regenerate Queues asynchronous regeneration of the session's clinical note from its transcript. Returns 202 immediately; generation typically takes under a minute. Register a NOTE_REGENERATED outbound webhook to be notified when the fresh note is ready, or poll GET /sessions/{sessionId}/notes. Requires the notes:write scope. Send an Idempotency-Key header to make a retry safe: a repeat with the same key and the same request within 24 hours returns the original 202 instead of regenerating again. | Requirement | Detail | | - | - | | **Scope** | `notes:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Runs AI note generation. | > [!WARNING] > > **Safety** > > * **Writes data:** Yes. Writes a new note for the session with AI. A `NOTE_REGENERATED` webhook fires when it is ready. > * **Safe to retry:** Yes, if you send an `Idempotency-Key` header: repeats with the same key for the same session run one regeneration. Without it, each request regenerates again. > * **Contacts an outside system:** None > * **Dry run:** Not available. Guide: [Clinical notes](/clinical-notes). Errors: [Error catalog](/errors). # Create a new patient Source: https://docs.healos.ai/api-reference/patients/create-a-new-patient openapi/ext-api-v1.json POST /patients | Requirement | Detail | | - | - | | **Scope** | `patients:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!NOTE] > > **Safety** > > * **Writes data:** Yes. Creates a patient in your organization. > * **Safe to retry:** Only with `external_id`: a repeat with the same `external_id` returns `409` with the existing record instead of a duplicate. Without it, a retry creates a second record. > * **Contacts an outside system:** None > * **Dry run:** Not available. Guide: [Making requests](/making-requests). Errors: [Error catalog](/errors). # Delete a patient Source: https://docs.healos.ai/api-reference/patients/delete-a-patient openapi/ext-api-v1.json DELETE /patients/{patientId} | Requirement | Detail | | - | - | | **Scope** | `patients:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!WARNING] > > **Safety** > > * **Writes data:** Yes. **Permanently** deletes the patient together with their sessions and clinical notes. This cannot be undone. > * **Safe to retry:** Yes. A repeat returns `404` because the patient is already gone. > * **Contacts an outside system:** None > * **Dry run:** Not available. Guide: [Making requests](/making-requests). Errors: [Error catalog](/errors). # Get patient by ID Source: https://docs.healos.ai/api-reference/patients/get-patient-by-id openapi/ext-api-v1.json GET /patients/{patientId} | Requirement | Detail | | - | - | | **Scope** | `patients:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Making requests](/making-requests). Errors: [Error catalog](/errors). # List patients Source: https://docs.healos.ai/api-reference/patients/list-patients openapi/ext-api-v1.json GET /patients Paginated list of patients. Pass `external_id=` to look up a single patient by caller-supplied external_id (returns 404 if not found). | Requirement | Detail | | - | - | | **Scope** | `patients:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Making requests](/making-requests). Errors: [Error catalog](/errors). # Update a patient Source: https://docs.healos.ai/api-reference/patients/update-a-patient openapi/ext-api-v1.json PATCH /patients/{patientId} | Requirement | Detail | | - | - | | **Scope** | `patients:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!NOTE] > > **Safety** > > * **Writes data:** Yes. Updates the fields you send. `external_id` is ignored on update. > * **Safe to retry:** Yes. Sending the same body again gives the same result. > * **Contacts an outside system:** None > * **Dry run:** Not available. Guide: [Making requests](/making-requests). Errors: [Error catalog](/errors). # Check Availity decisions now Source: https://docs.healos.ai/api-reference/prior-auth/check-availity-decisions-now openapi/ext-api-v1.json POST /prior-auth/status-checks Reads the payer's decision for your open Availity requests, as the daily check does. Runs in the background (202); read the results from the requests list. At most once every 10 minutes per organization. CoverMyMeds decisions are checked hourly automatically. | Requirement | Detail | | - | - | | **Scope** | `prior_auth:write` | | **Rate limit** | Once every 10 minutes per organization (`409` before then), plus the shared limit of about 60 per minute. | | **Cost** | Free | > [!WARNING] > > **Safety** > > * **Writes data:** Yes. Updates the decision on your open Availity requests. > * **Safe to retry:** Yes. A repeat within 10 minutes, or while a workflow is running, returns `409` and does nothing. > * **Contacts an outside system:** **Yes.** Signs in to Availity as your organization to read the payer's decisions. > * **Dry run:** Not available. Guide: [Prior authorization](/prior-auth). Errors: [Error catalog](/errors). # Get a prior-auth request Source: https://docs.healos.ai/api-reference/prior-auth/get-a-prior-auth-request openapi/ext-api-v1.json GET /prior-auth/requests/{requestId} | Requirement | Detail | | - | - | | **Scope** | `prior_auth:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Prior authorization](/prior-auth). Errors: [Error catalog](/errors). # List a request's events Source: https://docs.healos.ai/api-reference/prior-auth/list-a-requests-events openapi/ext-api-v1.json GET /prior-auth/requests/{requestId}/events What happened to the request, newest first (up to 100). Events carry a type, a time and, for decisions, the decision; never chart data or answers. | Requirement | Detail | | - | - | | **Scope** | `prior_auth:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Prior authorization](/prior-auth). Errors: [Error catalog](/errors). # List prior-auth requests Source: https://docs.healos.ai/api-reference/prior-auth/list-prior-auth-requests openapi/ext-api-v1.json GET /prior-auth/requests Both tracks (CoverMyMeds medications and Availity procedures), newest change first. Covers the 500 most recently changed requests per track; pass `updated_since` to sync incrementally. | Requirement | Detail | | - | - | | **Scope** | `prior_auth:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Prior authorization](/prior-auth). Errors: [Error catalog](/errors). # List prior-auth workflows Source: https://docs.healos.ai/api-reference/prior-auth/list-prior-auth-workflows openapi/ext-api-v1.json GET /prior-auth/workflows Your organization's EHR → portal workflows and their last run. Settings and sign-ins are not returned. | Requirement | Detail | | - | - | | **Scope** | `prior_auth:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Prior authorization](/prior-auth). Errors: [Error catalog](/errors). # Get provider by ID Source: https://docs.healos.ai/api-reference/providers/get-provider-by-id openapi/ext-api-v1.json GET /providers/{providerId} | Requirement | Detail | | - | - | | **Scope** | `providers:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Making requests](/making-requests). Errors: [Error catalog](/errors). # List providers Source: https://docs.healos.ai/api-reference/providers/list-providers openapi/ext-api-v1.json GET /providers Read-only, paginated list of the providers (clinicians) in your organization. The provider `id` is the stable internal identifier to map against your own directory and to pass as `provider_id` on patients and appointments. Pass `npi=` to look up a single provider by their individual (type-I) NPI. | Requirement | Detail | | - | - | | **Scope** | `providers:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Making requests](/making-requests). Errors: [Error catalog](/errors). # Create a receptionist task Source: https://docs.healos.ai/api-reference/receptionist/create-a-receptionist-task openapi/ext-api-v1.json POST /receptionist/tasks Adds a task to the AI Receptionist inbox, as staff do with New task. `status` defaults to `todo`. `patient_id`, `linked_call_id` and `assigned_provider_calendar_id` must belong to your organization (404 otherwise). Requires the receptionist:write scope. | Requirement | Detail | | - | - | | **Scope** | `receptionist:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!NOTE] > > **Safety** > > * **Writes data:** Yes. Adds a task to the AI Receptionist inbox in HealOS. It is not sent to your EHR. > * **Safe to retry:** Only with an `Idempotency-Key` header: a repeat with the same key returns the first task instead of a second one. Without it, a retry creates a second task. > * **Contacts an outside system:** None > * **Dry run:** Not available. > [!NOTE] > > Rolling out: this endpoint is on staging first and not yet on `api.healos.ai`. The task appears in the dashboard inbox like one staff created (`source` is `manual`). `status` defaults to `todo`. `patient_id`, `linked_call_id` and `assigned_provider_calendar_id` must belong to your organization; any other id is a `404` and no task is created. A call that staff removed from Call History cannot be linked. Guide: [Calls and inbox](/guides/receptionist/calls-and-inbox). Errors: [Error catalog](/errors). # Delete a receptionist task Source: https://docs.healos.ai/api-reference/receptionist/delete-a-receptionist-task openapi/ext-api-v1.json DELETE /receptionist/tasks/{taskId} Deletes the task from the inbox. This cannot be undone; to hide a task but keep it, set `status` to `archived` instead. Returns 404 if the task isn't your organization's. Requires the receptionist:write scope. | Requirement | Detail | | - | - | | **Scope** | `receptionist:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!WARNING] > > **Safety** > > * **Writes data:** Yes. **Permanently** deletes the task. To keep a record, set `status` to `archived` with `PATCH` instead. > * **Safe to retry:** Yes. A repeat returns `404` because the task is already gone. > * **Contacts an outside system:** None > * **Dry run:** Not available. > [!NOTE] > > Rolling out: this endpoint is on staging first and not yet on `api.healos.ai`. Another organization's task is a `404` and nothing is deleted. Guide: [Calls and inbox](/guides/receptionist/calls-and-inbox). Errors: [Error catalog](/errors). # Download a call recording Source: https://docs.healos.ai/api-reference/receptionist/download-a-call-recording openapi/ext-api-v1.json GET /receptionist/calls/{callId}/recording The call's recording as audio bytes (usually `audio/mpeg`), streamed through the API; there is no public media URL. Every download is written to the organization's recording access log before the audio is sent, with the key owner as the accessor. 404 when the call has no recording (`has_recording` is false on the call), 502 when the stored recording could not be read. Requires the receptionist:read scope. | Requirement | Detail | | - | - | | **Scope** | `receptionist:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No (an entry is added to your organization's recording access log on every download) > * **Safe to retry:** Yes > * **Contacts an outside system:** Reads the stored recording from HealOS storage or the voice provider > * **Dry run:** Not needed (read-only). The response body is the audio itself, not JSON. `Content-Type` is the stored media type (usually `audio/mpeg`) and `Content-Disposition` names the file `call-.mp3`. There is no public media URL: the bytes are streamed through the API, so the request needs your key like any other. Check `has_recording` on the call before downloading; a call without one answers `404`. The recording length is the call's `duration_sec`. Every download is written to the organization's recording access log before any audio is sent, with the API key's owner as the accessor, the same way dashboard downloads are logged. If that log cannot be written the download is refused with `503`. ```bash theme={null} curl -sS "https://api.healos.ai/ext-api/v1/receptionist/calls/$CALL_ID/recording" \ -H "X-API-Key: $HEALOS_API_KEY" \ -o "call-$CALL_ID.mp3" ``` Guide: [Receptionist call transcripts](/recipes/receptionist-call-transcripts). Errors: [Error catalog](/errors). # Get a receptionist call Source: https://docs.healos.ai/api-reference/receptionist/get-a-receptionist-call openapi/ext-api-v1.json GET /receptionist/calls/{callId} One AI Receptionist call with everything the list returns plus the full `transcript` (speaker and message per turn) and `extracted_data` (the structured details the post-call analysis pulled from the conversation). Returns 404 if the call isn't your organization's. Requires the receptionist:read scope. | Requirement | Detail | | - | - | | **Scope** | `receptionist:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Everything [List receptionist calls](/api-reference/receptionist/list-receptionist-calls) returns for the call, plus: * `transcript`: the conversation in order, one `{ speaker, message }` per turn. `user` is the caller, `assistant` is the AI receptionist. `null` when no transcript was recorded. * `extracted_data`: the structured details the post-call analysis pulled from the transcript, such as the reason for the call or whether a callback was requested. Keys vary by call and by what the practice's receptionist is configured to collect; treat unknown keys as informational. The transcript and extracted details are protected health information. Store them as you would any patient record. Guide: [Receptionist call transcripts](/recipes/receptionist-call-transcripts). Errors: [Error catalog](/errors). # Get a receptionist task Source: https://docs.healos.ai/api-reference/receptionist/get-a-receptionist-task openapi/ext-api-v1.json GET /receptionist/tasks/{taskId} One AI Receptionist inbox task. Returns 404 if the task isn't your organization's. Requires the receptionist:read scope. | Requirement | Detail | | - | - | | **Scope** | `receptionist:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). > [!NOTE] > > Rolling out: this endpoint is on staging first and not yet on `api.healos.ai`. One inbox task, with the same fields the list returns. Another organization's task is a `404`. Guide: [Calls and inbox](/guides/receptionist/calls-and-inbox). Errors: [Error catalog](/errors). # List receptionist calls Source: https://docs.healos.ai/api-reference/receptionist/list-receptionist-calls openapi/ext-api-v1.json GET /receptionist/calls Paginated AI Receptionist calls for your organization, newest first, with each call's status, outcome, summary and whether a recording and transcript exist. Filter by date received (`from_date`, `to_date`), outcome, or a caller name or number. Transcripts and extracted details are on GET /receptionist/calls/{callId}. Requires the receptionist:read scope. | Requirement | Detail | | - | - | | **Scope** | `receptionist:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Calls are returned newest first by the time HealOS received the call record (`created_at`), which is what `from_date` and `to_date` filter on. Each item carries the status, outcome and post-call summary; the transcript and extracted details are on [Get a receptionist call](/api-reference/receptionist/get-a-receptionist-call), and the audio on [Download a call recording](/api-reference/receptionist/download-a-call-recording). The `id` is the same `call_id` the post-call webhook sends, so you can use the webhook as the trigger and this endpoint to fetch the rest. Guide: [Receptionist call transcripts](/recipes/receptionist-call-transcripts). Errors: [Error catalog](/errors). # List receptionist tasks Source: https://docs.healos.ai/api-reference/receptionist/list-receptionist-tasks openapi/ext-api-v1.json GET /receptionist/tasks Paginated AI Receptionist inbox tasks for your organization, newest first: the call backs, refills and messages the receptionist (or staff) created for the front desk. Filter by `status`, `category`, title text or creation date. Requires the receptionist:read scope. | Requirement | Detail | | - | - | | **Scope** | `receptionist:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). > [!NOTE] > > Rolling out: this endpoint is on staging first and not yet on `api.healos.ai`. Inbox tasks are the call backs, refills and messages the AI Receptionist (or staff) leave for the front desk. They are returned newest first by `created_at`. Without `status`, every status is listed, archived tasks included; pass `status=todo` for the open ones. `caller_phone` is the number of the call the task came from, so you can call back. It is `null` for a task with no linked phone call. Task notes can contain protected health information. Store them as you would any patient record. Guide: [Calls and inbox](/guides/receptionist/calls-and-inbox). Errors: [Error catalog](/errors). # Update a receptionist task Source: https://docs.healos.ai/api-reference/receptionist/update-a-receptionist-task openapi/ext-api-v1.json PATCH /receptionist/tasks/{taskId} Changes the fields you send and leaves the rest. Resolve a task with `{"status": "done"}`; send `null` to clear an optional field. Linked ids must belong to your organization. Returns 404 if the task isn't your organization's. Requires the receptionist:write scope. | Requirement | Detail | | - | - | | **Scope** | `receptionist:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!NOTE] > > **Safety** > > * **Writes data:** Yes. Changes the fields you send; the rest stay as they are. > * **Safe to retry:** Yes. Sending the same change again leaves the task the same. > * **Contacts an outside system:** None > * **Dry run:** Not available. > [!NOTE] > > Rolling out: this endpoint is on staging first and not yet on `api.healos.ai`. Resolve a task with `{ "status": "done" }`, or hide it from the default inbox view with `archived`. Send `null` to clear an optional field such as `due_date` or `linked_call_id`. The ids you link are checked the same way as on create. Guide: [Calls and inbox](/guides/receptionist/calls-and-inbox). Errors: [Error catalog](/errors). # Delete a session Source: https://docs.healos.ai/api-reference/sessions/delete-a-session openapi/ext-api-v1.json DELETE /sessions/{sessionId} Moves the session and its notes to the recycle bin, the same as deleting a visit in the dashboard. It can be restored with POST /sessions/{sessionId}/restore. This never deletes permanently: a session already in the bin is left as it is (`changed: false`). Emptying the bin stays in the dashboard. Returns 404 if the session isn't your organization's. Requires notes:write. | Requirement | Detail | | - | - | | **Scope** | `notes:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!WARNING] > > **Safety** > > * **Writes data:** Yes. Moves the session and its notes to the recycle bin. It is **not** a permanent delete: restore it with [Restore a deleted session](/api-reference/sessions/restore-a-deleted-session). Emptying the recycle bin is only possible in the dashboard. > * **Safe to retry:** Yes. A repeat finds the session already in the bin, changes nothing and returns `changed: false`. > * **Contacts an outside system:** None. Notes already sent to an EHR stay there. > * **Dry run:** Not available. > [!NOTE] > > Rolling out: this endpoint is on staging first and not yet on `api.healos.ai`. A deleted session no longer appears in `GET /sessions/{sessionId}` or the notes endpoints. Another organization's session is a `404`. Guide: [Making requests](/making-requests). Errors: [Error catalog](/errors). # Get session details Source: https://docs.healos.ai/api-reference/sessions/get-session-details openapi/ext-api-v1.json GET /sessions/{sessionId} Metadata for one session: encounter date and times, duration, status, template, the owning provider, a patient summary and the ids of the notes generated for it. Use GET /sessions/{sessionId}/notes for note content and the transcript. Returns 404 if the session isn't owned by your organization. Requires the notes:read scope. | Requirement | Detail | | - | - | | **Scope** | `notes:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Clinical notes](/clinical-notes). Errors: [Error catalog](/errors). # Restore a deleted session Source: https://docs.healos.ai/api-reference/sessions/restore-a-deleted-session openapi/ext-api-v1.json POST /sessions/{sessionId}/restore Takes a session out of the recycle bin; it and its notes are visible again. A session that is not in the bin is left as it is (`changed: false`). Returns 404 if the session isn't your organization's. Requires notes:write. | Requirement | Detail | | - | - | | **Scope** | `notes:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!NOTE] > > **Safety** > > * **Writes data:** Yes. Takes the session out of the recycle bin. > * **Safe to retry:** Yes. A session that is not in the bin is left as it is (`changed: false`). > * **Contacts an outside system:** None > * **Dry run:** Not available. > [!NOTE] > > Rolling out: this endpoint is on staging first and not yet on `api.healos.ai`. The session returns as `completed` when its transcript finished, otherwise `finalizing`. Another organization's session is a `404`. Guide: [Making requests](/making-requests). Errors: [Error catalog](/errors). # Get note settings Source: https://docs.healos.ai/api-reference/settings/get-note-settings openapi/ext-api-v1.json GET /settings/notes The Scribe settings notes are generated with for the clinician who owns this API key: default template, model, languages, terminology and specialty. Read-only. Requires the settings:read scope. | Requirement | Detail | | - | - | | **Scope** | `settings:read` (rolling out: not yet on `api.healos.ai`) | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Templates](/templates). Errors: [Error catalog](/errors). # Get a template Source: https://docs.healos.ai/api-reference/templates/get-a-template openapi/ext-api-v1.json GET /templates/{templateId} One template with its sections and each section's instructions. Built-in templates, templates shared with your organization, and the key owner's own private templates (the same set POST /sessions/{sessionId}/notes/regenerate accepts as `template_id`). A template from another organization is a 404. Requires the templates:read scope. | Requirement | Detail | | - | - | | **Scope** | `templates:read` (rolling out: not yet on `api.healos.ai`) | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Templates](/templates). Errors: [Error catalog](/errors). # List templates Source: https://docs.healos.ai/api-reference/templates/list-templates openapi/ext-api-v1.json GET /templates Paginated list of the note templates your organization can generate with: HealOS built-in templates plus custom templates shared with your organization. A template's `id` is what POST /sessions/{sessionId}/notes/regenerate takes as `template_id`. Private templates (visible to a single clinician) are not listed. Requires the templates:read or notes:read scope. | Requirement | Detail | | - | - | | **Scope** | `templates:read` or `notes:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). Guide: [Templates](/templates). Errors: [Error catalog](/errors). # Create a webhook Source: https://docs.healos.ai/api-reference/webhooks/create-a-webhook openapi/ext-api-v1.json POST /webhooks Registers a webhook for one event type. Deliveries start with the next matching event for the key owner's notes and documents. `url` must be HTTPS on a public host. Requires the webhooks:write scope. | Requirement | Detail | | - | - | | **Scope** | `webhooks:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!NOTE] > > **Safety** > > * **Writes data:** Yes. Registers a webhook. HealOS starts sending events to `url` with the next matching note or document event. > * **Safe to retry:** Only with an `Idempotency-Key` header: a repeat with the same key returns the first webhook instead of a second one. > * **Contacts an outside system:** Not at creation. Later deliveries POST to your `url`. > * **Dry run:** Not available. > [!NOTE] > > Rolling out: this endpoint is on staging first and not yet on `api.healos.ai`. One webhook receives one `event_type`; create one per event you need. `url` must be HTTPS on a public host (loopback, private, link-local and cloud-metadata addresses are rejected, at creation and again before every delivery). Use `headers` to send a shared secret your endpoint checks, for example `{"Authorization": "Bearer "}`. `Host`, `Content-Type`, `Content-Length`, `User-Agent` and other framing headers are set by HealOS and cannot be configured. Header values cannot be read back, so keep your copy. Webhooks belong to the user who created the API key and receive that user's note and document events, the same as on the dashboard's Webhooks page. A webhook of another user, in your organization or any other, is a `404`. Guide: [Webhooks](/webhooks). Errors: [Error catalog](/errors). # Delete a webhook Source: https://docs.healos.ai/api-reference/webhooks/delete-a-webhook openapi/ext-api-v1.json DELETE /webhooks/{webhookId} Deletes one of your webhooks; deliveries stop. To pause instead, PATCH `active: false`. Another user's webhook is a 404. Requires the webhooks:write scope. | Requirement | Detail | | - | - | | **Scope** | `webhooks:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!WARNING] > > **Safety** > > * **Writes data:** Yes. **Permanently** deletes the webhook; deliveries stop. To pause instead, set `active` to `false` with `PATCH`. > * **Safe to retry:** Yes. A repeat returns `404` because the webhook is already gone. > * **Contacts an outside system:** None > * **Dry run:** Not available. > [!NOTE] > > Rolling out: this endpoint is on staging first and not yet on `api.healos.ai`. Webhooks belong to the user who created the API key and receive that user's note and document events, the same as on the dashboard's Webhooks page. A webhook of another user, in your organization or any other, is a `404`. Guide: [Webhooks](/webhooks). Errors: [Error catalog](/errors). # Get a webhook Source: https://docs.healos.ai/api-reference/webhooks/get-a-webhook openapi/ext-api-v1.json GET /webhooks/{webhookId} One of your webhooks. Another user's webhook is a 404. Requires the webhooks:read scope. | Requirement | Detail | | - | - | | **Scope** | `webhooks:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). > [!NOTE] > > Rolling out: this endpoint is on staging first and not yet on `api.healos.ai`. Webhooks belong to the user who created the API key and receive that user's note and document events, the same as on the dashboard's Webhooks page. A webhook of another user, in your organization or any other, is a `404`. Guide: [Webhooks](/webhooks). Errors: [Error catalog](/errors). # List webhooks Source: https://docs.healos.ai/api-reference/webhooks/list-webhooks openapi/ext-api-v1.json GET /webhooks The webhooks of the user who created this API key, the same list as the dashboard's Webhooks page. Header values are never returned. Requires the webhooks:read scope. | Requirement | Detail | | - | - | | **Scope** | `webhooks:read` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!TIP] > > **Safety** > > * **Writes data:** No > * **Safe to retry:** Yes > * **Contacts an outside system:** None > * **Dry run:** Not needed (read-only). > [!NOTE] > > Rolling out: this endpoint is on staging first and not yet on `api.healos.ai`. Webhooks belong to the user who created the API key and receive that user's note and document events, the same as on the dashboard's Webhooks page. A webhook of another user, in your organization or any other, is a `404`. Header values are write-only: each webhook lists `header_names`, never the values. Guide: [Webhooks](/webhooks). Errors: [Error catalog](/errors). # Update a webhook Source: https://docs.healos.ai/api-reference/webhooks/update-a-webhook openapi/ext-api-v1.json PATCH /webhooks/{webhookId} Changes the fields you send. `active: false` pauses deliveries. `headers` replaces every configured header. A new `url` is checked like on create. Another user's webhook is a 404. Requires the webhooks:write scope. | Requirement | Detail | | - | - | | **Scope** | `webhooks:write` | | **Rate limit** | About 60 requests per minute per API key (shared by all endpoints; approximate) | | **Cost** | Free | > [!NOTE] > > **Safety** > > * **Writes data:** Yes. Changes the fields you send. `headers` replaces every configured header. > * **Safe to retry:** Yes. Sending the same change again leaves the webhook the same. > * **Contacts an outside system:** None > * **Dry run:** Not available. > [!NOTE] > > Rolling out: this endpoint is on staging first and not yet on `api.healos.ai`. Pause deliveries with `{ "active": false }` and resume with `true`. A new `url` is checked the same way as on create. Webhooks belong to the user who created the API key and receive that user's note and document events, the same as on the dashboard's Webhooks page. A webhook of another user, in your organization or any other, is a `404`. Guide: [Webhooks](/webhooks). Errors: [Error catalog](/errors). # Authentication Source: https://docs.healos.ai/authentication How to authenticate with the Healos External API All requests must include a valid API key in the `X-API-Key` header. ```bash theme={null} curl -H "X-API-Key: hlsk_your_key_here" \ https://api.healos.ai/ext-api/v1/patients ``` ## Prerequisites * You must belong to an **organization**. If you don't have one, create one first from the Healos dashboard. * Only **organization admins** can create, list, and revoke API keys. ## Obtaining an API Key An organization admin creates keys in the HealOS dashboard: 1. Open **Account Settings → API Keys** at [app.healos.ai/account-settings](https://app.healos.ai/account-settings). 2. Select **Create API key**, give it a label, pick its [scopes](#scopes) and an expiry. 3. Copy the key. It is shown **only once**; HealOS keeps only a hash of it. API keys are prefixed with `hlsk_` and are tied to your organization. All data accessed through the key is scoped to your organization — you can read and write patients, appointments, and documents, list the providers in your organization, and read clinical notes belonging to any member of your org. A single key covers every provider in the organization; you assign records to specific providers with the `provider_id` field rather than issuing a key per provider. A key keeps working only while the admin who created it is still an admin of the organization. See [Security and HIPAA](/security) for storing, rotating and revoking keys. ## Scopes Each API key has a set of scopes that control resource access. Scopes follow a `resource:action` pattern. | Scope | Description | | - | - | | `*` | Full access to all resources | | `patients:read` | Read patient data | | `patients:write` | Create, update, delete patients | | `appointments:read` | Read appointments | | `appointments:write` | Create, update, delete appointments | | `documents:read` | Read documents | | `documents:write` | Upload and delete documents | | `notes:read` | Read and export clinical notes, and list note templates | | `templates:read` | List templates and read one template with its sections and their instructions (rolling out: not yet on `api.healos.ai`) | | `settings:read` | Read the key owner's Scribe note settings (rolling out: not yet on `api.healos.ai`) | | `notes:write` | Generate, regenerate and update notes and sessions | | `providers:read` | List the providers (clinicians) in your organization | | `benefits:read` | Read eligibility checks and search payers | | `benefits:write` | Run insurance eligibility checks | | `prior_auth:read` | Read prior-auth requests, their events and workflows | | `prior_auth:write` | Ask HealOS to check prior-auth decisions now | | `ehr:read` | Browse the EHR action catalog and see which EHRs your organization has connected (rolling out: not yet on `api.healos.ai`) | | `receptionist:read` | Read AI Receptionist calls: summaries, outcomes, transcripts, extracted details and recordings (rolling out: not yet on `api.healos.ai`) | | `receptionist:write` | Create, update (resolve, archive, reassign) and delete AI Receptionist inbox tasks (rolling out: not yet on `api.healos.ai`) | | `webhooks:read` | List and read the key owner's webhooks (header values are never returned) (rolling out: not yet on `api.healos.ai`) | | `fax:read` | List and read received and sent faxes, their extracted fields and files (rolling out: not yet on `api.healos.ai`) | | `webhooks:write` | Create, update, pause and delete the key owner's webhooks (rolling out: not yet on `api.healos.ai`) | > [!NOTE] > > `GET` and `HEAD` requests require `read` scopes. All other methods (`POST`, `PATCH`, `DELETE`) require `write` scopes. ## Check your key `GET /me` tells you who a key belongs to, which organization it acts in, its scopes and when it expires. It works with any valid key, whatever its scopes, so it is a safe first call for a new integration. ```bash theme={null} curl https://api.healos.ai/ext-api/v1/me \ -H "X-API-Key: $HEALOS_API_KEY" ``` ```json theme={null} { "data": { "user": { "id": "4f6c…", "name": "Dr. Example", "email": "dev@example.com" }, "org": { "id": "9a1b…", "name": "Example Clinic" }, "scopes": ["notes:read", "prior_auth:read"], "key": { "prefix": "hlsk_AbCd", "label": "Reporting job", "expires_at": "2027-01-01T00:00:00.000Z", "created_at": "2026-10-01T12:00:00.000Z" } } } ``` The response never includes the key itself or its hash. `expires_at` is `null` for a key with no expiry. ## Key Expiration and Revocation * Keys can have an optional expiration timestamp set at creation. * Keys can be revoked at any time. * Expired or revoked keys return `401 Unauthorized`. ## Security Best Practices * Use the **narrowest scopes** needed for your integration. * Set an **expiration date** on keys used in less-trusted environments. * **Rotate keys** periodically and revoke old ones. See [Rotate a key](/security#rotate-a-key). * Never expose keys in client-side code or public repositories. * Test with a key from a separate [test organization](/test-mode). # Benefit Verification Source: https://docs.healos.ai/benefits Run insurance eligibility checks and read past results The benefits endpoints check a patient's insurance coverage with their payer in real time (an X12 270/271 eligibility request) and keep every result in your organization's benefits history. Checks you run through the API also appear in the HealOS dashboard, and checks run in the dashboard can be read through the API. | Endpoint | Scope | What it does | | - | - | - | | `GET /benefits/payers/search` | `benefits:read` | Find the `payer_id` for a payer | | `POST /benefits/eligibility-checks` | `benefits:write` | Run a check and return the result | | `GET /benefits/eligibility-checks` | `benefits:read` | List past checks, optionally for one patient | | `GET /benefits/eligibility-checks/{checkId}` | `benefits:read` | Get one check with the full payer response | > [!WARNING] > > Eligibility results contain protected health information (member ids, > dates of birth, coverage details). Only use these endpoints under your > business associate agreement with HealOS, and store the results as PHI. ## 1. Find the payer Search by payer name or id (at least 2 characters). Use the returned `id` as `payer_id`. ```bash theme={null} curl "https://api.healos.ai/ext-api/v1/benefits/payers/search?q=aetna" \ -H "X-API-Key: $HEALOS_API_KEY" ``` ```json theme={null} { "data": [ { "id": "60054", "name": "Aetna" } ] } ``` ## 2. Run a check You always send the payer and the requesting provider. For the patient, send either: * `patient_id` for a patient already in HealOS. HealOS uses the patient's name, date of birth, gender, and the member id of their active insurance for this payer; or * `member_id`, `first_name`, `last_name` and `date_of_birth` (YYYY-MM-DD). | Field | Required | Description | | - | - | - | | `payer_id` | Yes | From payer search. | | `provider_name` | Yes | Requesting provider or practice name. | | `provider_npi` | Yes | 10-digit NPI of the requesting provider or practice. | | `patient_id` | One of | A HealOS patient in your organization. | | `member_id`, `first_name`, `last_name`, `date_of_birth` | One of | The member as the payer knows them. | | `payer_name` | No | Stored on the check for your records. | | `middle_name`, `gender` | No | Sent to the payer when given. | | `service_type` | No | X12 service type code; defaults to `30` (health benefit plan coverage). | | `insurance_type` | No | `primary` (default) or `secondary`. | | `linked_check_id` | No | For a secondary check, the id of its primary check. | ```bash theme={null} curl -X POST https://api.healos.ai/ext-api/v1/benefits/eligibility-checks \ -H "X-API-Key: $HEALOS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "payer_id": "60054", "payer_name": "Aetna", "provider_name": "Riverside Family Medicine", "provider_npi": "1234567893", "member_id": "W123456789", "first_name": "Jordan", "last_name": "Rivera", "date_of_birth": "1984-03-12" }' ``` The call waits for the payer, which usually takes a few seconds; allow up to a minute before giving up. A `200` means the payer answered; read `status` and `result` to see whether coverage is active. ```json theme={null} { "data": { "id": "3f2b9c1e-6a7d-4e1f-9b0a-2c4d5e6f7a8b", "status": "Active", "patient_name": "Jordan Rivera", "payer_name": "Aetna", "member_id": "W123456789", "patient_id": null, "insurance_type": "primary", "linked_check_id": null, "checked_at": "2026-10-20T10:00:00.000Z", "last_checked_at": "2026-10-20T10:00:00.000Z", "result": { "subscriber": { "firstName": "Jordan", "lastName": "Rivera", "memberId": "W123456789", "dateOfBirth": "1984-03-12" }, "payer": { "id": "60054", "organizationName": "Aetna" }, "plan": { "planNames": ["Choice POS II"], "groupNumber": "123456" }, "benefits": [ { "benefit": "Co-Payment", "services": "Professional (Physician) Visit - Office", "coverageLevel": "Individual", "inPlanNetwork": true, "amount": "25", "authRequired": false } ] } } } ``` ### What `result` contains `result` is the payer's response, normalized: * `subscriber` (and `dependents`): the member the payer matched. * `payer` and `provider`: who answered and who asked. * `plan`: plan names, group number and coverage dates. * `benefits`: one entry per benefit, with the benefit type (active coverage, co-payment, co-insurance, deductible, out-of-pocket), coverage level, in/out of network, amount or percentage, time period, and whether prior authorization is required. * `issues` / `warnings`: problems the payer reported, such as a member not found. ### Errors | Status | `code` | Meaning | | - | - | - | | `400` | `VALIDATION_ERROR` | A required field is missing or malformed. | | `404` | `PATIENT_NOT_FOUND`, `LINKED_CHECK_NOT_FOUND` | The patient or primary check isn't in your organization. | | `422` | `PAYER_VALIDATION_ERROR` | The payer rejected the request (for example, an invalid member id). | | `429` | | Over the rate limit (see below). | | `502` / `504` | `UPSTREAM_ERROR`, `GATEWAY_TIMEOUT` | The payer or clearinghouse failed or didn't answer in time. Retry later. | | `503` | `SERVICE_UNAVAILABLE` | Eligibility checking isn't available right now. | ## 3. Read past checks ```bash theme={null} # One patient's checks, most recent first curl "https://api.healos.ai/ext-api/v1/benefits/eligibility-checks?patient_id=481926357104938271" \ -H "X-API-Key: $HEALOS_API_KEY" # One check with its full result curl https://api.healos.ai/ext-api/v1/benefits/eligibility-checks/3f2b9c1e-6a7d-4e1f-9b0a-2c4d5e6f7a8b \ -H "X-API-Key: $HEALOS_API_KEY" ``` The list is paginated with `page` and `limit` (default 20, max 100). ## Limits and cost Every eligibility check is a real request to the payer and is billable, so `POST /benefits/eligibility-checks` is limited to about **10 requests per minute per API key**, on top of the general [rate limit](/rate-limiting). Reading past checks and searching payers only count toward the general limit. Re-use a recent check instead of re-running it when you can. # Changelog Source: https://docs.healos.ai/changelog What changed in the HealOS API and the HealOS CLI, newest first Changes to the HealOS API (`/ext-api/v1`) and the [`healos` CLI](/cli), newest first. Additive changes, such as new endpoints and new response fields, ship without notice and are listed here. Breaking changes are announced here in advance; see [Versioning and deprecation](/versioning). **October 27, 2026** Key ownership, input limits, EHR catalog, CLI ### Added * **EHR action catalog (read-only).** `GET /ehr/actions` and `GET /ehr/actions/{actionName}` list what HealOS can do in each connected EHR, with inputs, outputs and a safety box per action. `GET /ehr/connections` shows which EHRs your organization has connected (status only, never credentials). All three need the new `ehr:read` scope. See [EHR actions](/ehr-actions/overview). Running actions through the API is not available yet. These three endpoints are rolling out: until they reach your environment they return `404`. ### Changed * **Keys follow their creator's admin role.** A key works only while the admin who created it is still an admin of the organization. Removing that person from the organization, or making them a non-admin, turns their keys off (`401`). Create production keys from an admin account that will stay in place. * **Stricter organization isolation.** Appointments, notes on sessions with no patient yet, session reassignment and templates are always limited to the key's organization, including for clinicians who belong to more than one organization. Older appointments that have no organization are visible only to their patient's organization, and updating another organization's appointment returns `404`. * **Input limits.** These reject some requests that were accepted before. See [Rate limiting](/rate-limiting#request-size). * `limit` is at most 100; larger values are treated as 100. A `page` or `limit` that is not a positive whole number returns `400` instead of being ignored. * JSON bodies up to 1 MB, document uploads up to 10 MB and audio uploads up to 100 MB. Larger bodies return `413`. * Uploaded documents and audio are checked by their content. A file whose content doesn't match its type returns `400`, for example a HEIC photo renamed to `.jpg`. ### Fixed * For a few hours after the input limits went live, a request sent without a body, which includes every `DELETE` (delete a patient, document or appointment), could fail with `500`. Fixed the same day; no change is needed on your side. ### CLI * **`@healos/cli` 0.1.0** is on npm: sign in from the browser (`healos login`, read-only by default), and a command for every API operation, with `--json` output for scripts and AI agents. See [HealOS CLI](/cli). * **0.1.1** changes only how the package is built and published. Commands and output are the same as 0.1.0. **October 23, 2026** GET /me * `GET /me` returns the organization, scopes and expiry of the calling key. It works with any valid key, whatever its scopes. See [Check your key](/authentication#check-your-key). **October 22, 2026** Notes from text and audio, prior auth * `POST /notes/from-text` and `POST /notes/from-audio` generate a note from a transcript or a recording. Both answer `202` with a `session_id`. Each call uses one Scribe session from the organization's plan. * `PATCH /sessions/{sessionId}` files a session and its notes under a patient. * Notes include `model`, the note quality (`fast`, `balanced` or `detailed`) that produced them. * Prior authorization: `GET /prior-auth/requests`, `GET /prior-auth/requests/{requestId}`, `GET /prior-auth/requests/{requestId}/events`, `GET /prior-auth/workflows` and `POST /prior-auth/status-checks`, with the `prior_auth:read` and `prior_auth:write` scopes. See [Prior authorization](/prior-auth). **October 21, 2026** Validation errors * Validation errors return `400` with `error: "Validation error"` and a `details` object keyed by field. See [Error catalog](/errors). * `POST /patients/{patientId}/notes/from-documents` uses the organization's default template when you don't send `template_id`. * Eligibility checks name the missing fields when a required field is left out. **October 20, 2026** Templates, sessions, notes from documents, eligibility * `GET /templates` lists the templates your organization can generate notes with. * `GET /sessions/{sessionId}` returns a session's details. * `POST /patients/{patientId}/notes/from-documents` writes a note from a patient's uploaded documents (`202`). * Eligibility checks: `POST /benefits/eligibility-checks`, `GET /benefits/eligibility-checks`, `GET /benefits/eligibility-checks/{checkId}` and `GET /benefits/payers/search`, with the `benefits:read` and `benefits:write` scopes. See [Benefit verification](/benefits). * `POST /sessions/{sessionId}/notes/regenerate` accepts only the note quality choices offered in the dashboard (`fast`, `balanced`, `detailed`) for `model`. **August 2026** Webhooks and note regeneration * Webhooks for `DOCUMENT_STATUS_CHANGED`, `NOTE_CREATED`, `NOTE_REGENERATED` and `NOTE_UPDATED`. Payloads carry ids and a URL to fetch, not content. See [Webhooks](/webhooks). * `POST /sessions/{sessionId}/notes/regenerate` queues a fresh note (`202`). Send an `Idempotency-Key` header so a retried request doesn't start a second regeneration. **July 2026** Patient details, async uploads * Patients carry first and last name, date of birth, gender, phone, email, address and MRN, and `GET /patients?q=` searches them. MRN is optional. * `POST /patients/{patientId}/documents/{documentId}/extract` starts or retries text extraction. * Document upload returns as soon as the file is stored; text extraction runs in the background. Follow it on the document's `status`. * Invalid appointment input returns a `400` that names the problem. **June 2026** Clinical notes and providers * `GET /notes`, `GET /notes/{noteId}`, `GET /notes/export` and `GET /sessions/{sessionId}/notes` read and export clinical notes, with the `notes:read` scope. See [Clinical notes](/clinical-notes). * `GET /providers` and `GET /providers/{providerId}` list your organization's clinicians, with the `providers:read` scope. **May 2026** external\_id * Patients, appointments and documents accept your own `external_id`, unique in the organization, and can be looked up with `?external_id=`. See [External IDs](/making-requests#external-ids). **April 2026** First release * The HealOS API at `https://api.healos.ai/ext-api/v1`: patients, patient documents and appointments, with organization API keys (`X-API-Key`), scopes, pagination and rate limits. * Patient ids are opaque numeric strings generated by HealOS. Store them as strings. # HealOS CLI Source: https://docs.healos.ai/cli Use the HealOS API from your terminal, scripts and AI agents `healos` is the HealOS command line. It talks to the [HealOS API](/introduction), so every command uses the same API keys, scopes and [rate limits](/rate-limiting) as your own integration. It works the same for people at a terminal and for scripts or AI agents (`--json`). ## Install Requires Node.js 18 or later (or Bun). ```bash npm theme={null} npm install -g @healos/cli ``` ```bash bun theme={null} bun add -g @healos/cli ``` ```bash pnpm theme={null} pnpm add -g @healos/cli ``` ```bash yarn theme={null} yarn global add @healos/cli ``` Or run it without installing: ```bash npx theme={null} npx @healos/cli@latest whoami ``` ```bash bunx theme={null} bunx @healos/cli@latest whoami ``` Check the install with `healos --version`. ### Standalone binary Each release can also ship a single `healos` binary that needs no Node.js, for macOS (Apple silicon and Intel), Linux x64 and Windows x64, with a `SHA256SUMS` file. Check a download before you run it: ```bash theme={null} sha256sum --check --ignore-missing SHA256SUMS # macOS: shasum -a 256 --check --ignore-missing SHA256SUMS chmod +x healos-darwin-arm64 && mv healos-darwin-arm64 /usr/local/bin/healos ``` The binaries are not yet code-signed. On macOS, clear the download quarantine flag (`xattr -d com.apple.quarantine /usr/local/bin/healos`) or install from npm instead. ### Updating `healos update` tells you whether a newer version is out and how to upgrade the copy you have (the npm command, or the release binary to download). It asks the public npm registry and sends no API key. It does not replace the binary itself. With npm, `npm install -g @healos/cli@latest` updates in place. ## Sign in ```bash theme={null} healos login ``` This opens HealOS in your browser. Approve the request and the CLI saves a new API key on this machine. The key is labeled `CLI · · ` in **Settings → API keys** and expires after 90 days. The key is **read-only by default**. The approval page shows exactly which scopes it asks for. To let the CLI create or change data, ask for more: ```bash theme={null} healos login --scopes all # every scope healos login --scopes patients:read,notes:write # only these scopes ``` > [!NOTE] > > Only **organization admins** can approve a CLI sign-in, because API keys are organization-wide. If you are a member, ask an admin to create a key for you in **Settings → API keys**, then pass it on standard input: > > ```bash theme={null} > pbpaste | healos login --api-key - > ``` > > `--api-key hlsk_...` also works, but the CLI warns you: a key typed on the command line ends up in your shell history. ```bash theme={null} healos whoami # user, organization, scopes and key expiry healos logout # removes the key from this machine ``` `logout` does not revoke the key. Revoke it in **Settings → API keys**. **Where the key is stored:** the macOS Keychain when available, otherwise `~/.config/healos/credentials.json`, readable only by you. The CLI refuses to use a credentials file that other users can read. **Several accounts:** add `--profile ` to `login` and to any command, for example `healos login --profile clinic-b`. ## Commands Every command has `--help`, for example `healos notes create --help`. Lists take `--page`, `--limit` and `--all` (every page). ### Patients and documents | Command | What it does | | - | - | | `healos patients list [--q ]` | List patients | | `healos patients search ` | Find patients by name | | `healos patients get ` | Show one patient | | `healos patients create --first-name --last-name [--dob --phone --email --mrn]` | Create a patient | | `healos patients update [--phone --email ...]` | Update a patient | | `healos patients delete ` | Delete a patient (asks to confirm) | | `healos documents list --patient ` | List a patient's documents and their extraction status | | `healos documents upload --patient ` | Upload a PDF, JPG, PNG or DOCX (up to 10 MB) | | `healos documents extract --patient ` | Run or retry text extraction | | `healos documents delete --patient ` | Delete a document (asks to confirm) | ### Clinical notes | Command | What it does | | - | - | | `healos notes create --text "..." [--patient ] [--wait]` | Generate a note from text | | `healos notes create --audio visit.wav [--patient ] [--wait]` | Generate a note from a recording | | `healos notes from-documents --patient [--wait]` | Generate a note from the patient's documents | | `healos notes list [--patient --from --to]` | List notes | | `healos notes get ` | Show one note | | `healos notes export [--format json\|csv\|ndjson] [--out ]` | Export notes, with the same filters as `list` | | `healos notes regenerate [--template ]` | Regenerate a session's note | | `healos sessions get ` | Show a visit session and its status | | `healos sessions update --patient ` | Assign a session to a patient | | `healos sessions delete ` | Move a session and its notes to the recycle bin (asks first unless `--yes`; never permanent) | | `healos sessions restore ` | Take a session out of the recycle bin | | `healos templates list` | List note templates | `notes create` returns as soon as the note is queued. Add `--wait` to wait for the finished note (up to 5 minutes, or `--timeout `). ### Scheduling, eligibility and prior auth | Command | What it does | | - | - | | `healos providers list` | List providers in your organization | | `healos appointments list [--date]` | List appointments | | `healos appointments get ` | Show one appointment | | `healos appointments create --patient --type --visit-type --start --duration` | Create an appointment | | `healos appointments update [--start --duration --status ...]` | Update an appointment | | `healos appointments delete ` | Delete an appointment (asks to confirm) | | `healos eligibility check --payer --npi --provider-name --patient ` | Run an insurance eligibility check | | `healos eligibility list`, `healos eligibility get ` | Past eligibility checks | | `healos benefits payers search ` | Find a payer ID | | `healos prior-auth list [--status --decision]` | List prior-auth requests | | `healos prior-auth get `, `healos prior-auth events ` | A request and its history | | `healos prior-auth workflows` | Available prior-auth workflows | | `healos prior-auth check-status` | Refresh Availity statuses (at most every 10 minutes) | ### AI Receptionist | Command | What it does | | - | - | | `healos receptionist calls list [--from --to --outcome --search]` | List calls, newest first, with outcome and summary | | `healos receptionist calls get ` | Show one call with its extracted details | | `healos receptionist calls transcript ` | Print the transcript, one line per turn | | `healos receptionist calls recording --out ` | Download the recording (file created with mode 0600) | | `healos receptionist tasks list [--status --category --search --from --to]` | List inbox tasks, newest first | | `healos receptionist tasks get ` | Show one inbox task | | `healos receptionist tasks create --title [--category --notes --due --patient --call --assignee]` | Add an inbox task | | `healos receptionist tasks update [--title --status --category --notes --due ...]` | Change the fields you pass | | `healos receptionist tasks resolve ` | Mark a task done | | `healos receptionist tasks delete ` | Delete a task (asks first unless `--yes`) | | `healos webhooks list` | List your webhooks | | `healos webhooks get ` | Show one webhook | | `healos webhooks create --name --url --event [--format --description --header "Name: value"]` | Register a webhook | | `healos webhooks update [--url --event --name --header ... --pause / --resume]` | Change a webhook; `--header` replaces every header | | `healos webhooks delete ` | Delete a webhook (asks first unless `--yes`) | ### EHR actions | Command | What it does | | - | - | | `healos ehr actions list [--ehr athena]` | List the [EHR actions](/ehr-actions/overview) HealOS supports | | `healos ehr actions get ` | Show one action, for example `athena.search_patients` | | `healos ehr connections` | Which EHRs your organization has connected | These need the `ehr:read` scope. ## Examples ```bash theme={null} # Find a patient and generate a note for them healos patients search "Testy Example" healos notes create --patient --text-file visit.txt --wait # Upload a referral letter, then write a note from the patient's documents healos documents upload referral.pdf --patient healos notes from-documents --patient --wait # Check eligibility healos benefits payers search "Aetna" healos eligibility check --payer --npi 1234567893 --provider-name "Dr. Example" --patient # JSON for scripts healos patients list --all --json | jq '.data[].id' ``` ## Scripts, CI and AI agents * `--json` prints the raw API response. Errors go to stderr, also as JSON. * `HEALOS_API_KEY` uses a key without signing in, and takes precedence over the saved profile. * `--dry-run` prints the request it would send and sends nothing. * Writes ask for confirmation, and deletes always do. Pass `--yes` to skip the prompt. Without a terminal to ask on, they are refused unless `--yes` is passed. * The CLI only sends your key over HTTPS to HealOS, and never follows a redirect to another host. * `healos mcp` runs an MCP server for Claude, Cursor and other AI agents, read-only unless you pass `--allow-writes` (it ships in the next CLI release). See [Use HealOS from an AI agent](/ai-agents#use-healos-from-an-ai-agent-mcp). | Exit code | Meaning | | - | - | | `0` | Success | | `1` | Bad flags or cancelled | | `2` | The API rejected the request (4xx) | | `3` | Server or network error (5xx), or `--wait` timed out | | `4` | Not signed in, invalid key, or missing permission | # Clinical Notes Source: https://docs.healos.ai/clinical-notes Read, regenerate and bulk-export clinical notes, with transcript and patient context The notes endpoints let you pull clinical notes out of Healos — one at a time, by session, as a filtered list, or as a bulk export. Every note carries its medical codes, and you can request the session transcript and patient context alongside it. All notes endpoints require the `notes:read` scope. Access is scoped to your organization: you see notes authored by members of your org. > [!NOTE] > > `patient_id` is a BigInt serialized as a string — treat it as an opaque > string, same as elsewhere in the API. See [Making Requests](/making-requests). ## List Notes Lightweight, paginated list. Use it to discover note IDs; fetch full content with [Get a Note](#get-a-note) or [Export](#export-notes). ```bash theme={null} curl "https://api.healos.ai/ext-api/v1/notes?limit=20" \ -H "X-API-Key: hlsk_your_key_here" ``` ```json theme={null} { "data": [ { "id": "9b2d4f6a-1c3e-4a5b-8d7f-0e1a2b3c4d5e", "patient_id": "481926357104938271", "session_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "note_type": "clinical_visit", "specialty": "Cardiology", "template_id": "7a1c...", "template_name": "Follow-Up Patient Visit", "model": "balanced", "created_at": "2026-03-15T09:30:00.000Z", "updated_at": "2026-03-15T10:00:00.000Z" } ], "meta": { "page": 1, "limit": 20, "total_pages": 1 } } ``` Every note includes `model`: the note quality that produced it (`fast`, `balanced` or `detailed`, the same choices as the `model` option when you generate a note). It is read-only. It is `null` for older notes that have no record of it, and for a basic fallback note that no model wrote. ### Filters Both `GET /notes` and `GET /notes/export` accept the same filters: | Query param | Description | | - | - | | `patient_id` | Notes for one patient | | `session_id` | Notes for one session | | `template_id` | Notes generated from a template | | `created_by` | Notes authored by a specific clinician (must be in your org) | | `note_type` | e.g. `clinical_visit` | | `from` | Created on/after this date (ISO 8601, e.g. `2026-01-01`) | | `to` | Created on/before this date (ISO 8601) | ```bash theme={null} curl "https://api.healos.ai/ext-api/v1/notes?patient_id=481926357104938271&from=2026-01-01&to=2026-06-30" \ -H "X-API-Key: hlsk_your_key_here" ``` ## Get a Note Returns the full note — `content`, `problems`, `procedures`, `icd10_codes`, `cpt_codes` — with the session transcript and patient context embedded by default. ```bash theme={null} curl https://api.healos.ai/ext-api/v1/notes/9b2d4f6a-1c3e-4a5b-8d7f-0e1a2b3c4d5e \ -H "X-API-Key: hlsk_your_key_here" ``` ```json theme={null} { "data": { "id": "9b2d4f6a-1c3e-4a5b-8d7f-0e1a2b3c4d5e", "patient_id": "481926357104938271", "session_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "note_type": "clinical_visit", "specialty": "Cardiology", "template_name": "Follow-Up Patient Visit", "model": "balanced", "created_at": "2026-03-15T09:30:00.000Z", "content": "Chief complaint: ...", "problems": ["Hypertension"], "procedures": ["12-lead ECG"], "icd10_codes": { "I10": "Essential hypertension" }, "cpt_codes": { "Office visit": [{ "code": "99213", "description": "Established patient" }] }, "transcript": { "text": "Doctor: ... Patient: ...", "summary": "Patient stable on current regimen.", "title": "Follow-up visit", "status": "completed", "session_date": "2026-03-15T09:00:00.000Z", "start_time": "2026-03-15T09:00:00.000Z", "end_time": "2026-03-15T09:30:00.000Z" }, "patient": { "id": "481926357104938271", "name": "Maria Santos", "pronouns": "she/her", "date_of_birth": "1985-04-12", "client_history": { "medical_history": "...", "family_history": "...", "social_history": "...", "previous_treatment": "..." } } } } ``` ### Controlling embedded blocks The note body and medical codes are always returned. Control the heavier embedded blocks with the `include` query param — a comma-separated list of `transcript` and `patient`. It defaults to both. ```bash theme={null} # Omit both embedded blocks (note body + codes only) curl "https://api.healos.ai/ext-api/v1/notes/{noteId}?include=" \ -H "X-API-Key: hlsk_your_key_here" # Transcript only curl "https://api.healos.ai/ext-api/v1/notes/{noteId}?include=transcript" \ -H "X-API-Key: hlsk_your_key_here" ``` When excluded, `transcript` and `patient` are returned as `null`. ## Notes by Session Returns every note for a session, plus the session's transcript/summary and the patient context, in one call. Returns `404` if the session isn't owned by your organization. ```bash theme={null} curl https://api.healos.ai/ext-api/v1/sessions/f47ac10b-58cc-4372-a567-0e02b2c3d479/notes \ -H "X-API-Key: hlsk_your_key_here" ``` ```json theme={null} { "data": { "session": { "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "patient_id": "481926357104938271", "transcript": { "text": "...", "summary": "...", "title": "Follow-up visit" } }, "patient": { "id": "481926357104938271", "name": "Maria Santos" }, "notes": [ { "id": "9b2d...", "content": "...", "icd10_codes": {} } ] } } ``` ## Regenerate a Note `POST /sessions/{sessionId}/notes/regenerate` rebuilds the session's note from its transcript. It needs the `notes:write` scope, and only `completed` sessions can be regenerated (others return `409`). The call returns `202` straight away; the new note is usually ready in under a minute. | Field | Where | Required | Description | | - | - | - | - | | `sessionId` | Path | Yes | The session whose note you want rebuilt. | | `template_id` | Body | No | UUID of the template to use. Defaults to the session's current template. Must be a built-in template or one owned by your organization (otherwise `404`). | | `model` | Body | No | Note quality, the same choices as the HealOS dashboard: `fast`, `balanced` or `detailed`. Any other value returns `400`. | | `Idempotency-Key` | Header | No | Repeated requests with the same key for the same session collapse onto one regeneration (deduplicated for at least an hour). | ```bash theme={null} curl -X POST https://api.healos.ai/ext-api/v1/sessions/f47ac10b-58cc-4372-a567-0e02b2c3d479/notes/regenerate \ -H "X-API-Key: $HEALOS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "template_id": "0be8b728-5d7c-4a8e-9f61-2f3c1d4e5a6b", "model": "detailed" }' ``` ```json theme={null} { "data": { "session_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "status": "queued" }, "message": "Note regeneration queued. A NOTE_REGENERATED webhook fires when the new note is ready." } ``` To know when the new note is ready, register a `NOTE_REGENERATED` [webhook](/webhooks), or poll [Notes by Session](#notes-by-session). ## Export Notes `GET /notes/export` returns **all** notes matching the [filters](#filters) above (no pagination), with full content, codes, transcript, and patient context on each note. Pick the format with `?format=`: | `format` | Response | Notes | | - | - | - | | `json` (default) | `{ "data": [...], "meta": { "count", "truncated" } }` | Capped at 1000 notes | | `csv` | `text/csv` attachment | Flattened, one row per note. Capped at 1000 notes | | `ndjson` | `application/x-ndjson` stream | One JSON note per line. **No cap** — use this for large pulls | ```bash theme={null} # JSON (default), filtered to one patient curl "https://api.healos.ai/ext-api/v1/notes/export?patient_id=481926357104938271" \ -H "X-API-Key: hlsk_your_key_here" # CSV download curl "https://api.healos.ai/ext-api/v1/notes/export?format=csv&from=2026-01-01" \ -H "X-API-Key: hlsk_your_key_here" -o notes.csv # NDJSON stream (recommended for full exports) curl "https://api.healos.ai/ext-api/v1/notes/export?format=ndjson" \ -H "X-API-Key: hlsk_your_key_here" -o notes.ndjson ``` > [!WARNING] > > `json` and `csv` are capped at **1000 notes**. When the result is capped, > `json` sets `meta.truncated: true` and `csv` sets the `X-Result-Truncated` > header. To pull more than 1000 notes, narrow the date range with `from`/`to`, > or use `format=ndjson`, which streams the full set with no cap. The CSV columns are: `note_id`, `patient_id`, `patient_name`, `session_id`, `session_date`, `note_type`, `specialty`, `created_at`, `problems`, `procedures`, `icd10_codes`, `cpt_codes`, `content`, `transcript`, `model`. Array and code fields are flattened into a single cell. ## Generate a Note from Documents `POST /patients/{patientId}/notes/from-documents` writes a clinical note from the patient's uploaded documents alone, with no recording. It creates a new session for the patient and queues generation, so you get a `session_id` back straight away (`202`); the note is usually ready in under a minute. It needs the `notes:write` scope. Upload the documents first and wait for extraction to finish (see the [document upload flow](/webhooks#document-upload-flow)). At least one document must have `status: "completed"` with extracted text, otherwise the call returns `422` and no session is created. | Field | Where | Required | Description | | - | - | - | - | | `patientId` | Path | Yes | A patient in your organization (otherwise `404`). | | `template_id` | Body | No | UUID of the template to use. Defaults to the clinician's default template. Must be a built-in template or one owned by your organization (otherwise `404`). | | `model` | Body | No | Note quality, the same choices as the HealOS dashboard: `fast`, `balanced` or `detailed`. Any other value returns `400`. | ```bash theme={null} curl -X POST https://api.healos.ai/ext-api/v1/patients/481926357104938271/notes/from-documents \ -H "X-API-Key: $HEALOS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "balanced" }' ``` ```json theme={null} { "data": { "session_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "status": "queued" }, "message": "Note generation queued. A NOTE_CREATED webhook fires when the note is ready." } ``` To know when the note is ready, register a `NOTE_CREATED` [webhook](/webhooks), or poll [Notes by Session](#notes-by-session) with the returned `session_id`. > [!WARNING] > > Each call creates a new session and a new note. Don't retry a request that > already returned `202`; check the session's notes instead. ## Generate a Note from Text `POST /notes/from-text` writes a clinical note from text you send: typed visit notes, a dictation or a transcript from your own recorder. It creates a session, queues generation and returns its `session_id` straight away (`202`). It needs the `notes:write` scope and uses one of your organization's Scribe sessions (`402` when none are left). | Field | Required | Description | | - | - | - | | `text` | Yes | The visit text, up to 100,000 characters. | | `patient_id` | No | A patient in your organization (otherwise `404`). Omit it to create an **unassigned** session and [assign the patient later](#assign-a-patient-to-a-session). | | `template_id` | No | UUID of the template to use. Defaults to the clinician's default template, then New Patient Visit. Must be a built-in template or one owned by your organization (otherwise `404`). | | `model` | No | Note quality: `fast`, `balanced` or `detailed`. | ```bash theme={null} curl -X POST https://api.healos.ai/ext-api/v1/notes/from-text \ -H "X-API-Key: $HEALOS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "patient_id": "481926357104938271", "text": "Knee pain for two weeks, worse on stairs. No swelling. Ibuprofen 400 mg BID. Plan: physiotherapy, follow up in 4 weeks.", "model": "balanced" }' ``` ```json theme={null} { "data": { "session_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "status": "queued", "patient_id": "481926357104938271" }, "message": "Note generation queued. A NOTE_CREATED webhook fires when the note is ready." } ``` Sending the same text again while the first request is still being processed returns `409`. ## Generate a Note from Audio `POST /notes/from-audio` takes a recording of the visit as `multipart/form-data`, transcribes it and writes the clinical note, the same as uploading audio in the HealOS dashboard. It returns `202` with the `session_id` as soon as the file is stored; transcription and the note follow in the background (usually a few minutes for a 20-minute visit). It needs the `notes:write` scope and uses one Scribe session. | Field | Required | Description | | - | - | - | | `file` | Yes | The recording: `.wav`, `.mp3`, `.m4a`, `.mp4`, `.aac`, `.flac`, `.ogg` or `.webm`, up to 100 MB (`413` above that). Long recordings are split and transcribed in parts. | | `patient_id` | No | A patient in your organization. Omit it for an unassigned session. | | `template_id` | No | As for [text](#generate-a-note-from-text). | | `model` | No | `fast`, `balanced` or `detailed`. | ```bash theme={null} curl -X POST https://api.healos.ai/ext-api/v1/notes/from-audio \ -H "X-API-Key: $HEALOS_API_KEY" \ -F "file=@visit.wav" \ -F "patient_id=481926357104938271" \ -F "model=balanced" ``` The response has the same shape as from text. Track progress with [Session Details](#session-details) (`status` moves from `finalizing` to `completed`, or `failed` if the audio had no usable speech), or register a `NOTE_CREATED` [webhook](/webhooks). > [!WARNING] > > Each call creates a new session. Don't retry a request that already returned > `202`; check the session instead. ## Session Details `GET /sessions/{sessionId}` returns a session's metadata without the note content: the encounter date and times, duration, status, the template it was set up with, the clinician who owns it, a short patient summary and the ids of the notes generated for it. It needs the `notes:read` scope and returns `404` if the session isn't owned by your organization. ```bash theme={null} curl https://api.healos.ai/ext-api/v1/sessions/f47ac10b-58cc-4372-a567-0e02b2c3d479 \ -H "X-API-Key: $HEALOS_API_KEY" ``` ```json theme={null} { "data": { "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "title": "Follow-up visit", "status": "completed", "encounter_date": "2026-10-01T15:00:00.000Z", "start_time": "2026-10-01T15:02:00.000Z", "end_time": "2026-10-01T15:23:00.000Z", "duration_seconds": 1260, "source": "live_saved", "ehr_appointment_id": null, "template": { "id": "0be8b728-5d7c-4a8e-9f61-2f3c1d4e5a6b", "name": "SOAP Note" }, "provider": { "id": "aaaaaaa1-0000-0000-0000-000000000001", "name": "Dr. Jane Smith" }, "patient": { "id": "481926357104938271", "name": "Maria Santos", "first_name": "Maria", "last_name": "Santos", "date_of_birth": "1985-04-12", "mrn": "MRN-00123", "external_id": "pt-8812" }, "note_ids": ["9b2d6c1e-3f4a-4b5c-8d7e-1a2b3c4d5e6f"], "updated_at": "2026-10-01T15:25:00.000Z" } } ``` | Field | Description | | - | - | | `encounter_date` | The visit date, or the recording start when no date was set. | | `duration_seconds` | Seconds between `start_time` and `end_time`; `null` until both are set. | | `template` | The template the session was set up with. If the template no longer exists, `name` falls back to the session's note type. | | `provider` | The session owner. The `id` matches [`GET /providers`](/api-reference). | | `patient` | A short summary. Use [Notes by Session](#notes-by-session) for the full patient context and transcript. | | `note_ids` | Notes for this session, newest first. Fetch each with [Get a Note](#get-a-note). | ## Assign a Patient to a Session `PATCH /sessions/{sessionId}` files a session and its notes under a patient. Use it for a session created without `patient_id` (from text or audio), or to correct a session's patient. It needs the `notes:write` scope. | Field | Required | Description | | - | - | - | | `patient_id` | Yes | A patient in your organization (otherwise `404`). | ```bash theme={null} curl -X PATCH https://api.healos.ai/ext-api/v1/sessions/f47ac10b-58cc-4372-a567-0e02b2c3d479 \ -H "X-API-Key: $HEALOS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "patient_id": "481926357104938271" }' ``` ```json theme={null} { "data": { "session_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "patient_id": "481926357104938271", "patient_changed": true } } ``` A `NOTE_UPDATED` [webhook](/webhooks) fires for each of the session's notes. Sending the patient the session already has returns `patient_changed: false`. A session whose note was already sent to an EHR can't move to another patient (`409`). # HL7 feeds Source: https://docs.healos.ai/connections/hl7 Connect a hospital or EHR interface engine to HealOS over HL7 v2: what your team does and what HealOS does HealOS accepts **inbound HL7 v2 feeds** from hospital and EHR interface engines (for example MEDITECH, or an engine such as Mirth, Corepoint, Cloverleaf or Rhapsody). The feed keeps HealOS's patients, appointments and results current, so AI Scribe starts each visit with the patient's recent labs, imaging and documents. > [!NOTE] > > HL7 is **inbound only**. HealOS does not send notes or results back over HL7. Finished notes reach the chart through the EHR's own connection or the [Chrome extension](/guides/scribe/chrome-extension). ## What HealOS does with each message | Message | HealOS does | Key fields | | - | - | - | | **ADT** (admit, register, update) | Creates or updates the patient | PID-3 MRN (the match key), PID-5 name, PID-7 date of birth, PID-8 sex, PID-13 phone | | **SIU** (scheduling) | Updates the patient, then creates or updates the appointment and assigns it to the HealOS user mapped to the provider | SCH-1 appointment id (else PV1-19), SCH-11 start, SCH-9 duration (default 30 min), SCH-7 type, SCH-25 status, AIP-3 provider | | **ORM** (orders) | Creates or updates the patient | PID segment | | **ORU** (results) | Stores the report and its observations, grouped as lab, microbiology, blood bank, pathology, radiology or provider document | OBR, OBX-3/5/6/7/8/14, NTE | | Anything else | Kept, not processed. Ask HealOS if you need another message type | MSH-9 | Patients are matched within your organization by MRN, so the same MRN from your feed always updates the same HealOS patient. **In AI Scribe**, recent results appear as visit context, grouped as Recent Labs, Imaging, Pathology, Microbiology, Blood Bank and Provider Documents. By default HealOS uses the last 90 days, up to 30 reports; HealOS can tune this for your organization. ## How the feed reaches HealOS | Option | Use it when | Your side | HealOS side | | - | - | - | - | | **A. HTTPS from your interface engine** (recommended) | Your engine can send HTTPS with OAuth 2.0 | Point an outbound channel at the endpoint HealOS gives you, using the service credentials HealOS issues | A dedicated, per-customer HL7 store and delivery pipeline; issues the credentials | | **B. MLLP over a site-to-site VPN** | Your system speaks only MLLP over TCP, or policy requires IPsec | An IPsec VPN tunnel to HealOS, and an MLLP channel through it | The VPN endpoint, the MLLP listener and the same per-customer pipeline | Your system gets the HL7 acknowledgement from the receiving endpoint. HealOS processes each message after it arrives: a temporary failure is retried automatically, and a message that still fails is set aside for review instead of being lost. ## Who does what | Step | Your IT / interface team | HealOS | | - | - | - | | 1. Scope | Tell us what sends the feed (MEDITECH directly or an interface engine), whether it can send HTTPS, whether IPsec is required, and which message types | Recommends option A or B and confirms which messages HealOS will use | | 2. Provision | For option B: VPN details your network team needs to exchange | Creates your dedicated HL7 store and pipeline for test and production, and sends you a **tenant code** | | 3. Bind | An organization admin opens **Integrations → Connect HL7 Feed** in HealOS and pastes the tenant code | Links the feed to your organization. Messages are not processed until the feed is active and linked | | 4. Test | Send test messages with **test patients only**: one ADT, one SIU and one ORU | Confirms the patient, appointment and results appear correctly; maps your providers (AIP-3) to HealOS users | | 5. Go live | Switch the channel to production | Watches the first days of traffic with you | ## Monitoring and support * HealOS tracks when it last received each message type. If the feed goes quiet, HealOS shares the last-received time per message type with your interface team, which is usually the fastest way to find a stopped channel. * Messages that fail processing are kept and reviewed; send corrected messages again as usual. * To add a message type (for example pharmacy), contact HealOS: each new type needs a handler before it is used. ## Security * Option A uses TLS with OAuth service credentials; option B carries MLLP inside an IPsec tunnel. * Each customer has its own HL7 store and pipeline; HealOS accepts messages only from your configured feed and links them only to your organization. * Use test patients for all testing; HL7 messages contain PHI. # Connection methods Source: https://docs.healos.ai/connections/overview How HealOS connects to EHRs and hospital systems, what you provide and what HealOS does HealOS connects to each EHR in one of six ways. The method decides what you hand over, how fast setup is, and what keeps working when nobody is at a desk. Each [EHR page](/ehr-actions/overview) names its method and lists exactly what to provide. | Method | How it works | You provide | HealOS does | Used by | | - | - | - | - | - | | **Official API (OAuth)** | HealOS calls the EHR's own API with a token you authorize | Approve HealOS in the EHR's consent screen; some EHRs first need an API app or API access from the vendor | Refreshes tokens, retries rate limits, never asks for a password | Acuity Scheduling, DrChrono, Elation, Halaxy | | **Official API (API credentials)** | HealOS calls the EHR's API with a key or API user you create | An API key or API user, issued in the EHR or by its support team | Stores the credentials encrypted; uses them only for the actions you enable | Cerbo, Hint, ModMed, Tebra, athenahealth (note sending), Acuity Scheduling (API key option) | | **SMART on FHIR** | Standards-based FHIR connection approved per health system | Your FHIR base URL (and tenant ID on Oracle Health); your health system enables the HealOS app; a clinician signs in once | Reads the patient, encounter and practitioner; writes the note back as a document | Epic, Oracle Health (Cerner) | | **HealOS cloud browser** | For EHRs without a usable API, HealOS signs in to the EHR's web app from a secure, US-based cloud browser and acts like a careful staff member | A login (ideally a dedicated user), plus the two-factor setup the EHR uses: an authenticator secret, or a code inbox or phone set up with HealOS | Verifies the login before saving; stores credentials encrypted; keeps one signed-in session per practice and renews it during business hours; generates or reads two-factor codes itself | athenahealth, CharmHealth, CurveHero, eClinicalWorks, NextGen Office, Practice Fusion, SimplePractice, TheraNest, TherapyNotes, WebPT | | **Chrome extension** | The HealOS extension works inside the clinician's own signed-in EHR tab | Install the [extension](/guides/scribe/chrome-extension) and keep the EHR open in Chrome | Fills AI Scribe notes into the open note for the clinician to review and sign; nothing about the EHR login reaches HealOS | AdvancedMD, CureMD, Cliniko, Kalix, Office Ally and others; also many API EHRs for note filling | | **HL7 feed** | The hospital's interface engine sends HL7 v2 messages to HealOS | An interface-engine feed over HTTPS, or MLLP over a site-to-site VPN | Builds patients, appointments and results from the feed for AI Scribe context | Hospital systems such as MEDITECH. See [HL7 feeds](/connections/hl7) | ## Choosing a method * **An official API is the most durable.** Setup can take days when the vendor must grant API access or a fee applies, but it keeps working through password changes. * **The cloud browser is the fastest to set up** (minutes, with a login), and the only option for EHRs without a usable API. Give HealOS a dedicated user: some EHRs allow one active session per login, and a shared user's password changes break the connection. * **The Chrome extension needs no credentials**, but it works only while the clinician's EHR tab is open, so it suits note filling, not after-hours phone calls. ## Where you connect | Product | Where in HealOS | Who can connect | | - | - | - | | AI Frontdesk (AI Receptionist) | **AI Frontdesk → Integrations → Connect an EHR** ([guide](/guides/receptionist/connect-your-ehr)) | Organization admins | | AI Scribe | **Integrations** (AI Scribe Integrations), or the [Chrome extension](/guides/scribe/chrome-extension) | Clinicians and admins | | HL7 feed | **Integrations → Connect HL7 Feed**, with the tenant code HealOS gives you | Organization admins | Other ways the AI Frontdesk can book without an EHR connection: [HealOS Scheduling](/guides/receptionist/overview) and [Google Calendar](/guides/receptionist/google-calendar). ## Security * Credentials are encrypted at rest and used only by the HealOS service that runs your enabled actions. They are never returned by the HealOS API: [`GET /ehr/connections`](/api-reference/ehr/list-your-ehr-connections) reports connection status only. * Every action runs against your live EHR, never a sandbox, and writes that change appointments are enabled per practice. See [Security](/security). # Acuity Scheduling Source: https://docs.healos.ai/ehr-actions/acuity What AI Frontdesk and AI Scribe do in Acuity Scheduling, and its 7 API actions ## What HealOS does in Acuity Scheduling ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in Acuity Scheduling during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | | Look up upcoming appointments | Yes | | Cancel an appointment | Yes | | Reschedule an appointment | Yes | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe AI Scribe notes cannot be sent to Acuity Scheduling yet; copy the note from HealOS. ### Connection **Method:** Official API (OAuth), Official API (API credentials). [How the methods compare](/connections/overview). **You provide** * Sign in to Acuity in the OAuth window from **AI Frontdesk → Integrations → Connect an EHR**. * Or paste your Acuity User ID and API key (Acuity: Settings → Integrations → API). API keys need an Acuity plan that includes API access. **HealOS does** * Uses Acuity's official scheduling API with your authorization. * Connecting with one method replaces the other. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 7 actions in Acuity Scheduling. Action names (`acuity.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `acuity.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `acuity.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `acuity.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `acuity.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | | **List upcoming appointments** `acuity.list_appointments` | List a patient's upcoming appointments. | read | `patient_id` | `appointments` | | **Cancel appointment** `acuity.cancel_appointment` | Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id` | `appointment_id`, `status` | | **Reschedule appointment** `acuity.reschedule_appointment` | Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id`, `slot_id`, `start_at_utc`, `duration_minutes` | `appointment_id`, `start_at_utc` | ## Search patients `acuity.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `acuity.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** not run by HealOS before creating **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `acuity.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `acuity.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | ## List upcoming appointments `acuity.list_appointments` · scheduling · version 1 List a patient's upcoming appointments. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | **Outputs** | Field | Type | Description | | - | - | - | | `appointments` | array of object | | Each item in `appointments`: | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | Start as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `end_at_utc` | string | End as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `date` | string | Start date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Start time in the practice's time zone. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `provider_name` | string | Provider display name. Null when the EHR does not return it. | | `reason` | string | Visit reason or type. Null when the EHR does not return it. | ## Cancel appointment `acuity.cancel_appointment` · scheduling · version 1 Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `status` | string | The appointment's new status. | ## Reschedule appointment `acuity.reschedule_appointment` · scheduling · version 1 Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | New start (ISO 8601 UTC). Null when the EHR does not return it. | # AdvancedMD Source: https://docs.healos.ai/ehr-actions/advancedmd What AI Frontdesk and AI Scribe do in AdvancedMD ## What HealOS does in AdvancedMD ### AI Frontdesk The AI Frontdesk (AI Receptionist) does not work in AdvancedMD yet. ### AI Scribe How a finished AI Scribe note gets into AdvancedMD: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the AdvancedMD note open in the clinician's browser | Yes | ### Connection **Method:** Chrome extension. [How the methods compare](/connections/overview). **You provide** * Install the [HealOS Chrome extension](/guides/scribe/chrome-extension) and sign in to HealOS in it. * Open the patient's note in the EHR in the same Chrome window. **HealOS does** * Fills the finished AI Scribe note into the note page open in the clinician's browser; the clinician reviews and signs it in the EHR. * Nothing is stored on HealOS's side for this EHR: the extension works in the clinician's own signed-in session. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. # athenahealth Source: https://docs.healos.ai/ehr-actions/athena What AI Frontdesk and AI Scribe do in athenahealth, and its 5 API actions ## What HealOS does in athenahealth ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in athenahealth during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | | Look up upcoming appointments | Yes | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe How a finished AI Scribe note gets into athenahealth: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | On request | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the athenahealth note open in the clinician's browser | Yes | ### Connection **Method:** HealOS cloud browser, Official API (API credentials), Chrome extension. [How the methods compare](/connections/overview). **You provide** * For AI Frontdesk: a dedicated athenaOne user (username and password) and its authenticator (TOTP) secret, pasted as the base32 key, an `otpauth://` link or the QR code image, in **AI Frontdesk → Integrations → Connect an EHR**. * For sending AI Scribe notes from HealOS (on request): athenahealth API credentials (Client ID, Client Secret and Practice ID) in **Integrations** (AI Scribe Integrations). **HealOS does** * Checks the sign-in before saving anything: a login that fails is not stored. * Stores the credentials encrypted and signs in from a secure, US-based cloud browser. * Keeps one signed-in session per practice and renews it during business hours, so calls don't wait for a login. * Generates the authenticator codes itself, so no one has to read codes to HealOS. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 5 actions in athenahealth. Action names (`athena.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `athena.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `athena.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `athena.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `athena.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | | **List upcoming appointments** `athena.list_appointments` | List a patient's upcoming appointments. | read | `patient_id` | `appointments` | ## Search patients `athena.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `athena.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** searches by last name and date of birth first, and links an exact single match instead of creating a chart * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `athena.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `athena.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | ## List upcoming appointments `athena.list_appointments` · scheduling · version 1 List a patient's upcoming appointments. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | **Outputs** | Field | Type | Description | | - | - | - | | `appointments` | array of object | | Each item in `appointments`: | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | Start as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `end_at_utc` | string | End as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `date` | string | Start date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Start time in the practice's time zone. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `provider_name` | string | Provider display name. Null when the EHR does not return it. | | `reason` | string | Visit reason or type. Null when the EHR does not return it. | # CareTracker Source: https://docs.healos.ai/ehr-actions/caretracker What AI Frontdesk and AI Scribe do in CareTracker ## What HealOS does in CareTracker ### AI Frontdesk The AI Frontdesk (AI Receptionist) does not work in CareTracker yet. ### AI Scribe How a finished AI Scribe note gets into CareTracker: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the CareTracker note open in the clinician's browser | Yes | ### Connection **Method:** Chrome extension. [How the methods compare](/connections/overview). **You provide** * Install the [HealOS Chrome extension](/guides/scribe/chrome-extension) and sign in to HealOS in it. * Open the patient's note in the EHR in the same Chrome window. **HealOS does** * Fills the finished AI Scribe note into the note page open in the clinician's browser; the clinician reviews and signs it in the EHR. * Nothing is stored on HealOS's side for this EHR: the extension works in the clinician's own signed-in session. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. # Cerbo Source: https://docs.healos.ai/ehr-actions/cerbo What AI Frontdesk and AI Scribe do in Cerbo, and its 8 API actions ## What HealOS does in Cerbo ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in Cerbo during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | | Look up upcoming appointments | Yes | | Cancel an appointment | On request | | Confirm an appointment | On request | | Reschedule an appointment | On request | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe How a finished AI Scribe note gets into Cerbo: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | On request | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the Cerbo note open in the clinician's browser | — | ### Connection **Method:** Official API (API credentials). [How the methods compare](/connections/overview). **You provide** * An API user from Cerbo's API User Management console: username, secret key, your Cerbo URL and the provider's NPI. * Enter them in **AI Frontdesk → Integrations → Connect an EHR** or **Integrations** (AI Scribe Integrations). **HealOS does** * Uses Cerbo's official API (HTTP Basic) with those credentials, stored encrypted. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 8 actions in Cerbo. Action names (`cerbo.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `cerbo.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `cerbo.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `cerbo.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `cerbo.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | | **List upcoming appointments** `cerbo.list_appointments` | List a patient's upcoming appointments. | read | `patient_id` | `appointments` | | **Cancel appointment** `cerbo.cancel_appointment` | Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id` | `appointment_id`, `status` | | **Confirm appointment** `cerbo.confirm_appointment` | Mark one of the patient's appointments as confirmed. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id` | `appointment_id`, `status` | | **Reschedule appointment** `cerbo.reschedule_appointment` | Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id`, `slot_id`, `start_at_utc`, `duration_minutes` | `appointment_id`, `start_at_utc` | ## Search patients `cerbo.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `cerbo.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** searches by last name and date of birth first, and links an exact single match instead of creating a chart **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `cerbo.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `cerbo.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | ## List upcoming appointments `cerbo.list_appointments` · scheduling · version 1 List a patient's upcoming appointments. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | **Outputs** | Field | Type | Description | | - | - | - | | `appointments` | array of object | | Each item in `appointments`: | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | Start as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `end_at_utc` | string | End as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `date` | string | Start date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Start time in the practice's time zone. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `provider_name` | string | Provider display name. Null when the EHR does not return it. | | `reason` | string | Visit reason or type. Null when the EHR does not return it. | ## Cancel appointment `cerbo.cancel_appointment` · scheduling · version 1 Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused > * **Per-practice enablement:** off until HealOS turns it on for the practice **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `status` | string | The appointment's new status. | ## Confirm appointment `cerbo.confirm_appointment` · scheduling · version 1 Mark one of the patient's appointments as confirmed. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused > * **Per-practice enablement:** off until HealOS turns it on for the practice **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `status` | string | The appointment's new status. | ## Reschedule appointment `cerbo.reschedule_appointment` · scheduling · version 1 Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused > * **Per-practice enablement:** off until HealOS turns it on for the practice **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | New start (ISO 8601 UTC). Null when the EHR does not return it. | # Oracle Health (Cerner) Source: https://docs.healos.ai/ehr-actions/cerner What AI Frontdesk and AI Scribe do in Oracle Health (Cerner), and its 5 API actions ## What HealOS does in Oracle Health (Cerner) ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in Oracle Health (Cerner) during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | | Look up upcoming appointments | Yes | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe How a finished AI Scribe note gets into Oracle Health (Cerner): | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | On request | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the Oracle Health (Cerner) note open in the clinician's browser | — | ### Connection **Method:** SMART on FHIR. [How the methods compare](/connections/overview). **You provide** * Your Oracle Health tenant ID and FHIR R4 base URL, in **AI Frontdesk → Integrations → Connect an EHR** or **Integrations** (AI Scribe Integrations); then the provider signs in to approve HealOS. **HealOS does** * Connects with SMART on FHIR v2 (authorization code with PKCE). > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 5 actions in Oracle Health (Cerner). Action names (`cerner.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `cerner.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `cerner.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `cerner.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `cerner.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | | **List upcoming appointments** `cerner.list_appointments` | List a patient's upcoming appointments. | read | `patient_id` | `appointments` | ## Search patients `cerner.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `cerner.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** searches by last name and date of birth first, and links an exact single match instead of creating a chart **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `cerner.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `cerner.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | ## List upcoming appointments `cerner.list_appointments` · scheduling · version 1 List a patient's upcoming appointments. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | **Outputs** | Field | Type | Description | | - | - | - | | `appointments` | array of object | | Each item in `appointments`: | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | Start as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `end_at_utc` | string | End as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `date` | string | Start date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Start time in the practice's time zone. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `provider_name` | string | Provider display name. Null when the EHR does not return it. | | `reason` | string | Visit reason or type. Null when the EHR does not return it. | # CharmHealth Source: https://docs.healos.ai/ehr-actions/charmhealth What AI Frontdesk and AI Scribe do in CharmHealth, and its 7 API actions ## What HealOS does in CharmHealth ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in CharmHealth during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | | Look up upcoming appointments | Yes | | Cancel an appointment | Yes | | Reschedule an appointment | Yes | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe How a finished AI Scribe note gets into CharmHealth: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the CharmHealth note open in the clinician's browser | Yes | ### Connection **Method:** HealOS cloud browser, Chrome extension. [How the methods compare](/connections/overview). **You provide** * A CharmHealth username and password and your Charm web address (for example `ehr2.charmtracker.com`), in **AI Frontdesk → Integrations → Connect an EHR**. **HealOS does** * Checks the sign-in before saving anything: a login that fails is not stored. * Stores the credentials encrypted and signs in from a secure, US-based cloud browser. * Keeps one signed-in session per practice and renews it during business hours, so calls don't wait for a login. **Limits** * CharmHealth limits daily sign-ins per account. HealOS reuses one signed-in session per practice, but heavy use can still exhaust them. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 7 actions in CharmHealth. Action names (`charmhealth.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `charmhealth.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `charmhealth.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `charmhealth.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `charmhealth.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | | **List upcoming appointments** `charmhealth.list_appointments` | List a patient's upcoming appointments. | read | `patient_id` | `appointments` | | **Cancel appointment** `charmhealth.cancel_appointment` | Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id` | `appointment_id`, `status` | | **Reschedule appointment** `charmhealth.reschedule_appointment` | Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id`, `slot_id`, `start_at_utc`, `duration_minutes` | `appointment_id`, `start_at_utc` | ## Search patients `charmhealth.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. * CharmHealth limits daily sign-ins per account. HealOS reuses one signed-in session per practice, but heavy use can still exhaust them. **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `charmhealth.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** not run by HealOS before creating * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. * CharmHealth limits daily sign-ins per account. HealOS reuses one signed-in session per practice, but heavy use can still exhaust them. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `charmhealth.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. * CharmHealth limits daily sign-ins per account. HealOS reuses one signed-in session per practice, but heavy use can still exhaust them. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `charmhealth.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. * CharmHealth limits daily sign-ins per account. HealOS reuses one signed-in session per practice, but heavy use can still exhaust them. **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | ## List upcoming appointments `charmhealth.list_appointments` · scheduling · version 1 List a patient's upcoming appointments. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. * CharmHealth limits daily sign-ins per account. HealOS reuses one signed-in session per practice, but heavy use can still exhaust them. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | **Outputs** | Field | Type | Description | | - | - | - | | `appointments` | array of object | | Each item in `appointments`: | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | Start as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `end_at_utc` | string | End as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `date` | string | Start date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Start time in the practice's time zone. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `provider_name` | string | Provider display name. Null when the EHR does not return it. | | `reason` | string | Visit reason or type. Null when the EHR does not return it. | ## Cancel appointment `charmhealth.cancel_appointment` · scheduling · version 1 Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. * CharmHealth limits daily sign-ins per account. HealOS reuses one signed-in session per practice, but heavy use can still exhaust them. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `status` | string | The appointment's new status. | ## Reschedule appointment `charmhealth.reschedule_appointment` · scheduling · version 1 Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. * CharmHealth limits daily sign-ins per account. HealOS reuses one signed-in session per practice, but heavy use can still exhaust them. **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | New start (ISO 8601 UTC). Null when the EHR does not return it. | # Cliniko Source: https://docs.healos.ai/ehr-actions/cliniko What AI Frontdesk and AI Scribe do in Cliniko ## What HealOS does in Cliniko ### AI Frontdesk The AI Frontdesk (AI Receptionist) does not work in Cliniko yet. ### AI Scribe How a finished AI Scribe note gets into Cliniko: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the Cliniko note open in the clinician's browser | Yes | ### Connection **Method:** Chrome extension. [How the methods compare](/connections/overview). **You provide** * Install the [HealOS Chrome extension](/guides/scribe/chrome-extension) and sign in to HealOS in it. * Open the patient's note in the EHR in the same Chrome window. **HealOS does** * Fills the finished AI Scribe note into the note page open in the clinician's browser; the clinician reviews and signs it in the EHR. * Nothing is stored on HealOS's side for this EHR: the extension works in the clinician's own signed-in session. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. # Cortex HIS Source: https://docs.healos.ai/ehr-actions/cortex-his What AI Frontdesk and AI Scribe do in Cortex HIS ## What HealOS does in Cortex HIS ### AI Frontdesk The AI Frontdesk (AI Receptionist) does not work in Cortex HIS yet. ### AI Scribe How a finished AI Scribe note gets into Cortex HIS: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the Cortex HIS note open in the clinician's browser | Specific setups | ### Connection **Method:** Chrome extension. [How the methods compare](/connections/overview). **You provide** * Install the [HealOS Chrome extension](/guides/scribe/chrome-extension) and sign in to HealOS in it. * Open the patient's note in the EHR in the same Chrome window. **HealOS does** * Fills the finished AI Scribe note into the note page open in the clinician's browser; the clinician reviews and signs it in the EHR. * Nothing is stored on HealOS's side for this EHR: the extension works in the clinician's own signed-in session. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. # CureMD Source: https://docs.healos.ai/ehr-actions/curemd What AI Frontdesk and AI Scribe do in CureMD ## What HealOS does in CureMD ### AI Frontdesk The AI Frontdesk (AI Receptionist) does not work in CureMD yet. ### AI Scribe How a finished AI Scribe note gets into CureMD: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the CureMD note open in the clinician's browser | Yes | ### Connection **Method:** Chrome extension. [How the methods compare](/connections/overview). **You provide** * Install the [HealOS Chrome extension](/guides/scribe/chrome-extension) and sign in to HealOS in it. * Open the patient's note in the EHR in the same Chrome window. **HealOS does** * Fills the finished AI Scribe note into the note page open in the clinician's browser; the clinician reviews and signs it in the EHR. * Nothing is stored on HealOS's side for this EHR: the extension works in the clinician's own signed-in session. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. # CurveHero Source: https://docs.healos.ai/ehr-actions/curvehero What AI Frontdesk and AI Scribe do in CurveHero, and its 7 API actions ## What HealOS does in CurveHero ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in CurveHero during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | | Look up upcoming appointments | Yes | | Cancel an appointment | Yes | | Reschedule an appointment | Yes | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe How a finished AI Scribe note gets into CurveHero: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the CurveHero note open in the clinician's browser | Yes | ### Connection **Method:** HealOS cloud browser, Chrome extension. [How the methods compare](/connections/overview). **You provide** * A CurveHero username and password and your practice address (`yourpractice.curvehero.com`), in **AI Frontdesk → Integrations → Connect an EHR**. * An email inbox that receives CurveHero's sign-in codes, set up with HealOS during onboarding so HealOS can read the codes. **HealOS does** * Checks the sign-in before saving anything: a login that fails is not stored. * Stores the credentials encrypted and signs in from a secure, US-based cloud browser. * Keeps one signed-in session per practice and renews it during business hours, so calls don't wait for a login. * Reads the emailed sign-in code itself; it accepts only codes that arrive after the login it started. **Limits** * The first connection can take several minutes while CurveHero emails the code. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 7 actions in CurveHero. Action names (`curvehero.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `curvehero.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `curvehero.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `curvehero.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `curvehero.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | | **List upcoming appointments** `curvehero.list_appointments` | List a patient's upcoming appointments. | read | `patient_id` | `appointments` | | **Cancel appointment** `curvehero.cancel_appointment` | Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id` | `appointment_id`, `status` | | **Reschedule appointment** `curvehero.reschedule_appointment` | Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id`, `slot_id`, `start_at_utc`, `duration_minutes` | `appointment_id`, `start_at_utc` | ## Search patients `curvehero.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `curvehero.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** not run by HealOS before creating * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `curvehero.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `curvehero.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | ## List upcoming appointments `curvehero.list_appointments` · scheduling · version 1 List a patient's upcoming appointments. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | **Outputs** | Field | Type | Description | | - | - | - | | `appointments` | array of object | | Each item in `appointments`: | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | Start as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `end_at_utc` | string | End as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `date` | string | Start date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Start time in the practice's time zone. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `provider_name` | string | Provider display name. Null when the EHR does not return it. | | `reason` | string | Visit reason or type. Null when the EHR does not return it. | ## Cancel appointment `curvehero.cancel_appointment` · scheduling · version 1 Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `status` | string | The appointment's new status. | ## Reschedule appointment `curvehero.reschedule_appointment` · scheduling · version 1 Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | New start (ISO 8601 UTC). Null when the EHR does not return it. | # DrChrono Source: https://docs.healos.ai/ehr-actions/drchrono What AI Frontdesk and AI Scribe do in DrChrono, and its 5 API actions ## What HealOS does in DrChrono ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in DrChrono during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | | Look up upcoming appointments | Yes | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe How a finished AI Scribe note gets into DrChrono: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | Yes | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the DrChrono note open in the clinician's browser | Yes | ### Connection **Method:** Official API (OAuth), Chrome extension. [How the methods compare](/connections/overview). **You provide** * Create an API application in the DrChrono developer portal and paste its Client ID and Client Secret. Give the application a name unique to your practice, such as `HealOS_`: DrChrono rejects an application name another account already uses, so a plain `HealOS` can fail. * When DrChrono asks for a Redirect URI, paste the **Redirect URL** shown in HealOS's DrChrono connect dialog (it has a copy button); it must match exactly. * Then approve HealOS in DrChrono's consent screen, from **AI Frontdesk → Integrations → Connect an EHR** or **Integrations** (AI Scribe Integrations). **HealOS does** * Uses DrChrono's official API with OAuth 2.0 and refreshes the access token automatically. * Sends finished AI Scribe notes to the chart. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 5 actions in DrChrono. Action names (`drchrono.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `drchrono.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `drchrono.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `drchrono.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `drchrono.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | | **List upcoming appointments** `drchrono.list_appointments` | List a patient's upcoming appointments. | read | `patient_id` | `appointments` | ## Search patients `drchrono.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `drchrono.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** not run by HealOS before creating **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `drchrono.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `drchrono.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | ## List upcoming appointments `drchrono.list_appointments` · scheduling · version 1 List a patient's upcoming appointments. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | **Outputs** | Field | Type | Description | | - | - | - | | `appointments` | array of object | | Each item in `appointments`: | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | Start as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `end_at_utc` | string | End as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `date` | string | Start date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Start time in the practice's time zone. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `provider_name` | string | Provider display name. Null when the EHR does not return it. | | `reason` | string | Visit reason or type. Null when the EHR does not return it. | # eClinicalWorks Source: https://docs.healos.ai/ehr-actions/ecw What AI Frontdesk and AI Scribe do in eClinicalWorks, and its 2 API actions ## What HealOS does in eClinicalWorks ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in eClinicalWorks during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe How a finished AI Scribe note gets into eClinicalWorks: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | Yes | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the eClinicalWorks note open in the clinician's browser | Yes | ### Connection **Method:** HealOS cloud browser, Chrome extension. [How the methods compare](/connections/overview). **You provide** * An eClinicalWorks username and password and your eCW web address (`…ecwcloud.com`), in **AI Frontdesk → Integrations → Connect an EHR** or **Integrations** (AI Scribe Integrations). The connection is shared by the organization. **HealOS does** * Checks the sign-in before saving anything: a login that fails is not stored. * Stores the credentials encrypted and signs in from a secure, US-based cloud browser. * Keeps one signed-in session per practice and renews it during business hours, so calls don't wait for a login. * Sends finished AI Scribe notes to the chart. **Limits** * Booking stays off until your visit-type and status defaults are reviewed with HealOS. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 2 actions in eClinicalWorks. Action names (`ecw.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `ecw.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `ecw.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | ## Search patients `ecw.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `ecw.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** not run by HealOS before creating * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | # Elation Source: https://docs.healos.ai/ehr-actions/elation What AI Frontdesk and AI Scribe do in Elation, and its 7 API actions ## What HealOS does in Elation ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in Elation during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | | Look up upcoming appointments | Yes | | Cancel an appointment | On request | | Reschedule an appointment | On request | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe How a finished AI Scribe note gets into Elation: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the Elation note open in the clinician's browser | Yes | ### Connection **Method:** Official API (OAuth), Chrome extension. [How the methods compare](/connections/overview). **You provide** * Elation's Direct API access, which you request from your Elation account representative (Elation may charge for it). You receive a Client ID and Client Secret for sandbox or production. * Enter them, with the matching environment, in **AI Frontdesk → Integrations → Connect an EHR**. **HealOS does** * Uses Elation's official API (OAuth 2.0 client credentials). * Builds open slots from each provider's availability minus booked appointments. **Limits** * Sandbox and production credentials are not interchangeable. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 7 actions in Elation. Action names (`elation.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `elation.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `elation.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `elation.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `elation.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | | **List upcoming appointments** `elation.list_appointments` | List a patient's upcoming appointments. | read | `patient_id` | `appointments` | | **Cancel appointment** `elation.cancel_appointment` | Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id` | `appointment_id`, `status` | | **Reschedule appointment** `elation.reschedule_appointment` | Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id`, `slot_id`, `start_at_utc`, `duration_minutes` | `appointment_id`, `start_at_utc` | ## Search patients `elation.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `elation.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** not run by HealOS before creating **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `elation.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `elation.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | ## List upcoming appointments `elation.list_appointments` · scheduling · version 1 List a patient's upcoming appointments. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | **Outputs** | Field | Type | Description | | - | - | - | | `appointments` | array of object | | Each item in `appointments`: | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | Start as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `end_at_utc` | string | End as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `date` | string | Start date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Start time in the practice's time zone. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `provider_name` | string | Provider display name. Null when the EHR does not return it. | | `reason` | string | Visit reason or type. Null when the EHR does not return it. | ## Cancel appointment `elation.cancel_appointment` · scheduling · version 1 Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused > * **Per-practice enablement:** off until HealOS turns it on for the practice **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `status` | string | The appointment's new status. | ## Reschedule appointment `elation.reschedule_appointment` · scheduling · version 1 Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused > * **Per-practice enablement:** off until HealOS turns it on for the practice **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | New start (ISO 8601 UTC). Null when the EHR does not return it. | # Epic Source: https://docs.healos.ai/ehr-actions/epic What AI Frontdesk and AI Scribe do in Epic ## What HealOS does in Epic ### AI Frontdesk The AI Frontdesk (AI Receptionist) does not work in Epic yet. ### AI Scribe How a finished AI Scribe note gets into Epic: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | On request | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the Epic note open in the clinician's browser | — | ### Connection **Method:** SMART on FHIR. [How the methods compare](/connections/overview). **You provide** * Your organization's Epic FHIR R4 base URL, in **Integrations** (AI Scribe Integrations); then the clinician signs in to Epic to approve HealOS. * Your health system must enable the HealOS app in Epic. **HealOS does** * Connects with SMART on FHIR (authorization code), reading the patient, encounter and practitioner, and writing the note as a DocumentReference. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. # Halaxy Source: https://docs.healos.ai/ehr-actions/halaxy What AI Frontdesk and AI Scribe do in Halaxy, and its 5 API actions ## What HealOS does in Halaxy ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in Halaxy during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | | Look up upcoming appointments | Yes | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe AI Scribe notes cannot be sent to Halaxy yet; copy the note from HealOS. ### Connection **Method:** Official API (OAuth). [How the methods compare](/connections/overview). **You provide** * Halaxy's API add-on. In Halaxy, Settings → Integrations → External → Create New Key, with Patient read/write, Appointment read/write and Slot read. * Paste the Client ID, Client Secret and region (AU or EU) in **AI Frontdesk → Integrations → Connect an EHR**. **HealOS does** * Uses Halaxy's FHIR API (OAuth 2.0 client credentials) and renews the token as it expires. **Limits** * Halaxy allows about 500 API requests per minute per credential. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 5 actions in Halaxy. Action names (`halaxy.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `halaxy.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `halaxy.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `halaxy.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `halaxy.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | | **List upcoming appointments** `halaxy.list_appointments` | List a patient's upcoming appointments. | read | `patient_id` | `appointments` | ## Search patients `halaxy.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `halaxy.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** not run by HealOS before creating **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `halaxy.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `halaxy.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | ## List upcoming appointments `halaxy.list_appointments` · scheduling · version 1 List a patient's upcoming appointments. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | **Outputs** | Field | Type | Description | | - | - | - | | `appointments` | array of object | | Each item in `appointments`: | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | Start as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `end_at_utc` | string | End as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `date` | string | Start date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Start time in the practice's time zone. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `provider_name` | string | Provider display name. Null when the EHR does not return it. | | `reason` | string | Visit reason or type. Null when the EHR does not return it. | # Hint Source: https://docs.healos.ai/ehr-actions/hint What AI Frontdesk and AI Scribe do in Hint, and its 2 API actions ## What HealOS does in Hint ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in Hint during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe AI Scribe notes cannot be sent to Hint yet; copy the note from HealOS. ### Connection **Method:** Official API (API credentials). [How the methods compare](/connections/overview). **You provide** * Your Hint practice API key, in **AI Frontdesk → Integrations → Connect an EHR**. **HealOS does** * Uses Hint's official API with the key, stored encrypted. **Limits** * Hint's API has no booking or note endpoints, so HealOS can find and register patients only. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 2 actions in Hint. Action names (`hint.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `hint.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `hint.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | ## Search patients `hint.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `hint.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** not run by HealOS before creating **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | # Kalix Source: https://docs.healos.ai/ehr-actions/kalix What AI Frontdesk and AI Scribe do in Kalix ## What HealOS does in Kalix ### AI Frontdesk The AI Frontdesk (AI Receptionist) does not work in Kalix yet. ### AI Scribe How a finished AI Scribe note gets into Kalix: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the Kalix note open in the clinician's browser | Yes | ### Connection **Method:** Chrome extension. [How the methods compare](/connections/overview). **You provide** * Install the [HealOS Chrome extension](/guides/scribe/chrome-extension) and sign in to HealOS in it. * Open the patient's note in the EHR in the same Chrome window. **HealOS does** * Fills the finished AI Scribe note into the note page open in the clinician's browser; the clinician reviews and signs it in the EHR. * Nothing is stored on HealOS's side for this EHR: the extension works in the clinician's own signed-in session. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. # MDLand Source: https://docs.healos.ai/ehr-actions/mdland What AI Frontdesk and AI Scribe do in MDLand ## What HealOS does in MDLand ### AI Frontdesk The AI Frontdesk (AI Receptionist) does not work in MDLand yet. ### AI Scribe How a finished AI Scribe note gets into MDLand: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the MDLand note open in the clinician's browser | Specific setups | ### Connection **Method:** Chrome extension. [How the methods compare](/connections/overview). **You provide** * Install the [HealOS Chrome extension](/guides/scribe/chrome-extension) and sign in to HealOS in it. * Open the patient's note in the EHR in the same Chrome window. **HealOS does** * Fills the finished AI Scribe note into the note page open in the clinician's browser; the clinician reviews and signs it in the EHR. * Nothing is stored on HealOS's side for this EHR: the extension works in the clinician's own signed-in session. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. # ModMed Source: https://docs.healos.ai/ehr-actions/modmed What AI Frontdesk and AI Scribe do in ModMed, and its 8 API actions ## What HealOS does in ModMed ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in ModMed during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | | Look up upcoming appointments | Yes | | Cancel an appointment | Yes | | Reschedule an appointment | Yes | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe How a finished AI Scribe note gets into ModMed: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | On request | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the ModMed note open in the clinician's browser | — | ### Connection **Method:** Official API (API credentials). [How the methods compare](/connections/overview). **You provide** * ModMed API credentials, which ModMed's practice solutions team issues to your practice: username, password, your firm's URL prefix and API key (optionally the provider's NPI). * Enter them in **AI Frontdesk → Integrations → Connect an EHR** or **Integrations** (AI Scribe Integrations). **HealOS does** * Uses ModMed's official FHIR R4 and REST APIs with your firm's own API key. * Reschedules by booking the new time first, then cancelling the old one. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 8 actions in ModMed. Action names (`modmed.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `modmed.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `modmed.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `modmed.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `modmed.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | | **List upcoming appointments** `modmed.list_appointments` | List a patient's upcoming appointments. | read | `patient_id` | `appointments` | | **Cancel appointment** `modmed.cancel_appointment` | Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id` | `appointment_id`, `status` | | **Reschedule appointment** `modmed.reschedule_appointment` | Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id`, `slot_id`, `start_at_utc`, `duration_minutes` | `appointment_id`, `start_at_utc` | | **Push clinical note** `modmed.push_note` | Write a HealOS Scribe note into the patient's chart in the EHR. | write | `session_id`, `content` | `status`, `job_id` | ## Search patients `modmed.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `modmed.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** not run by HealOS before creating **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `modmed.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `modmed.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | ## List upcoming appointments `modmed.list_appointments` · scheduling · version 1 List a patient's upcoming appointments. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | **Outputs** | Field | Type | Description | | - | - | - | | `appointments` | array of object | | Each item in `appointments`: | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | Start as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `end_at_utc` | string | End as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `date` | string | Start date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Start time in the practice's time zone. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `provider_name` | string | Provider display name. Null when the EHR does not return it. | | `reason` | string | Visit reason or type. Null when the EHR does not return it. | ## Cancel appointment `modmed.cancel_appointment` · scheduling · version 1 Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `status` | string | The appointment's new status. | ## Reschedule appointment `modmed.reschedule_appointment` · scheduling · version 1 Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | New start (ISO 8601 UTC). Null when the EHR does not return it. | ## Push clinical note `modmed.push_note` · notes · version 1 Write a HealOS Scribe note into the patient's chart in the EHR. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Synchronous: the result reports the saved note. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `session_id` | string | Yes | HealOS session id the note belongs to. | | `content` | string | Yes | Note text to write to the chart. | **Outputs** | Field | Type | Description | | - | - | - | | `status` | string | saved when the EHR stored the note; queued when the write runs asynchronously. | | `job_id` | string | Job id when the write is queued. Null when the EHR does not return it. | # NeoCareX Source: https://docs.healos.ai/ehr-actions/neocarex What AI Frontdesk and AI Scribe do in NeoCareX ## What HealOS does in NeoCareX ### AI Frontdesk The AI Frontdesk (AI Receptionist) does not work in NeoCareX yet. ### AI Scribe How a finished AI Scribe note gets into NeoCareX: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the NeoCareX note open in the clinician's browser | Specific setups | ### Connection **Method:** Chrome extension. [How the methods compare](/connections/overview). **You provide** * Install the [HealOS Chrome extension](/guides/scribe/chrome-extension) and sign in to HealOS in it. * Open the patient's note in the EHR in the same Chrome window. **HealOS does** * Fills the finished AI Scribe note into the note page open in the clinician's browser; the clinician reviews and signs it in the EHR. * Nothing is stored on HealOS's side for this EHR: the extension works in the clinician's own signed-in session. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. # NextGen Office Source: https://docs.healos.ai/ehr-actions/nextgen What AI Frontdesk and AI Scribe do in NextGen Office, and its 8 API actions ## What HealOS does in NextGen Office ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in NextGen Office during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | | Look up upcoming appointments | Yes | | Cancel an appointment | On request | | Confirm an appointment | On request | | Reschedule an appointment | On request | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe How a finished AI Scribe note gets into NextGen Office: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the NextGen Office note open in the clinician's browser | Yes | ### Connection **Method:** HealOS cloud browser, Chrome extension. [How the methods compare](/connections/overview). **You provide** * A NextGen Office username and password, in **AI Frontdesk → Integrations → Connect an EHR**. * An email inbox that receives NextGen's sign-in codes, set up with HealOS during onboarding so HealOS can read the codes. **HealOS does** * Checks the sign-in before saving anything: a login that fails is not stored. * Stores the credentials encrypted and signs in from a secure, US-based cloud browser. * Keeps one signed-in session per practice and renews it during business hours, so calls don't wait for a login. * Reads the emailed sign-in code itself; it accepts only codes that arrive after the login it started. **Limits** * Connecting can take up to about four minutes while NextGen emails the code. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 8 actions in NextGen Office. Action names (`nextgen.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `nextgen.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `nextgen.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `nextgen.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `nextgen.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | | **List upcoming appointments** `nextgen.list_appointments` | List a patient's upcoming appointments. | read | `patient_id` | `appointments` | | **Cancel appointment** `nextgen.cancel_appointment` | Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id` | `appointment_id`, `status` | | **Confirm appointment** `nextgen.confirm_appointment` | Mark one of the patient's appointments as confirmed. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id` | `appointment_id`, `status` | | **Reschedule appointment** `nextgen.reschedule_appointment` | Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id`, `slot_id`, `start_at_utc`, `duration_minutes` | `appointment_id`, `start_at_utc` | ## Search patients `nextgen.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `nextgen.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** not run by HealOS before creating * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `nextgen.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `nextgen.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | ## List upcoming appointments `nextgen.list_appointments` · scheduling · version 1 List a patient's upcoming appointments. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | **Outputs** | Field | Type | Description | | - | - | - | | `appointments` | array of object | | Each item in `appointments`: | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | Start as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `end_at_utc` | string | End as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `date` | string | Start date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Start time in the practice's time zone. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `provider_name` | string | Provider display name. Null when the EHR does not return it. | | `reason` | string | Visit reason or type. Null when the EHR does not return it. | ## Cancel appointment `nextgen.cancel_appointment` · scheduling · version 1 Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused > * **Per-practice enablement:** off until HealOS turns it on for the practice * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `status` | string | The appointment's new status. | ## Confirm appointment `nextgen.confirm_appointment` · scheduling · version 1 Mark one of the patient's appointments as confirmed. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused > * **Per-practice enablement:** off until HealOS turns it on for the practice * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `status` | string | The appointment's new status. | ## Reschedule appointment `nextgen.reschedule_appointment` · scheduling · version 1 Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused > * **Per-practice enablement:** off until HealOS turns it on for the practice * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | New start (ISO 8601 UTC). Null when the EHR does not return it. | # Office Ally Source: https://docs.healos.ai/ehr-actions/office-ally What AI Frontdesk and AI Scribe do in Office Ally ## What HealOS does in Office Ally ### AI Frontdesk The AI Frontdesk (AI Receptionist) does not work in Office Ally yet. ### AI Scribe How a finished AI Scribe note gets into Office Ally: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the Office Ally note open in the clinician's browser | Yes | ### Connection **Method:** Chrome extension. [How the methods compare](/connections/overview). **You provide** * Install the [HealOS Chrome extension](/guides/scribe/chrome-extension) and sign in to HealOS in it. * Open the patient's note in the EHR in the same Chrome window. **HealOS does** * Fills the finished AI Scribe note into the note page open in the clinician's browser; the clinician reviews and signs it in the EHR. * Nothing is stored on HealOS's side for this EHR: the extension works in the clinician's own signed-in session. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. # EHR integrations Source: https://docs.healos.ai/ehr-actions/overview What AI Frontdesk and AI Scribe do in 31 EHRs, and 114 API actions across 19 of them HealOS works with 31 EHRs and practice-management systems. The AI Frontdesk works in 19 of them during calls, and AI Scribe gets notes into 25. Open an EHR for what each product does there, how to connect it, and its API actions. ## Integrations | EHR | Connection | AI Frontdesk on calls | AI Scribe notes | API actions | | - | - | - | - | - | | [Acuity Scheduling](/ehr-actions/acuity) | Official API (OAuth) · Official API (API credentials) | Find patient, register, open slots, book, look up, cancel, reschedule | — | 7 | | [AdvancedMD](/ehr-actions/advancedmd) | Chrome extension | — | Chrome extension | — | | [athenahealth](/ehr-actions/athena) | HealOS cloud browser · Official API (API credentials) · Chrome extension | Find patient, register, open slots, book, look up | Sent from HealOS (on request) · Chrome extension | 5 | | [CareTracker](/ehr-actions/caretracker) | Chrome extension | — | Chrome extension | — | | [Cerbo](/ehr-actions/cerbo) | Official API (API credentials) | Find patient, register, open slots, book, look up; on request: cancel, confirm, reschedule | Sent from HealOS (on request) | 8 | | [CharmHealth](/ehr-actions/charmhealth) | HealOS cloud browser · Chrome extension | Find patient, register, open slots, book, look up, cancel, reschedule | Chrome extension | 7 | | [Cliniko](/ehr-actions/cliniko) | Chrome extension | — | Chrome extension | — | | [Cortex HIS](/ehr-actions/cortex-his) | Chrome extension | — | Chrome extension (specific setups) | — | | [CureMD](/ehr-actions/curemd) | Chrome extension | — | Chrome extension | — | | [CurveHero](/ehr-actions/curvehero) | HealOS cloud browser · Chrome extension | Find patient, register, open slots, book, look up, cancel, reschedule | Chrome extension | 7 | | [DrChrono](/ehr-actions/drchrono) | Official API (OAuth) · Chrome extension | Find patient, register, open slots, book, look up | Sent from HealOS · Chrome extension | 5 | | [eClinicalWorks](/ehr-actions/ecw) | HealOS cloud browser · Chrome extension | Find patient, register | Sent from HealOS · Chrome extension | 2 | | [Elation](/ehr-actions/elation) | Official API (OAuth) · Chrome extension | Find patient, register, open slots, book, look up; on request: cancel, reschedule | Chrome extension | 7 | | [Epic](/ehr-actions/epic) | SMART on FHIR | — | Sent from HealOS (on request) | — | | [Halaxy](/ehr-actions/halaxy) | Official API (OAuth) | Find patient, register, open slots, book, look up | — | 5 | | [Hint](/ehr-actions/hint) | Official API (API credentials) | Find patient, register | — | 2 | | [Kalix](/ehr-actions/kalix) | Chrome extension | — | Chrome extension | — | | [MDLand](/ehr-actions/mdland) | Chrome extension | — | Chrome extension (specific setups) | — | | [ModMed](/ehr-actions/modmed) | Official API (API credentials) | Find patient, register, open slots, book, look up, cancel, reschedule | Sent from HealOS (on request) | 8 | | [NeoCareX](/ehr-actions/neocarex) | Chrome extension | — | Chrome extension (specific setups) | — | | [NextGen Office](/ehr-actions/nextgen) | HealOS cloud browser · Chrome extension | Find patient, register, open slots, book, look up; on request: cancel, confirm, reschedule | Chrome extension | 8 | | [Office Ally](/ehr-actions/office-ally) | Chrome extension | — | Chrome extension | — | | [Oracle Health (Cerner)](/ehr-actions/cerner) | SMART on FHIR | Find patient, register, open slots, book, look up | Sent from HealOS (on request) | 5 | | [Practice Fusion](/ehr-actions/practicefusion) | HealOS cloud browser · Chrome extension | Find patient, register, open slots, book, look up (cloud connection only), cancel (cloud connection only), reschedule (cloud connection only) | Sent from HealOS · Chrome extension | 8 | | [Prognocis](/ehr-actions/prognocis) | Chrome extension | — | Chrome extension (specific setups) | — | | [SimplePractice](/ehr-actions/simplepractice) | HealOS cloud browser · Chrome extension | Find patient, register, open slots, book | Chrome extension | 4 | | [Tebra (Kareo)](/ehr-actions/tebra) | Official API (API credentials) · Chrome extension | Find patient, register, open slots, book, look up | Chrome extension | 5 | | [TheraNest](/ehr-actions/theranest) | HealOS cloud browser | Find patient, register, open slots, book, look up, cancel, reschedule | — | 7 | | [TherapyNotes](/ehr-actions/therapynotes) | HealOS cloud browser | Find patient, register, open slots, book, look up, cancel, reschedule | — | 7 | | [WebPT](/ehr-actions/webpt) | HealOS cloud browser | Find patient, register, open slots, book, look up, cancel, reschedule | — | 7 | | [WoundExpert](/ehr-actions/woundexpert) | Chrome extension | — | Chrome extension | — | **AI Scribe notes:** *Sent from HealOS* writes the finished note to the chart through the EHR connection; *Chrome extension* fills it into the EHR page open in the clinician's browser. **Connection** methods are compared in [Connection methods](/connections/overview); hospital HL7 feeds are covered in [HL7 feeds](/connections/hl7). > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API action catalog > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. The catalog lists the 114 actions HealOS runs in 19 EHRs: finding and registering patients, scheduling, and pushing Scribe notes. Each action has a stable name (`athena.search_patients`), input and output fields, and a safety box. ### Endpoints | Endpoint | Scope | What it does | | - | - | - | | `GET /ehr/actions` | `ehr:read` | Every action, or one EHR's with `?ehr=athena` | | `GET /ehr/actions/{actionName}` | `ehr:read` | One action by name, for example `athena.search_patients` | | `GET /ehr/connections` | `ehr:read` | Which EHRs your organization has connected (status only, never credentials) | ### Reading the safety box | Field | Meaning | | - | - | | External effect | `read` looks data up; `write` changes the practice's EHR | | Idempotent | Sending the same request twice has the same effect as once | | Safe to retry | You can retry after a timeout without checking the EHR first. Every write is **No** | | Dry run | No action supports a dry run yet | | Touches the practice's live EHR | Actions run against production EHR data, not a sandbox | | Ownership check | Cancel, confirm and reschedule refuse an appointment that is not the patient's | | Duplicate check | `create_patient` only: whether HealOS looks for an existing chart first | | Per-practice enablement | Writes HealOS turns on per practice after a supervised test | Output fields are documented from the integration code (`schema_completeness: best_effort`); EHRs can omit optional fields. ### Actions | Action | Title | Effect | | - | - | - | | `search_patients` | Search patients | read | | `create_patient` | Create patient | write | | `search_slots` | Search appointment slots | read | | `book_appointment` | Book appointment | write | | `list_appointments` | List upcoming appointments | read | | `cancel_appointment` | Cancel appointment | write | | `confirm_appointment` | Confirm appointment | write | | `reschedule_appointment` | Reschedule appointment | write | | `push_note` | Push clinical note | write | ### Actions by EHR | EHR | Actions | `search_patients` | `create_patient` | `search_slots` | `book_appointment` | `list_appointments` | `cancel_appointment` | `confirm_appointment` | `reschedule_appointment` | `push_note` | | - | - | - | - | - | - | - | - | - | - | - | | [Acuity Scheduling](/ehr-actions/acuity) | 7 | Yes | Yes | Yes | Yes | Yes | Yes | – | Yes | – | | [athenahealth](/ehr-actions/athena) | 5 | Yes | Yes | Yes | Yes | Yes | – | – | – | – | | [Cerbo](/ehr-actions/cerbo) | 8 | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | – | | [Oracle Health (Cerner)](/ehr-actions/cerner) | 5 | Yes | Yes | Yes | Yes | Yes | – | – | – | – | | [CharmHealth](/ehr-actions/charmhealth) | 7 | Yes | Yes | Yes | Yes | Yes | Yes | – | Yes | – | | [CurveHero](/ehr-actions/curvehero) | 7 | Yes | Yes | Yes | Yes | Yes | Yes | – | Yes | – | | [DrChrono](/ehr-actions/drchrono) | 5 | Yes | Yes | Yes | Yes | Yes | – | – | – | – | | [eClinicalWorks](/ehr-actions/ecw) | 2 | Yes | Yes | – | – | – | – | – | – | – | | [Elation](/ehr-actions/elation) | 7 | Yes | Yes | Yes | Yes | Yes | Yes | – | Yes | – | | [Halaxy](/ehr-actions/halaxy) | 5 | Yes | Yes | Yes | Yes | Yes | – | – | – | – | | [Hint](/ehr-actions/hint) | 2 | Yes | Yes | – | – | – | – | – | – | – | | [ModMed](/ehr-actions/modmed) | 8 | Yes | Yes | Yes | Yes | Yes | Yes | – | Yes | Yes | | [NextGen Office](/ehr-actions/nextgen) | 8 | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | – | | [Practice Fusion](/ehr-actions/practicefusion) | 8 | Yes | Yes | Yes | Yes | Yes | Yes | – | Yes | Yes | | [SimplePractice](/ehr-actions/simplepractice) | 4 | Yes | Yes | Yes | Yes | – | – | – | – | – | | [Tebra (Kareo)](/ehr-actions/tebra) | 5 | Yes | Yes | Yes | Yes | Yes | – | – | – | – | | [TheraNest](/ehr-actions/theranest) | 7 | Yes | Yes | Yes | Yes | Yes | Yes | – | Yes | – | | [TherapyNotes](/ehr-actions/therapynotes) | 7 | Yes | Yes | Yes | Yes | Yes | Yes | – | Yes | – | | [WebPT](/ehr-actions/webpt) | 7 | Yes | Yes | Yes | Yes | Yes | Yes | – | Yes | – | # Practice Fusion Source: https://docs.healos.ai/ehr-actions/practicefusion What AI Frontdesk and AI Scribe do in Practice Fusion, and its 8 API actions ## What HealOS does in Practice Fusion ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in Practice Fusion during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | | Look up upcoming appointments | Yes (cloud connection only) | | Cancel an appointment | Yes (cloud connection only) | | Reschedule an appointment | Yes (cloud connection only) | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe How a finished AI Scribe note gets into Practice Fusion: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | Yes | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the Practice Fusion note open in the clinician's browser | Yes | ### Connection **Method:** HealOS cloud browser, Chrome extension. [How the methods compare](/connections/overview). **You provide** * Cloud connection: a Practice Fusion email and password, in **AI Frontdesk → Integrations → Connect an EHR**. Practice Fusion's two-factor code is sent by phone; HealOS receives it on a number set up with you during onboarding, or a staff member enters it. * Extension connection: the HealOS Chrome extension, with a staff member signed in to Practice Fusion in Chrome. **HealOS does** * Checks the sign-in before saving anything: a login that fails is not stored. * Stores the credentials encrypted and signs in from a secure, US-based cloud browser. * Keeps one signed-in session per practice and renews it during business hours, so calls don't wait for a login. * Queues AI Scribe notes and sends one at a time per patient. **Limits** * Looking up, cancelling and rescheduling appointments need the cloud connection. * With the extension connection, actions run only while a signed-in Chrome tab is open. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 8 actions in Practice Fusion. Action names (`practicefusion.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `practicefusion.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `practicefusion.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `practicefusion.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `practicefusion.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | | **List upcoming appointments** `practicefusion.list_appointments` | List a patient's upcoming appointments. | read | `patient_id` | `appointments` | | **Cancel appointment** `practicefusion.cancel_appointment` | Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id` | `appointment_id`, `status` | | **Reschedule appointment** `practicefusion.reschedule_appointment` | Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id`, `slot_id`, `start_at_utc`, `duration_minutes` | `appointment_id`, `start_at_utc` | | **Push clinical note** `practicefusion.push_note` | Write a HealOS Scribe note into the patient's chart in the EHR. | write | `session_id`, `content` | `status`, `job_id` | ## Search patients `practicefusion.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Practice Fusion has no public API. Actions run through the HealOS browser extension in a staff member's signed-in Practice Fusion tab, or through the HealOS cloud connection. **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `practicefusion.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** searches by last name and date of birth first, and links an exact single match instead of creating a chart * Practice Fusion has no public API. Actions run through the HealOS browser extension in a staff member's signed-in Practice Fusion tab, or through the HealOS cloud connection. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `practicefusion.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Practice Fusion has no public API. Actions run through the HealOS browser extension in a staff member's signed-in Practice Fusion tab, or through the HealOS cloud connection. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `practicefusion.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Practice Fusion has no public API. Actions run through the HealOS browser extension in a staff member's signed-in Practice Fusion tab, or through the HealOS cloud connection. **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | ## List upcoming appointments `practicefusion.list_appointments` · scheduling · version 1 List a patient's upcoming appointments. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Practice Fusion has no public API. Actions run through the HealOS browser extension in a staff member's signed-in Practice Fusion tab, or through the HealOS cloud connection. * Needs the cloud connection. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | **Outputs** | Field | Type | Description | | - | - | - | | `appointments` | array of object | | Each item in `appointments`: | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | Start as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `end_at_utc` | string | End as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `date` | string | Start date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Start time in the practice's time zone. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `provider_name` | string | Provider display name. Null when the EHR does not return it. | | `reason` | string | Visit reason or type. Null when the EHR does not return it. | ## Cancel appointment `practicefusion.cancel_appointment` · scheduling · version 1 Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused * Practice Fusion has no public API. Actions run through the HealOS browser extension in a staff member's signed-in Practice Fusion tab, or through the HealOS cloud connection. * Needs the cloud connection. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `status` | string | The appointment's new status. | ## Reschedule appointment `practicefusion.reschedule_appointment` · scheduling · version 1 Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused * Practice Fusion has no public API. Actions run through the HealOS browser extension in a staff member's signed-in Practice Fusion tab, or through the HealOS cloud connection. * Needs the cloud connection. **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | New start (ISO 8601 UTC). Null when the EHR does not return it. | ## Push clinical note `practicefusion.push_note` · notes · version 1 Write a HealOS Scribe note into the patient's chart in the EHR. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Practice Fusion has no public API. Actions run through the HealOS browser extension in a staff member's signed-in Practice Fusion tab, or through the HealOS cloud connection. * Asynchronous: the write is queued and completed by the HealOS browser extension or cloud connection, so the result reports a queued job, not a saved note. One pending push per patient. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `session_id` | string | Yes | HealOS session id the note belongs to. | | `content` | string | Yes | Note text to write to the chart. | **Outputs** | Field | Type | Description | | - | - | - | | `status` | string | saved when the EHR stored the note; queued when the write runs asynchronously. | | `job_id` | string | Job id when the write is queued. Null when the EHR does not return it. | # Prognocis Source: https://docs.healos.ai/ehr-actions/prognocis What AI Frontdesk and AI Scribe do in Prognocis ## What HealOS does in Prognocis ### AI Frontdesk The AI Frontdesk (AI Receptionist) does not work in Prognocis yet. ### AI Scribe How a finished AI Scribe note gets into Prognocis: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the Prognocis note open in the clinician's browser | Specific setups | ### Connection **Method:** Chrome extension. [How the methods compare](/connections/overview). **You provide** * Install the [HealOS Chrome extension](/guides/scribe/chrome-extension) and sign in to HealOS in it. * Open the patient's note in the EHR in the same Chrome window. **HealOS does** * Fills the finished AI Scribe note into the note page open in the clinician's browser; the clinician reviews and signs it in the EHR. * Nothing is stored on HealOS's side for this EHR: the extension works in the clinician's own signed-in session. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. # SimplePractice Source: https://docs.healos.ai/ehr-actions/simplepractice What AI Frontdesk and AI Scribe do in SimplePractice, and its 4 API actions ## What HealOS does in SimplePractice ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in SimplePractice during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe How a finished AI Scribe note gets into SimplePractice: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the SimplePractice note open in the clinician's browser | Yes | ### Connection **Method:** HealOS cloud browser, Chrome extension. [How the methods compare](/connections/overview). **You provide** * A SimplePractice username and password, in **AI Frontdesk → Integrations → Connect an EHR**. * For AI Scribe, the HealOS Chrome extension (no connection card needed). **HealOS does** * Checks the sign-in before saving anything: a login that fails is not stored. * Stores the credentials encrypted and signs in from a secure, US-based cloud browser. * Keeps one signed-in session per practice and renews it during business hours, so calls don't wait for a login. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 4 actions in SimplePractice. Action names (`simplepractice.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `simplepractice.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `simplepractice.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `simplepractice.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `simplepractice.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | ## Search patients `simplepractice.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `simplepractice.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** searches by last name and date of birth first, and links an exact single match instead of creating a chart * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `simplepractice.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `simplepractice.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | # Tebra (Kareo) Source: https://docs.healos.ai/ehr-actions/tebra What AI Frontdesk and AI Scribe do in Tebra (Kareo), and its 5 API actions ## What HealOS does in Tebra (Kareo) ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in Tebra (Kareo) during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | | Look up upcoming appointments | Yes | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe How a finished AI Scribe note gets into Tebra (Kareo): | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the Tebra (Kareo) note open in the clinician's browser | Yes | ### Connection **Method:** Official API (API credentials), Chrome extension. [How the methods compare](/connections/overview). **You provide** * Tebra API access: a system administrator opens a case with Tebra Customer Care, then shares the Customer Key. * Enter the username, password, Customer Key, Practice ID and Practice Name in **AI Frontdesk → Integrations → Connect an EHR**. The user needs a System Admin or Account Administrator role. **HealOS does** * Uses Tebra's official practice-management API. **Limits** * Tebra rate-limits some calls per account (for example, appointment lookups about once per second). > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 5 actions in Tebra (Kareo). Action names (`tebra.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `tebra.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `tebra.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `tebra.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `tebra.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | | **List upcoming appointments** `tebra.list_appointments` | List a patient's upcoming appointments. | read | `patient_id` | `appointments` | ## Search patients `tebra.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `tebra.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** not run by HealOS before creating **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `tebra.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `tebra.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | ## List upcoming appointments `tebra.list_appointments` · scheduling · version 1 List a patient's upcoming appointments. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | **Outputs** | Field | Type | Description | | - | - | - | | `appointments` | array of object | | Each item in `appointments`: | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | Start as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `end_at_utc` | string | End as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `date` | string | Start date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Start time in the practice's time zone. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `provider_name` | string | Provider display name. Null when the EHR does not return it. | | `reason` | string | Visit reason or type. Null when the EHR does not return it. | # TheraNest Source: https://docs.healos.ai/ehr-actions/theranest What AI Frontdesk and AI Scribe do in TheraNest, and its 7 API actions ## What HealOS does in TheraNest ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in TheraNest during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | | Look up upcoming appointments | Yes | | Cancel an appointment | Yes | | Reschedule an appointment | Yes | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe AI Scribe notes cannot be sent to TheraNest yet; copy the note from HealOS. ### Connection **Method:** HealOS cloud browser. [How the methods compare](/connections/overview). **You provide** * A TheraNest email and password, in **AI Frontdesk → Integrations → Connect an EHR**. HealOS finds your practice address itself. **HealOS does** * Checks the sign-in before saving anything: a login that fails is not stored. * Stores the credentials encrypted and signs in from a secure, US-based cloud browser. * Keeps one signed-in session per practice and renews it during business hours, so calls don't wait for a login. * Cancels by setting the appointment's status to Canceled; it never deletes appointments. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 7 actions in TheraNest. Action names (`theranest.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `theranest.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `theranest.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `theranest.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `theranest.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | | **List upcoming appointments** `theranest.list_appointments` | List a patient's upcoming appointments. | read | `patient_id` | `appointments` | | **Cancel appointment** `theranest.cancel_appointment` | Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id` | `appointment_id`, `status` | | **Reschedule appointment** `theranest.reschedule_appointment` | Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id`, `slot_id`, `start_at_utc`, `duration_minutes` | `appointment_id`, `start_at_utc` | ## Search patients `theranest.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `theranest.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** not run by HealOS before creating * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `theranest.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `theranest.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | ## List upcoming appointments `theranest.list_appointments` · scheduling · version 1 List a patient's upcoming appointments. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | **Outputs** | Field | Type | Description | | - | - | - | | `appointments` | array of object | | Each item in `appointments`: | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | Start as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `end_at_utc` | string | End as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `date` | string | Start date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Start time in the practice's time zone. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `provider_name` | string | Provider display name. Null when the EHR does not return it. | | `reason` | string | Visit reason or type. Null when the EHR does not return it. | ## Cancel appointment `theranest.cancel_appointment` · scheduling · version 1 Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `status` | string | The appointment's new status. | ## Reschedule appointment `theranest.reschedule_appointment` · scheduling · version 1 Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | New start (ISO 8601 UTC). Null when the EHR does not return it. | # TherapyNotes Source: https://docs.healos.ai/ehr-actions/therapynotes What AI Frontdesk and AI Scribe do in TherapyNotes, and its 7 API actions ## What HealOS does in TherapyNotes ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in TherapyNotes during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | | Look up upcoming appointments | Yes | | Cancel an appointment | Yes | | Reschedule an appointment | Yes | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe AI Scribe notes cannot be sent to TherapyNotes yet; copy the note from HealOS. ### Connection **Method:** HealOS cloud browser. [How the methods compare](/connections/overview). **You provide** * Your TherapyNotes practice code (from your login address, `therapynotes.com/app/login//`), username, password and authenticator (TOTP) secret, in **AI Frontdesk → Integrations → Connect an EHR**. **HealOS does** * Checks the sign-in before saving anything: a login that fails is not stored. * Stores the credentials encrypted and signs in from a secure, US-based cloud browser. * Keeps one signed-in session per practice and renews it during business hours, so calls don't wait for a login. * Generates the authenticator codes itself. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 7 actions in TherapyNotes. Action names (`therapynotes.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `therapynotes.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `therapynotes.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `therapynotes.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `therapynotes.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | | **List upcoming appointments** `therapynotes.list_appointments` | List a patient's upcoming appointments. | read | `patient_id` | `appointments` | | **Cancel appointment** `therapynotes.cancel_appointment` | Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id` | `appointment_id`, `status` | | **Reschedule appointment** `therapynotes.reschedule_appointment` | Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id`, `slot_id`, `start_at_utc`, `duration_minutes` | `appointment_id`, `start_at_utc` | ## Search patients `therapynotes.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `therapynotes.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** not run by HealOS before creating * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `therapynotes.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `therapynotes.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | ## List upcoming appointments `therapynotes.list_appointments` · scheduling · version 1 List a patient's upcoming appointments. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | **Outputs** | Field | Type | Description | | - | - | - | | `appointments` | array of object | | Each item in `appointments`: | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | Start as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `end_at_utc` | string | End as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `date` | string | Start date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Start time in the practice's time zone. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `provider_name` | string | Provider display name. Null when the EHR does not return it. | | `reason` | string | Visit reason or type. Null when the EHR does not return it. | ## Cancel appointment `therapynotes.cancel_appointment` · scheduling · version 1 Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `status` | string | The appointment's new status. | ## Reschedule appointment `therapynotes.reschedule_appointment` · scheduling · version 1 Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | New start (ISO 8601 UTC). Null when the EHR does not return it. | # WebPT Source: https://docs.healos.ai/ehr-actions/webpt What AI Frontdesk and AI Scribe do in WebPT, and its 7 API actions ## What HealOS does in WebPT ### AI Frontdesk What the AI Frontdesk (AI Receptionist) can do in WebPT during a call: | Task | Available | | - | - | | Find the caller's chart | Yes | | Register a new patient | Yes | | Find open slots | Yes | | Book an appointment | Yes | | Look up upcoming appointments | Yes | | Cancel an appointment | Yes | | Reschedule an appointment | Yes | Connect it from **AI Frontdesk → Integrations → Connect an EHR** ([Connect your EHR](/guides/receptionist/connect-your-ehr)). ### AI Scribe AI Scribe notes cannot be sent to WebPT yet; copy the note from HealOS. ### Connection **Method:** HealOS cloud browser. [How the methods compare](/connections/overview). **You provide** * A dedicated WebPT login (email and password) for HealOS, in **AI Frontdesk → Integrations → Connect an EHR**. **HealOS does** * Checks the sign-in before saving anything: a login that fails is not stored. * Stores the credentials encrypted and signs in from a secure, US-based cloud browser. * Keeps one signed-in session per practice and renews it during business hours, so calls don't wait for a login. **Limits** * WebPT allows one active session per login, so give HealOS its own user. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. ## API actions > [!WARNING] > > This is a catalog of what HealOS can do in each EHR. Running these actions through the HealOS API is > coming later. Listing them (`GET /ehr/actions`) and checking which EHRs your organization has connected > (`GET /ehr/connections`), with the `ehr:read` scope, are **rolling out: they work on staging but are not > yet available on `api.healos.ai`**. Every action runs against the practice's live EHR, never a sandbox. HealOS supports 7 actions in WebPT. Action names (`webpt.`) are stable. | Action | Description | Effect | Inputs | Outputs | | - | - | - | - | - | | **Search patients** `webpt.search_patients` | Find an existing patient in the EHR by phone number, name, date of birth or email. | read | `phone`, `first_name`, `last_name`, `dob`, `email` | `found`, `patient_id`, `display_name` | | **Create patient** `webpt.create_patient` | Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). | write | `phone`, `first_name`, `last_name`, `dob`, `gender`, `email`, `provider_id`, `address1`, `city`, `state`, `zip` | `patient_id`, `display_name` | | **Search appointment slots** `webpt.search_slots` | List open appointment times, optionally narrowed to a window, provider, visit type or location. | read | `start_at_utc`, `end_at_utc`, `provider_id`, `appointment_type`, `location`, `patient_dob` | `slots` | | **Book appointment** `webpt.book_appointment` | Book an appointment for an existing patient, from a slot returned by search\_slots. | write | `patient_id`, `slot_id`, `start_at_utc`, `duration_minutes`, `provider_id`, `appointment_type`, `chief_complaint`, `notes` | `appointment_id`, `patient_id`, `start_at_utc` | | **List upcoming appointments** `webpt.list_appointments` | List a patient's upcoming appointments. | read | `patient_id` | `appointments` | | **Cancel appointment** `webpt.cancel_appointment` | Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id` | `appointment_id`, `status` | | **Reschedule appointment** `webpt.reschedule_appointment` | Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. | write | `patient_id`, `appointment_id`, `slot_id`, `start_at_utc`, `duration_minutes` | `appointment_id`, `start_at_utc` | ## Search patients `webpt.search_patients` · patients · version 1 Find an existing patient in the EHR by phone number, name, date of birth or email. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send at least one field. | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | No | Phone number, E.164 preferred. | | `first_name` | string | No | Patient first name. | | `last_name` | string | No | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `email` | string (email) | No | Email address. | **Outputs** | Field | Type | Description | | - | - | - | | `found` | boolean | True on a match. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Create patient `webpt.create_patient` · patients · version 1 Register a new patient chart in the EHR. Some EHRs need extra fields (for example a mailing address on NextGen). > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Duplicate check:** not run by HealOS before creating * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `phone` | string | Yes | Phone number, E.164 preferred. | | `first_name` | string | Yes | Patient first name. | | `last_name` | string | Yes | Patient last name. | | `dob` | string (date) | No | Date of birth (YYYY-MM-DD). | | `gender` | string | No | Gender as the patient states it. | | `email` | string (email) | No | Email address. | | `provider_id` | string | No | EHR provider id to file the chart under, where the EHR assigns one at registration. | | `address1` | string | No | Street address, for EHRs that require one. | | `city` | string | No | City, for EHRs that require an address. | | `state` | string | No | State, for EHRs that require an address. | | `zip` | string | No | ZIP code, for EHRs that require an address. | **Outputs** | Field | Type | Description | | - | - | - | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `display_name` | string | Patient display name. Null when the EHR does not return it. | ## Search appointment slots `webpt.search_slots` · scheduling · version 1 List open appointment times, optionally narrowed to a window, provider, visit type or location. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `start_at_utc` | string (date-time) | No | Window start (ISO 8601 UTC). | | `end_at_utc` | string (date-time) | No | Window end (ISO 8601 UTC). | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `location` | string | No | Location name or id, for multi-location practices. | | `patient_dob` | string (date) | No | Patient date of birth (YYYY-MM-DD), used only to honour per-provider age limits. | **Outputs** | Field | Type | Description | | - | - | - | | `slots` | array of object | | Each item in `slots`: | Field | Type | Description | | - | - | - | | `slot_id` | string | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string | Start (ISO 8601 UTC). Null when the EHR does not return it. | | `date` | string | Date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Time in the practice's time zone. | | `duration_minutes` | integer | Visit length in minutes. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `appointment_type` | string | Visit type. Null when the EHR does not return it. | ## Book appointment `webpt.book_appointment` · scheduling · version 1 Book an appointment for an existing patient, from a slot returned by search\_slots. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | | `provider_id` | string | No | EHR provider id. | | `appointment_type` | string | No | Visit type id or name. | | `chief_complaint` | string | No | Reason for the visit. | | `notes` | string | No | Free-text note stored on the appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `patient_id` | string | The EHR's patient id, as returned by search\_patients or create\_patient. | | `start_at_utc` | string | Booked start (ISO 8601 UTC). Null when the EHR does not return it. | ## List upcoming appointments `webpt.list_appointments` · scheduling · version 1 List a patient's upcoming appointments. > [!NOTE] > > **Safety** > > * **External effect:** read > * **Writes to the EHR:** No > * **Idempotent:** Yes > * **Safe to retry:** Yes > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | **Outputs** | Field | Type | Description | | - | - | - | | `appointments` | array of object | | Each item in `appointments`: | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | Start as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `end_at_utc` | string | End as an ISO 8601 UTC instant. Null when the EHR does not return it. | | `date` | string | Start date in the practice's time zone (YYYY-MM-DD). | | `time` | string | Start time in the practice's time zone. | | `provider_id` | string | The EHR's provider id. Null when the EHR does not return it. | | `provider_name` | string | Provider display name. Null when the EHR does not return it. | | `reason` | string | Visit reason or type. Null when the EHR does not return it. | ## Cancel appointment `webpt.cancel_appointment` · scheduling · version 1 Cancel one of the patient's appointments. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `status` | string | The appointment's new status. | ## Reschedule appointment `webpt.reschedule_appointment` · scheduling · version 1 Move one of the patient's appointments to a new time. Refused unless the appointment belongs to that patient. > [!WARNING] > > **Safety** > > * **External effect:** write > * **Writes to the EHR:** Yes > * **Idempotent:** No > * **Safe to retry:** No. After a timeout or unclear result, check the EHR before trying again > * **Dry run:** Not supported > * **Touches the practice's live EHR:** Yes > * **Ownership check:** the appointment must belong to the patient, or the action is refused * Runs in a cloud browser session against the EHR's web app: expect several seconds per call and limited concurrency per practice. **Inputs** Send `slot_id` or `start_at_utc`. | Field | Type | Required | Description | | - | - | - | - | | `patient_id` | string | Yes | The EHR's patient id, as returned by search\_patients or create\_patient. | | `appointment_id` | string | Yes | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `slot_id` | string | No | Opaque slot id from search\_slots. Preferred over start\_at\_utc: it carries the provider, visit type and duration the EHR needs. | | `start_at_utc` | string (date-time) | No | Appointment start as an ISO 8601 UTC instant. | | `duration_minutes` | integer | No | Visit length in minutes. | **Outputs** | Field | Type | Description | | - | - | - | | `appointment_id` | string | The EHR's appointment id, as returned by list\_appointments or book\_appointment. | | `start_at_utc` | string | New start (ISO 8601 UTC). Null when the EHR does not return it. | # WoundExpert Source: https://docs.healos.ai/ehr-actions/woundexpert What AI Frontdesk and AI Scribe do in WoundExpert ## What HealOS does in WoundExpert ### AI Frontdesk The AI Frontdesk (AI Receptionist) does not work in WoundExpert yet. ### AI Scribe How a finished AI Scribe note gets into WoundExpert: | Route | Available | | - | - | | Sent from HealOS: the note is written to the patient's chart through the EHR connection | — | | Filled by the [HealOS Chrome extension](/guides/scribe/chrome-extension) into the WoundExpert note open in the clinician's browser | Yes | ### Connection **Method:** Chrome extension. [How the methods compare](/connections/overview). **You provide** * Install the [HealOS Chrome extension](/guides/scribe/chrome-extension) and sign in to HealOS in it. * Open the patient's note in the EHR in the same Chrome window. **HealOS does** * Fills the finished AI Scribe note into the note page open in the clinician's browser; the clinician reviews and signs it in the EHR. * Nothing is stored on HealOS's side for this EHR: the extension works in the clinician's own signed-in session. > [!NOTE] > > * **Yes**: works once the practice connects the EHR (or, for the Chrome extension, installs it). > * **On request**: built; HealOS turns it on for a practice after a review with them. > * **Specific setups**: built for particular practice configurations; ask us before relying on it. > > A **Yes** means the workflow exists, not that every practice's setup allows it: practice settings, user permissions and the EHR plan can still limit it, so confirm during onboarding. # Error catalog Source: https://docs.healos.ai/errors Every error the API returns: what it means, whether to retry, and how to fix it ## Error shape Every error is JSON with an `error` message: ```json theme={null} { "error": "Patient not found" } ``` Some errors carry more fields: ```json Validation (400) theme={null} { "error": "Validation error", "details": { "name": ["String must contain at least 1 character(s)"], "_form": ["Errors that are not about one field"] } } ``` ```json Duplicate external_id (409) theme={null} { "error": "external_id already in use", "existing": { "id": "481926357104938271", "external_id": "PARTNER-12345" } } ``` ```json Eligibility (any status) theme={null} { "error": "The eligibility service did not respond in time. Please try again.", "code": "GATEWAY_TIMEOUT" } ``` > [!NOTE] > > Branch on the HTTP status, and on `code` where one is given. The `error` > text is for people and can change. ## By status | Status | Typical `error` | Meaning | Retry? | Fix | | - | - | - | - | - | | `400` | `Validation error` | A field is missing, has the wrong type or is out of range. `details` names it. | No | Fix the request. | | `400` | `provider_id is not a provider in your organization` | The `provider_id` isn't a member of the key's organization. | No | Use an id from [`GET /providers`](/api-reference/providers/list-providers). | | `400` | `No file provided`, `File content does not match its extension (...)` | Upload problem. | No | Send a PDF, JPEG, PNG or DOCX whose content matches its extension. | | `401` | `Missing X-API-Key header` | No key sent. | No | Send `X-API-Key: hlsk_...`. | | `401` | `Invalid API key` | The key is wrong or was deleted. | No | Check the key, or create a new one. | | `401` | `API key has been revoked`, `API key has expired` | The key no longer works. | No | Create a new key. See [rotation](/security#rotate-a-key). | | `402` | `No Scribe sessions left.` | Note generation from text or audio needs a Scribe session and the plan has none left. | No | Upgrade the plan or wait for it to renew. | | `403` | `Insufficient scope. Required: notes:write` | The key lacks the scope named. | No | Create a key with that scope. See [scopes](/authentication#scopes). | | `404` | `Patient not found`, `Session not found`, ... | The record doesn't exist **or** belongs to another organization. Also returned by `external_id` lookups that match nothing. | No | Check the id and that the key is for the right organization. | | `409` | `external_id already in use` | Another record in your organization has this `external_id`. | No | Use `existing.id` from the response. | | `409` | `The same text is already being processed for this patient.` | A request for this patient is being submitted right now. | No | Wait for that request's `202`, then check its session. Resending later creates a second note. | | `409` | `Session is not ready for regeneration (status: ...)` | Only `completed` sessions can be regenerated. | Later | Wait for the session to complete. | | `409` | `Manual-text sessions cannot be regenerated via this endpoint` | Notes from text are regenerated differently. | No | Generate a new note with [`POST /notes/from-text`](/api-reference/notes/generate-a-note-from-text). | | `409` | Varies (from `PATCH /sessions/{sessionId}`) | A note of this session was already sent to an EHR, so the session can't move to another patient. | No | Correct the patient in the EHR. | | `409` | `Statuses were checked recently; try again in N min.` | Prior-auth decisions were read less than 10 minutes ago. | After N min | Wait. | | `413` | `Request body is too large (limit N MB)` | Over 1 MB of JSON, 10 MB for a document or 100 MB for audio. | No | Send a smaller body or file. | | `422` | `No documents with extracted text for this patient. ...` | Note from documents asked for before any document finished extraction. | Later | Wait for a document to reach `completed`. | | `422` | Payer message, `code` `PAYER_VALIDATION_ERROR` | The payer rejected the eligibility request. | No | Check the member details. | | `429` | `Rate limit exceeded. Please retry after the window resets.` | Over the limit of about 60 requests a minute for this key. | Yes | Wait for `Retry-After` seconds. See [rate limiting](/rate-limiting). | | `429` | `Too many uploads in progress for this API key (limit 2 at a time). ...` | A third document or audio upload sent while this key already has two in progress on the same API server. | Yes | Wait for an upload to finish, or `Retry-After` seconds. See [concurrent uploads](/rate-limiting#concurrent-uploads). | | `429` | `Too many uploads in progress for this organization. ...` | The organization's API keys together have as many uploads in progress as it allows (about 4) on the same API server. | Yes | Wait for an upload to finish, or `Retry-After` seconds. | | `429` | `The server is busy with other uploads. Please retry shortly.` | The API server is handling as many uploads as it allows at once, from all customers. | Yes | Wait `Retry-After` seconds, then retry with backoff. | | `429` | `Too many requests. Please try again later.` | Over an endpoint's own limit, such as 10 eligibility checks a minute. | Yes | Wait until the next minute. | | `500` | `Something went wrong. Please try again.` | A HealOS error. | Yes, with backoff (not eligibility checks, see below) | If it persists, contact support with the time and endpoint. | | `502`, `504` | Eligibility service errors | The payer or clearinghouse failed or timed out. | Yes, with backoff | Wait, then retry once. | | `503` | `Failed to queue note generation; please retry`, eligibility unavailable | A HealOS service is briefly unavailable. | Yes, with backoff | Retry after a short wait. | > [!NOTE] > > `404` does not tell "doesn't exist" apart from "belongs to another > organization". This is on purpose, so ids from other organizations can't be > discovered. ## Eligibility `code` values Eligibility errors ([`POST /benefits/eligibility-checks`](/api-reference/benefits/run-an-eligibility-check)) carry a `code`: | `code` | Status | Meaning | Retry? | | - | - | - | - | | `VALIDATION_ERROR` | `400` | A required field is missing or malformed. No payer request was made. | No | | `PATIENT_NOT_FOUND` | `404` | `patient_id` isn't in your organization. No payer request was made. | No | | `LINKED_CHECK_NOT_FOUND` | `404` | `linked_check_id` isn't a check in your organization. | No | | `PAYER_VALIDATION_ERROR` | `422` | The payer rejected the request, for example an unknown member id. The payer's own code can appear instead. | No | | `RATE_LIMITED` | `429` | The payer or clearinghouse is limiting requests. | Yes, later | | `UPSTREAM_ERROR` | `502` | The payer or clearinghouse returned an error. | Yes, with backoff | | `UPSTREAM_INVALID_RESPONSE` | `502` | The eligibility service returned a response that couldn't be read. | Yes, with backoff | | `UPSTREAM_UNREACHABLE` | `502` | The eligibility service couldn't be reached. | Yes, with backoff | | `GATEWAY_TIMEOUT` | `504` | The payer didn't answer in time. | Yes, with backoff | | `SERVICE_UNAVAILABLE` | `503` | Eligibility checking isn't available right now. | Yes, later | | `INTERNAL_ERROR` | `500` | A HealOS error. The payer may already have been asked. | No, list recent checks first | > [!WARNING] > > Every eligibility retry is a new, billable payer request. Retry only the > statuses marked above, and wait before you do. ## Retrying safely * Retry `429`, `500`, `502`, `503` and `504` with exponential backoff (for example 1, 2, 4, 8 seconds), and honor `Retry-After` when it is sent. * **Exception: eligibility checks.** Each retry is a new billable payer request. Retry only `502`, `503` and `504`, after a wait. After a `500`, [list recent checks](/api-reference/benefits/list-eligibility-checks) to see whether the check was saved before running it again. * Don't retry other `4xx` errors without changing the request. * Before retrying a write that may have succeeded (a timeout or a lost response), check the endpoint's **Safety** box in the [API Reference](/api-reference). Some writes create a new record on every call; for those, look the record up first, for example by `external_id`. # Going to production Source: https://docs.healos.ai/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](/test-mode) and production uses a key from your real organization. Never share one key between them. * [ ] **Check the organization on startup.** Call [`GET /me`](/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](/security#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](/authentication#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](/security#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](/security#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](/rate-limiting). * [ ] **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](/making-requests#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](/api-reference/benefits/list-eligibility-checks) 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](/api-reference) before you add a retry. See [Retrying safely](/errors#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](/webhooks). * [ ] **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](/security#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](/versioning). * [ ] You branch on the HTTP status and `code`, not on the `error` text. See [Error catalog](/errors). * [ ] Every flow has passed end to end in your test organization with made-up data. * [ ] Someone on your team follows the [Changelog](/changelog). # Eligibility setup Source: https://docs.healos.ai/guides/eligibility/setup What to have ready, the steps, how to test, and what blocks go-live for insurance eligibility checks. HealOS checks a patient's insurance coverage with the payer in real time, from the dashboard or during a call with the AI receptionist. ## What to have ready * **Your accepted payers.** The list the AI receptionist should check against. * **A decision on who gets checked:** new patients only, or all patients. * **Payer portal logins** for payers where the clearinghouse returns nothing. Without them HealOS cannot answer for those payers. ## Steps **1. Run a check in the dashboard** Open **AI Benefit Verification**, find the payer, and run a check with a member id. This shows what the payer returns for your practice. **2. Turn on checks in the receptionist** In the AI Frontdesk settings, turn on **Verify benefits before booking** and choose who to verify. **3. Add portal logins where needed** For payers that return nothing through the clearinghouse, give us the portal login so HealOS can check there. ## How to test 1. Run a check in the dashboard for a patient you know is covered. 2. Call the AI receptionist as that patient and book a visit. The check appears in **Insurance Checks**. ## What blocks go-live * The payer returns nothing through the clearinghouse and there is no portal login. * The receptionist setting is off. You are live when the first eligibility answer comes back from a payer. # Fax setup Source: https://docs.healos.ai/guides/fax/setup What to have ready, the steps, how to test, and what blocks go-live for the Fax Inbox. HealOS brings incoming faxes into the **Fax Inbox**, reads and types each one with AI, matches the patient, and can file it into the chart. ## What to have ready * **Your fax source.** One of: * your **EHR's fax inbox**, through the EHR connection you already have in HealOS, or * your **fax service login** (for example Weave) plus a **channel for its sign-in code**: a phone number or a mailbox HealOS can read. * **Routing rules.** For each kind of document (referrals, lab results, prescriptions, records requests, prior-auth and insurance documents, billing notices, other), who should get it and where in the chart it belongs. * **A decision on auto-filing.** Should HealOS file a matched fax into the patient's chart on its own, or should every fax wait in the inbox for staff? ## Steps **1. Connect the fax source** Open **AI Fax & Referrals → Fax Inbox → Integration** and connect your EHR fax or your fax service. HealOS tests the login while you connect. **2. Turn on sync** Turn on sync. Faxes received from that moment on come into the Fax Inbox. Older faxes are not pulled. **3. Set routing** Open **Fax Inbox → Workflows** and set where each kind of document goes. **4. Choose auto-filing** Leave **File into the patient's chart** off until you have checked a few faxes. With it off, faxes wait in the inbox for staff. ## How to test 1. Send a test fax with no real patient information to your fax number. 2. Wait for it in the Fax Inbox (a few minutes for synced sources). 3. Check the document type, the patient match and the routing it got. 4. If auto-filing is on, check that it reached the right chart. ## What blocks go-live * The fax service login fails, or its sign-in code has nowhere to go. * Routing rules are not decided. You are live when the first fax is read into the Fax Inbox. # Prior authorization setup Source: https://docs.healos.ai/guides/prior-auth/setup What to have ready, the steps, how to test, and what blocks go-live for prior authorization. HealOS prepares prior authorizations: it reads the chart, drafts the answers to the plan's questions, and fills the portal form. **Staff review every answer. Nothing is sent to the plan automatically.** ## What to have ready * **A CoverMyMeds login** for an account that belongs to your practice's provider group, with prescriber permissions. Ask your CoverMyMeds administrator to invite the account to the group if it is not already in it. * **A way to receive sign-in codes.** CoverMyMeds and the payer portals send a code at sign-in. Decide with us whether the code goes to a phone number or a mailbox HealOS can read. * **Your EHR connection.** HealOS reads chart facts (diagnoses, measurements, signed visit notes) from the EHR your practice already connected to HealOS. * **Payer portal logins** (for example Availity) if you want procedure requests prepared, not only medications. * **Two or three sample patients** who need a prior authorization, and your **workflow document**: who starts a request, who reviews it, who sends it. ## Steps **1. Connect your EHR** If your EHR is not connected yet, connect it first. HealOS only uses charts from the connected practice. **2. Sign in to CoverMyMeds** Open **AI Prior Auth → CoverMyMeds**, connect the secure browser, and sign in with the provider-group account. HealOS does not save the password in the request. **3. Add payer portal workflows (optional)** For procedure requests, open **AI Prior Auth → Workflows** and set up the EHR-to-portal workflow with your payer portal login. **4. Review the practice answers** Fill in the practice details HealOS reuses on every form (specialty, contact details). Staff can change them later. ## How to test 1. Start a request for one sample patient. Enter the exact medication and strength and the payer form. 2. Check the chart facts and the drafted answers. Each answer shows where it came from. A missing fact stays unanswered; HealOS never turns it into "No". 3. Approve the answers, then fill them into CoverMyMeds. HealOS saves the draft and never presses **Send to Plan**. 4. Open the request in CoverMyMeds and check the saved answers before a person sends it. ## What blocks go-live * The CoverMyMeds account is not in the practice's provider group, or has no prescriber permission. * No working channel for sign-in codes. * The EHR is not connected, so there is no chart to read. You are live when the first authorization is prepared: staff approved a drafted answer set, or a workflow filled a portal form for a person to send. # Calls, inbox, and reports Source: https://docs.healos.ai/guides/receptionist/calls-and-inbox What your staff sees after every call. ## Dashboard Calls handled, average duration, appointments booked, AI-resolved calls, missed and voicemails, after-hours calls, charts by type and hour, top callers. **Download PDF** and a weekly report email. > [!TIP] > > Pulling calls into your own system? The External API returns the same data: see the [Receptionist call transcripts](/recipes/receptionist-call-transcripts) recipe. ## Inbound Calls **Call History** lists every call. Filter by status (Completed, Missed, Voicemail, Failed), source, language, and date. Search by name or phone. **Export CSV**. Click a call to open **Call Details**: > [tab] Transcript > > The full conversation, with timestamps. Copy or download. > [tab] Summary > > Outcome, notes, and the key information the AI captured. > [tab] Recording > > Audio player and download. > [tab] Events > > Every lookup, booking, transfer, and text the AI made, with the result. Transfer results read as connected, no answer, line busy, or voicemail. > [!TIP] > > **Events** is the first place to look when a booking or transfer did not go as expected. "No answer" means your line rang and nobody picked up, so the AI took a message instead. **Create task from call** is in the row menu. ## Inbox Tasks Every message, refill request, callback, and follow-up. Filter by type, status, category, and date. Assign a **Provider**, link a **Patient**, add notes, **Mark done**. Done items archive after 30 days. ## Providers Add providers for task assignment and per-provider notifications: text or email a provider when a refill or urgent request comes in. Providers do not need a HealOS login to receive these. ## Intake Forms Build your own forms, or have HealOS extract them from a photo of your paper form. Group them into **Appointment Categories**, set per-doctor links, and review **Submissions**. Approve a submission to create or link the patient. # Connect your EHR Source: https://docs.healos.ai/guides/receptionist/connect-your-ehr Let the AI look up patients, check real availability, and book in your EHR. **AI Frontdesk → Integrations** ("AI Receptionist Integrations") → **Connect an EHR**. **1. Pick your system** The **Connect an EHR** screen lists every system the AI can use for live calls. Choose **HealOS Scheduling** if you have no EHR and want HealOS to act as your calendar. > [!NOTE] > > Not in the list? Email [team@healos.ai](mailto:team@healos.ai) and we will tell you whether it can be added. **2. Connect** Click **Connect** and follow the steps the dialog shows for your system. Each EHR has its own short connection flow; the screen walks you through it. > [!TIP] > > A dedicated HealOS user in your EHR keeps the connection stable when staff change their own passwords. **3. Choose what the AI may do** Under **AI Actions in the EHR**, tick the allowed actions. Unsupported ones for your EHR are marked. | Action | Default | | - | - | | Read Patient Details | Always on | | Create Patient Record | On | | Check Available Slots | Always on | | Create Appointment | On | | Reschedule Appointment | On where supported | | Cancel Appointment | On where supported | | Add Call Notes | On where supported | | Benefit Verification | Off | **4. Set booking defaults and provider routing** * **Booking defaults**: default provider, appointment type, and **Appointment duration** used when the caller does not specify. * **Provider routing**: one row per category, with the provider, the appointment type, and the phrases callers use ("new patient", "physical therapy", "Dr. Chen"). New-patient and follow-up visits usually need separate rows. **5. Set provider office hours** Working days and hours per provider. > [!WARNING] > > **These must match the EHR.** If HealOS says Wednesday 2–5 and the EHR says 1–5, patients hear "not available" for real openings, or a booking lands where the provider is not working. ## Benefit Verification Off by default. When on, the AI checks insurance eligibility before booking. Turn on **Offer self-pay when coverage can't be verified** so a failed check does not end the call without a booking. ## How the AI identifies a patient The AI confirms the caller's **name and date of birth**, then looks them up in your EHR. Returning patients are matched to their existing chart; new callers are registered if **Create Patient Record** is on. > [!NOTE] > > When a lookup fails it is almost always a spelling or DOB mismatch. The AI asks callers to spell their last name and reads the DOB back. A nickname on file ("Bill" vs "William") can still cause a miss. ## Disconnecting **Disconnect** stops all EHR actions immediately. Booking defaults are kept for when you reconnect. # Custom workflows Source: https://docs.healos.ai/guides/receptionist/custom-workflows When the settings cannot express how your practice handles calls, send us your script and we build it. The settings cover most practices. Some call handling is more specific than any setting can express, for example: * Fixed booking slots (10:30, 11:00, then 2:30 to 4:00 only) * Insurance verified before the calendar is even mentioned * Message-only during lunch, no booking after 5 PM, weekends to urgent care * A scripted greeting read word for word * Different rules per provider or per location * A specific order of questions, or questions the AI must never ask twice In those cases, **do not try to force it through the free-text fields.** Ask us to set up a custom workflow and custom instructions for your practice. ## How to request one **1. Gather what your front desk already follows** A written call script, a flowchart, a decision tree, or a standard operating procedure. Word, PDF, a Google Doc link, or even a photo of the paper version is fine. If nothing is written down, list the rules in plain language. **2. Add a few example calls** Two or three short examples of what should happen: "New patient calls at 4:49 AM → take a message, do not offer a slot." **3. Send it through your upload link** Ask for an upload link in the in-app chat. Open it and add a screen recording or screenshots of the script, the examples, and who at the practice confirms the final version. The link is for your practice only and expires, so nothing sits in an inbox. ## What stays in your control While a custom workflow is active, your Settings page shows a banner saying the call script is managed by HealOS. These still work from Settings exactly as before: * Greeting and AI name * EHR actions and booking defaults * Transfer numbers * Intake form settings Call-handling rules and FAQs entered in Settings are saved but do not change the custom script. Send changes through an upload link (ask for one in the in-app chat) and we usually have them live within a day. > [!TIP] > > Not sure whether your case needs a custom workflow? Send the script anyway. If a setting already covers it, we will point you to it. # FAQ Source: https://docs.healos.ai/guides/receptionist/faq Testing, transfers, intake forms, languages, recordings, reminders, and billing. > [accordion] Do I need to forward my line to test? > > No. Call the HealOS number directly from a cell phone. > [accordion] Can callers press a number to reach a person? > > There is no key-press menu. The AI understands "I want to speak to someone" and follows your **Caller insists on a live person** routing. > [accordion] Does the AI read back the caller's number? > > It confirms the callback number the caller gives. It never reads your office number as the caller's number. > [accordion] Can it tell patients our fax number, parking, or portal link? > > Yes. Put it in the **Knowledge base** FAQs. > [accordion] Can it send the intake form by email? > > It texts the link, and also emails it when the caller shares an email address during the call. Staff can send a form manually from **Intake Forms → Send Form** with a phone number and/or email. > [accordion] Can we have different intake forms per doctor? > > Yes, via **Appointment Categories** and per-form links under **Intake Forms → General Settings**. > [accordion] Is there hold music during transfers? > > Callers hear ringing while the AI reaches your staff. > [accordion] Are calls recorded? > > Yes, up to the moment a transfer connects. Recordings and transcripts are under **Inbound Calls**. > [accordion] What languages are supported? > > English plus the languages you enable in the Voice card (Spanish, Mandarin, Cantonese, and others depending on the voice). The greeting starts in English and follows the caller. > [accordion] Can the AI book in an imported (subscribed) Google calendar? > > No, those are read-only. Book into a calendar the connected account owns, and add the imported one as an **External busy calendar** so its events block slots. > [accordion] Does the AI send appointment reminders? > > Confirmation texts, yes. Reminder sequences are coming; the **Reminders** tab under Appointments shows the status. > [accordion] Our call flow is complicated and I can't find a setting for it. What do I do? > > Ask for an upload link in the in-app chat and add a screen recording or screenshots of your existing call script or workflow document; we set up a custom workflow. See [Custom workflows](/guides/receptionist/custom-workflows). > [accordion] Will changes I make in Settings take effect, or does HealOS need to do something? > > They take effect on the next call once saved. If you are on a custom workflow managed by HealOS, the Settings page shows a banner and script changes go through us. > [accordion] How is usage billed? > > Per minute of completed call time, plus texts sent. **Subscription** shows your plan and included minutes. # Google Calendar booking Source: https://docs.healos.ai/guides/receptionist/google-calendar Book appointments on Google Calendar instead of an EHR. Settings → **Automations** → **Google Calendar** → **Connect**. Allow the popup, sign in to the Google account that can see every provider's calendar, and grant access. ## The Google Calendar dialog | Setting | What it does | | - | - | | **Calendar to use** | The calendar to book into. Becomes **Fallback calendar** once you add providers. | | **Providers** | One row per doctor: their own calendar, specialty, a one-line blurb, optional custom working hours. The AI asks which provider the caller wants. | | **Appointment types** | Name, duration, buffer. | | **Working hours** | Per day. | | **Booking rules** | **Min notice**, **Max advance (days)**, **Allow double-booking** (keep off), and **External busy calendars**. | > [!TIP] > > **External busy calendars** takes iCal feed URLs, one per line. Times booked in another system are read live before every offer, so they are never double-offered. Only busy times are read; event details stay private. ## Two things to know > [!WARNING] > > Calendars you have **subscribed to** (imported, read-only) cannot be booked into. The AI needs a calendar the connected account can write to. Add the subscribed one as an external busy calendar instead. > [!NOTE] > > Your Google calendar's timezone is treated as the source of truth. Make sure it matches the practice. # Overview Source: https://docs.healos.ai/guides/receptionist/overview What HealOS AI Receptionist (AI Frontdesk) does and where to start. Patients call your number. HealOS answers in a natural voice, 24/7, and handles the call the way you configure it. > [card] Book appointments > > Offers real open slots from your EHR or Google Calendar and books them. > [card] Recognize patients > > Looks up returning patients and registers new ones in your EHR. > [card] Transfer and take messages > > Warm-transfers to staff with a spoken summary, or files a task for a callback. > [card] Answer questions > > Hours, insurance accepted, parking, services, from your knowledge base. > [card] Text patients > > Intake form links and appointment confirmations by SMS. > [card] Handle emergencies > > Flags urgent calls and routes them to the number you set. Everything it does on a call is visible afterwards under **Inbound Calls** (transcript, summary, recording, every action taken) and **Inbox Tasks**. > [!NOTE] > > **Your call handling is more complex than the settings allow?** Send us your call script or workflow document and we set it up for you. See [Custom workflows](/guides/receptionist/custom-workflows). ## Where to go next > [card] [Setup checklist](/guides/receptionist/setup) > > From "Start Setup" to the first live call, in order. > [card] [Settings](/guides/receptionist/settings) > > Every section, with defaults. > [card] [Phone number and forwarding](/guides/receptionist/phone-and-forwarding) > > Get a number, forward your line, avoid the two settings that drop calls. > [card] [Connect your EHR](/guides/receptionist/connect-your-ehr) > > Actions, booking defaults, provider routing, office hours. > [card] [Google Calendar booking](/guides/receptionist/google-calendar) > > Book without an EHR. > [card] [Troubleshooting](/guides/receptionist/troubleshooting) > > Transfers, bookings, languages, forwarding. > [!TIP] > > Three things cause most support tickets: transfer numbers without the country code, provider hours that do not match the EHR, and a **Maximum booking window** that is too short. # Phone number and forwarding Source: https://docs.healos.ai/guides/receptionist/phone-and-forwarding Get your AI number, choose how patients reach it, and avoid the two phone-system settings that drop calls. ## Two ways to go live > [card] Keep your number, forward calls > > Recommended. Patients keep calling the number they know. Your carrier forwards to the HealOS number. > [card] Use the HealOS number directly > > Put the new number on your website and Google Business Profile. No forwarding needed. ## Get the number On "Your AI Frontdesk is ready" (or Settings → **AI Phone Number** → **Change**): search by area code, pick a number, **Activate & assign number**. > [!NOTE] > > The number works as soon as it is assigned. Call it from a cell phone to test booking and transfers before you change any forwarding. ## Forward your existing line Under "Connect to your existing line", pick your **Phone system type** (cell, VoIP, landline) and your **provider**. HealOS shows the exact steps or dial codes for that carrier, with a copy button on each. > [tab] Cell carriers > > AT\&T and T-Mobile use `**21*#` to enable and `##21#` to disable. Verizon uses `*72` and `*73`. The screen shows the codes for your carrier. > [tab] VoIP systems > > RingCentral, Google Voice, Vonage, Dialpad, 8x8, and Zoom Phone all have a "forward all calls" setting in their admin console. The screen shows the menu path for each. > [tab] Landlines > > Most support `*72` and `*73`. Otherwise contact your provider. Some charge a monthly forwarding fee. ## Before you forward > [!WARNING] > > **Turn off "confirm connection", "press 1 to accept", and call screening on the forwarding rule.** The AI cannot press keys. With these on, a large share of calls drop before the AI speaks. * Turn off voicemail on the forwarded line so it does not race the AI. * Save the HealOS outbound number in staff phones. On iPhones, unsaved numbers can be caught by Call Screening, which makes warm transfers fail. ## Turning it off temporarily Remove the forwarding rule (the disable code is shown on screen). Calls ring your front desk again immediately. # Settings Source: https://docs.healos.ai/guides/receptionist/settings Every section of Frontdesk Settings, what it controls, and the defaults. **AI Frontdesk → Settings** ("Frontdesk Settings"). The left rail lists the sections; each has a **Save & continue** button. Changes save to the live agent, so the next call uses them. ## Practice profile Name, main phone, specialty, **Timezone**, locations, providers. > [!WARNING] > > Check the **Timezone**. The default is America/New\_York. Provider names here must match your EHR spelling exactly; a typo stops tasks from auto-assigning to that provider. ## Voice & identity * **AI receptionist name** (for example "Ava"). Leave blank for "the AI assistant". * **Business-hours greeting** and **After-hours greeting**. Write them exactly as you want them read. * **Include emergency safety line**: on by default. Prepends "If this is a medical emergency, hang up and dial 911." * **Pronunciation overrides**: spell tricky names phonetically (Dr. Nguyen → "Win"). Also useful for your web address. * **Voice**: in the Voice card lower on the page. Preview, pick, **Apply**. * **Speak in** (multilingual voices): a specific language, or **Multilingual (auto-detect)** so the AI follows the caller. * **Languages the receptionist speaks**: tick every language your patients use. Greyed-out ones are not supported yet. ## Office hours Weekly schedule, exceptions (lunch, holidays), and **After-hours handling**: | Option | Behavior | | - | - | | **Take a message + create staff task** (default) | After-hours greeting, then a message and a task. | | **AI answers 24/7** | Same capabilities as business hours, including booking. | | **Urgent calls transfer only** | Everything else goes to voicemail. | ## Caller info Name, phone, and reason are always captured. Tick extra fields to collect: **Date of birth**, **Insurance provider / member ID**, **Email address**, **Preferred callback time**, **Pharmacy**, **Referring provider**. Add **New patient intake questions** one per line; answers land in the call summary. ## Call routing One row per call type. | Call type | Default action | | - | - | | New patient booking, Existing patient booking | Auto-book in EHR | | Cancellation, Rescheduling, Prescription / refill, Lab results, Insurance company calling, Referral from another provider | Take message / task | | Billing / payment inquiry, Caller insists on a live person, Pharmacy calling | Warm transfer | | General FAQ | AI answers | For every **Warm transfer** row enter the number in full international format (`+1` then 10 digits) and an optional extension. Add **Custom routing rules** for anything else. > [!WARNING] > > **Give live-person transfers a working destination.** If the only number you enter is the billing line, callers who ask for a human are sent to billing. ## Automations | Setting | What it does | Default | | - | - | - | | **Auto-Schedule Appointments** | Books directly. **Booking Duration** and **Buffer Time** set the slot cadence. | On, 30 min, 15 min buffer | | **Minimum booking lead time** | Blocks bookings sooner than N days. 1 = no same-day. | Off | | **Maximum booking window** | Blocks bookings further out than N days. | Off | | **Send Intake Forms** | Texts new patients the intake link, and emails it if the caller shares an address. | Trigger: new patient calls only | | **Appointment Confirmations** | Confirmation text after booking. Edit the template with `{{first_name}}`, `{{date}}`, `{{time}}`. | On | | **Send Links via SMS** | Text a link when a caller asks for directions, the portal, and so on. | Off | | **Email Notifications** | Recipients for completed-call emails. | On | > [!TIP] > > If your providers book weeks ahead, leave **Maximum booking window** off or set it high. A low value makes the AI tell patients "we'll call you back". ## Escalation **Emergency keywords** (chest pain, shortness of breath, bleeding, unconscious, stroke, severe pain, allergic reaction by default), **Emergency transfer number**, **After-hours emergency number**, **Route self-harm to 988** (on by default), optional direct-to-911 keywords, and specialty-specific rules. ## Knowledge base **Services offered**, **Accepted insurance plans**, **Plans NOT accepted**, **Frequently asked questions**, **What the AI must never say**. > [!TIP] > > FAQs are read to the AI word for word. Put your fax number, parking instructions, and portal link here if patients ask for them. ## Special workflows Short free-text rules the AI follows on every call: "Always confirm the caller is an established patient before continuing", "Remind patients to arrive 15 minutes early". > [!NOTE] > > If the setting you need is not on this page, do not force it through free text. Send us your call script or workflow document instead. See [Custom workflows](/guides/receptionist/custom-workflows). ## Voice, phone number, rebuild, reset Below the sections: the **Voice** card, the **AI Phone Number** card (**Change** number), **Run AI Builder** (re-run guided setup), and **Reset Configuration**. > [!WARNING] > > **Reset All Settings** wipes everything. Ask us before using it. # Setup checklist Source: https://docs.healos.ai/guides/receptionist/setup From Start Setup to the first live call. A practice can be live in one sitting. **1. Start setup** **Front Office → AI Frontdesk → Start Setup**. **2. Let the AI draft your setup** On "Let the AI study your practice", enter **Practice name**, **Specialty**, **Main phone number**, and your **Practice website** if you have one. HealOS drafts the greeting, hours, call types, and FAQs from it. Or choose **Skip and fill in manually**. **3. Review the three chapters** **Identity** (who the AI is), **Operations** (what it does), **Growth** (optional). Click any line to change it, or **Advanced edit** for the full form. **4. Fill the required fields** Only three things block go-live: practice name, main phone, and **BAA signed?** Everything else has sensible defaults you can change later. **5. Set office hours and after-hours behavior** Default is Mon–Fri 9:00–17:00, weekends closed, after hours = **Take a message + create staff task**. **6. Set call routing** For each call type pick **Auto-book in EHR**, **Warm transfer**, **Take message / task**, or **AI answers**. > [!WARNING] > > Warm transfer needs a full phone number with country code, for example `+12125550142`. A row without a valid number cannot transfer. **7. Add the escalation number** **Emergency transfer number**, and optionally an **After-hours emergency number**. **8. Fill the knowledge base** Services, accepted and not-accepted insurance, FAQs, and "What the AI must never say". **9. Create the agent** On "Review & create agent", click **Create agent**. Takes about a minute. **10. Get your AI phone number** On "Your AI Frontdesk is ready", click **Get AI phone number**. Search by area code, pick a number, **Activate & assign number**. **11. Test with a web call** Click **Test a web call**. Live transfer and SMS do not work on web test calls; test those from a real phone once the number is live. **12. Connect your EHR or calendar** Until this is done the AI takes messages instead of booking. See [Connect your EHR](/guides/receptionist/connect-your-ehr) or [Google Calendar](/guides/receptionist/google-calendar). **13. Forward your line** Follow the carrier-specific steps on screen. See [Phone number and forwarding](/guides/receptionist/phone-and-forwarding). **14. Call the number from a cell phone** Book a test appointment, ask for a transfer, hang up mid-call. Then check **Inbound Calls** and **Inbox Tasks** to see what was captured. > [!NOTE] > > If your call handling has rules that do not fit these screens, stop here and read [Custom workflows](/guides/receptionist/custom-workflows). # Transfers, messages, and texts Source: https://docs.healos.ai/guides/receptionist/transfers-and-messages What happens on a call: warm transfers, taking a message, after hours, texts, and emergencies. ## Warm transfer **1. The AI announces the transfer** "I'm connecting you with our front office now." The caller hears ringing while on hold. **2. Your staff line rings** When someone answers, the AI tells them who is calling and why. **3. The caller is connected** Nothing is recorded after the transfer connects. If the line is busy, unanswered after about 30 seconds, or goes to voicemail, the AI comes back to the caller and takes a message. The outcome (connected, no answer, line busy, voicemail) is shown on the call under **Inbound Calls**. > [!TIP] > > Transfer to a direct line or extension, not your main auto-attendant. An IVR answering the transfer makes the AI repeat "would you like to connect?". ## Taking a message The AI collects name, DOB, callback number, and reason, files a task under **Inbox Tasks**, and tells the caller someone will call back. This is what happens whenever booking is off, the EHR is not connected, or routing says **Take message / task**. ## After hours The after-hours greeting plays and the AI follows your **After-hours handling** setting. > [!NOTE] > > If you want zero bookings outside office hours, keep "Take a message" and tell us so we can enable strict closed-hours mode for your practice. ## Texts patients receive * Appointment confirmation, if **Appointment Confirmations** is on. * Intake form link, if **Send Intake Forms** is on and the caller is a new patient. * Any links you configured under **Send Links via SMS**. Intake links expire after a set time; patients can ask for a new one. ## Emergencies Keywords trigger the **Emergency transfer number**, or the 911 / 988 guidance you configured under **Escalation**. # Troubleshooting Source: https://docs.healos.ai/guides/receptionist/troubleshooting What you see, what is usually going on, and what to do. ## Transfers > [accordion] “It didn't transfer even though I set up call routing” > > The transfer number is missing the country code, or the row is not set to **Warm transfer**. > > Enter `+1` followed by 10 digits, save, and test from a cell phone. > [accordion] “It hangs up on patients who ask for a receptionist” or “says they aren't available” > > The staff line was busy or unanswered, or an iPhone screened the transfer call. > > Add a second live-person destination. Save the HealOS outbound number in staff phones. Turn off Call Screening. > [accordion] Callers asking for a person get sent to billing > > Billing was the only transfer number configured. Add a number to **Caller insists on a live person**. > [accordion] “Would you like to connect?” repeated several times > > The transfer reached your practice's own auto-attendant, not a person. Transfer to a direct line or extension, not the main IVR. > [accordion] Summary says “transfer failed” or “technical difficulties” > > Usually nobody answered the staff line. Check the **Events** tab on the call for the real outcome. ## Phone and forwarding > [accordion] A large share of calls drop before the AI speaks > > The forwarding rule has "confirm connection" or "press 1 to accept" on. Turn it off on the forwarding rule. > [accordion] The AI stopped answering entirely > > A rare platform-side issue. Remove forwarding so calls ring your desk, and tell support. We send the missed-call list afterwards. ## Booking > [accordion] “It says the doctor isn't available but the schedule is open” > > Provider hours in HealOS differ from the EHR, or the provider is mapped to more than one location. Match **Provider office hours** to the EHR. One location per provider. > [accordion] “It said it booked but nothing is on the calendar” > > The booking was not completed (EHR error), or it landed on a different provider or location. Open the call's **Events** tab. If booking shows an error, tell support with the call time. > [accordion] Patients told “we'll call you back” instead of being booked weeks out > > **Maximum booking window** is too short. Raise it or turn it off. > [accordion] Appointment booked at the wrong time, hours off > > A timezone mismatch between HealOS, the EHR, or the Google calendar. Check **Timezone** in Practice profile and the calendar's timezone. > [accordion] “Patient not found” for an existing patient > > Spelling or DOB mismatch, or a nickname on file. The AI asks callers to spell the name and reads the DOB back. Correct the chart if it uses a nickname. > [accordion] Even the test call only takes a message > > The EHR or calendar is not connected yet, or **Auto-Schedule Appointments** is off. See [Connect your EHR](/guides/receptionist/connect-your-ehr). ## Voice and language > [accordion] The AI answers in the wrong language > > **Speak in** is set to one language, or the voice does not support the caller's language. Set **Speak in** to **Multilingual (auto-detect)**, tick the languages, and pick a voice that supports them. > [accordion] Names or medications misheard repeatedly > > Common with unusual names and drug names. Add pronunciation overrides, and ask us to add a spell-back rule and a medication list for your specialty. ## Settings and tasks > [accordion] Settings will not save, “updated somewhere else” > > Someone else edited settings, or the page was open a long time. Reload the page and save again. > [accordion] “The settings can't express how we handle calls” > > Your workflow is more complex than the built-in options. Send us your call script or workflow document. See [Custom workflows](/guides/receptionist/custom-workflows). > [accordion] Caller hung up mid-call and no task appeared > > A task is only created when the AI captured a request. Check **Inbound Calls** for the transcript. Ask us to enable follow-up tasks for incomplete calls. > [accordion] Intake form sent after a cancellation > > **Trigger Condition** is set to "All callers". Set it to "New patient calls only". > [accordion] Provider notifications or task assignment not working > > The provider name in Settings does not match the name callers use or the EHR spelling. Fix the spelling under Providers and Practice profile. > [accordion] “This feature needs to be turned on” for a new team member > > Product access has not been granted. The practice admin grants AI Frontdesk access; otherwise contact support. ## When to contact support Use the in-app chat or [team@healos.ai](mailto:team@healos.ai) when: * The AI stops answering, or every call fails at once. * A booking shows an error in the **Events** tab. * Your call handling needs a custom workflow the settings cannot express. Send your script or workflow document. * You need an EHR that is not listed. > [!NOTE] > > Send the caller's phone number (or "web test"), the date and time, and what you expected to happen. We can trace every call from that. # Chrome extension and EHR push Source: https://docs.healos.ai/guides/scribe/chrome-extension Record and insert notes inside your EHR, or push notes directly from the web app. ## Install **1. Sign in on the HealOS website** Open **app.healos.ai** and sign in. The extension picks up your session from there. **2. Get the extension** Sidebar → **Chrome Extension** → **Get Healos.ai Chrome Extension**. Add it from the Chrome Web Store. **3. Open it on your EHR page** Click the HealOS icon in the toolbar while on your EHR. The panel shows "Sign in on the HealOS website. The extension will unlock automatically." only if you skipped step 1. ## Use it The panel has two views. > [tab] Capture Visit > > Search or add the patient, pick a template, **Record** → **Pause** / **Resume** → **Stop**. > [tab] Sessions > > Open a finished session, then **Copy** or **Insert into EHR**. You can also right-click any text field in the EHR and choose **Healos → Paste Entire Note**, or a single section such as **Paste Subjective** or **Paste Assessment**. > [!WARNING] > > **Before you insert:** open the patient's chart and the note editor (encounter or SOAP screen). If the editor is not open you will see "Could not find a suitable frame with note sections". Confirm the right patient is open; the extension warns if the chart does not match the session. ## Keeping it current The extension updates itself through the Chrome Web Store, usually within half a day of a release. EHR vendors change their pages from time to time and we ship an update to match. > [!TIP] > > If inserting stops working after it "worked yesterday", check the version at `chrome://extensions` and tell us. That is almost always an EHR page change waiting for the extension update. ## Supported EHRs Works with most web-based EHRs. The **Integrations** page in the app shows what is supported for your practice. If yours is not there, email [team@healos.ai](mailto:team@healos.ai). ## Push to EHR without the extension Some EHRs accept notes directly from the web app with the **Push to EHR** button on the session page. Connect them under sidebar → **Integrations**. Each EHR card on the Integrations page says which path it uses: **Push to EHR** from the web app, or chart insertion through the Chrome extension. > [!NOTE] > > If **Push to EHR** says "Patient link still pending", link the patient in the EHR first and push again. # FAQ Source: https://docs.healos.ai/guides/scribe/faq Signing, telehealth, patient instructions, retention, billing, and team management. > [accordion] How do I approve and sign a note? > > Review it on the session page. There is no separate approval step. Add your signature under Account Settings → **Signature** so it appears on exports. > [accordion] Can I use this for telehealth? > > Yes. Record from the web app on the same computer that runs the video call, with the microphone set to the device that picks up both sides, or use the Chrome extension inside your EHR. Test once with a colleague before a real visit. > [accordion] How do I get word-for-word transcription for X-ray or procedure reports? > > Add a section to your template with the word-for-word instruction from [Templates](/guides/scribe/templates), or ask support to add it. > [accordion] Can I add a patient instructions section? > > Yes, in a custom template: add the **Patient Education** or **Patient Follow Up Email** section. You can also ask the AI Editor for a **Patient handout** after the note is generated. The built-in visit templates cannot be modified, so copy one first. > [accordion] How do I delete a custom template? > > Open it under **Templates → Custom** and delete it from there, or ask support. Deleting a template does not affect notes already generated. > [accordion] Does HealOS store the audio? > > Only if you turn on **Enable dictation playback**. Otherwise audio is used for transcription and not kept for playback. > [accordion] Can I see the previous provider's note for a new patient? > > Upload it under **Patient Documents** before recording, or turn on **Use Prior Context** if the previous visit was in HealOS. > [accordion] Where do I change data retention? > > Account Settings → **Data retention**. This is a per-user account setting, not part of AI Front Desk. > [accordion] Does HealOS enter charges or bill for me? > > AI Scribe suggests ICD-10 and CPT codes for you to review. It does not submit claims. Ask us about the billing products if you need that. > [accordion] How do I remove a team member? > > Practice admins remove members from the organization settings. Contact support if the option is missing. > [accordion] Is there a free plan? > > Yes, with a monthly session limit. **Subscription** in the sidebar shows your plan and upgrade options. # Mobile app Source: https://docs.healos.ai/guides/scribe/mobile-app Recording on iOS and Android with the same account and sessions. Same account, same sessions. The bottom tabs are **Sessions**, **Select Patient**, **Settings**, and **Appointments**. **1. Pick the patient** **Select Patient**, then open **Capture Session**. **2. Record** Start the session. Recording continues if you minimize the app or lock the phone. **3. End the session** Tap **End session**. The note generates and appears on the phone and on the web. ## Good to know * If the app closes mid-visit, it offers **Unfinished Recording Found → Continue** on next launch. * **Regenerate** a note with a different template or quality (**Balanced**, **Detailed**, **Concise**) from the session details. * Note preferences (language, template, terminology) are set on the web, not in the app. > [!WARNING] > > Keep the app updated. If sessions show on the phone but not on the web, the app is on an old version. # Overview Source: https://docs.healos.ai/guides/scribe/overview What HealOS AI Scribe does and where to start. You record the visit. HealOS transcribes it and writes a structured clinical note in the template you choose. You review the note, refine it with the AI Editor if needed, then copy it, export it, or push it into your EHR. > [card] Web app > > Record at **app.healos.ai**, review notes, manage templates and settings. > [card] Chrome extension > > Record and insert notes without leaving your EHR tab. > [card] Mobile app > > Record on iOS or Android. Sessions sync to the web. ## How it works **1. Pick the patient and template** Search or add a patient, choose a visit template, confirm consent. **2. Record the visit** Start recording, pause and resume as needed, end the session. Or upload audio, or type the encounter. **3. Review the note** Edit manually or ask the AI Editor. Check the suggested ICD-10 and CPT codes. **4. Send it to your chart** Copy, export as PDF or DOCX, push to a connected EHR, or insert with the Chrome extension. > [!NOTE] > > One visit is one session. A session holds the transcript, the note, and any extra documents you generate from it. Nothing is signed or sent anywhere until you act on it. ## Where to go next > [card] [Setup checklist](/guides/scribe/setup) > > Account, profile, phone verification, defaults, extension. About 15 minutes. > [card] [Record your first visit](/guides/scribe/record-a-visit) > > Step by step through the session screen. > [card] [Settings that matter](/guides/scribe/settings) > > Transcript language, default template, note style, retention. > [card] [Templates and dot phrases](/guides/scribe/templates) > > Make the note sound like you. > [card] [Troubleshooting](/guides/scribe/troubleshooting) > > What you see, what is going on, what to do. > [card] [FAQ](/guides/scribe/faq) > > Signing, telehealth, retention, billing. > [!TIP] > > Three things cause most support tickets: the microphone too far from the conversation, the wrong **Transcript Language**, and an out-of-date Chrome extension. Each is a one-minute fix. # Record a visit Source: https://docs.healos.ai/guides/scribe/record-a-visit From choosing the patient to a finished note, in the web app. **1. Choose the patient** Sidebar → **AI Scribe** → **Record**. Type in **"Search or add patient name"**. Pick an existing patient or choose **Add "…" (New patient)**. If your EHR is connected, a **From EHR** group appears so you can pick the chart directly. Some EHRs get their own **Search in …** box on this screen. > [!NOTE] > > You cannot start recording without a patient selected. That is what lets HealOS pull prior-visit context. **2. Confirm consent** The first thing on the session screen is **Patient Consent for Recording**. Tell the patient the visit is being recorded, then click **I Confirm Patient Consent**. You can turn this prompt off under Account Settings → **Show Consent Prompt**. **3. Pick the template and note style** * **Choose template**: start with **New Patient Visit** or **Follow-Up Patient Visit**. Custom templates appear here once you create them. * **Select note quality**: **Balanced**, **Fast**, or **Detailed**. Detailed takes longer but produces the most complete note. Optional but useful: * **Patient context**: a free-text box for anything the AI should know. Read-only once recording starts. * **Patient Documents**: upload reports, prior notes, or intake forms. The note can pull from them. **4. Record** Click **Start recording**. Allow microphone access when the browser asks. **Pause** and **Resume** as needed. Click **End Session** when the visit is over. > [!WARNING] > > Record for at least **1 minute**. Stopping earlier shows a **Recording Too Short** warning because very short audio produces thin notes. ## Recording modes Use the small arrow next to **Start recording** to pick a microphone and a **Recording Mode**. > [tab] Batch (recommended) > > Audio uploads in 30-second pieces while you talk. The transcript appears after you end the session. Works well on ordinary office Wi-Fi. > [tab] Live > > The transcript appears on screen as you speak. Useful when you want to glance at what was captured mid-visit. Needs a stable connection. > [tab] Offline > > Saves locally and uploads when you are back online. Use this on unreliable Wi-Fi or when travelling between sites. > [!TIP] > > Keep the device within a few feet of the conversation. Almost every "no note was generated" report turns out to be audio with no audible speech: laptop across the room, another app holding the microphone, or a muted input. ## Other ways to create a note Below the recorder, under **"or use a different input"**: > [card] Upload audio > > Drop in an existing recording, up to 50 MB. The note generates in the background. > [card] Type the note > > Write the encounter as text and click **Generate Note**. ## What happens next After **End Session**, HealOS finalizes the transcript and generates the note. The session page shows a **Note** tab, a **Transcript** tab, and a **Session Summary** card. * If generation takes more than a minute you will see **"Taking too long? Try again"**. * If it fails outright you will see **Note generation failed** with a **Regenerate Note** button, which rebuilds from the saved audio. Next: [Review and use the note](/guides/scribe/review-notes). # Review and use the note Source: https://docs.healos.ai/guides/scribe/review-notes Editing, the AI Editor, codes, export, and pushing to your EHR. Open a session from **Record** (past sessions) or from **View Past Sessions** on the patient page. The note screen has a **Note** tab and a **Transcript** tab. ## Actions on the note | Button | What it does | | - | - | | **Edit** → **Save** / **Cancel** | Manual edits, section by section. | | **AI Editor** | Chat sidebar. Describe a change and review the proposed diff before accepting. | | **⋯ More Options** | **Copy All**, **Regenerate Note**, **Export as TXT / PDF / DOCX**, **Send to Email**. | | **Generate Note** / **Generate Document** | Create an additional note or document from the same visit with a different template, such as a referral letter or patient summary. | | **Push to EHR** | Sends the note to your connected EHR. See [Chrome extension and EHR push](/guides/scribe/chrome-extension). | | **ICD-10 Diagnostic Codes** / **CPT Procedure Codes** | Suggested codes panel. Toggle between the two and copy what you need. | ## The AI Editor Ask for one change at a time: "tighten the HPI", "add that the patient denies chest pain", "use the patient's name". Quick skills are one click away: **Tighten language**, **Simplify**, **Use patient name**, **Align ICD-10**, **Align CPT**, **Differential prompts**, **Red flags**, **Patient handout**. > [!TIP] > > After accepting an edit that touches the Plan or medications, glance at that section to confirm it landed. If the editor stops responding, reload the page and start a new conversation. ## The note quality banner Sometimes a note shows "Review this note carefully". That is HealOS flagging possible mismatches between the note and the transcript. It is a prompt to review, not an error. ## Signing HealOS has no separate "sign" step. The note is ready when you have reviewed it. To include your signature on PDF and DOCX exports, upload it under Account Settings → **Signature** and turn on **Include in exports**. ## Deleting and restoring Deleted sessions go to **Deleted Notes** (the Recycle Bin), where they can be restored or removed permanently. # Settings Source: https://docs.healos.ai/guides/scribe/settings The Account Settings that shape every note, with defaults and what we recommend. Sidebar → **Account Settings**. Click **Save Changes** after editing. ## Language and template | Setting | What it controls | Default | Recommendation | | - | - | - | - | | **Transcript Language** | The language the speech engine listens for. | English (US) | Set this before the first visit. For bilingual visits, pick the language most of the conversation is in. English medical terms mixed into another language are fine. One language per account. | | **Default Note Language** | The language the note is written in. | English | Leave on English unless you chart in another language. | | **Default Template** | Template pre-selected on each new session. | New Patient Visit | Switch to your most common visit type once you have a custom template. | | **Default AI Model** | Note style: Balanced, Fast, or Detailed. | Detailed | Detailed for complex visits, Balanced for high-volume days. | | **Specialty** (set during onboarding) | Injected into every note. Drives what the AI assumes about you. | Your choice | Use **Other** plus the exact sub-specialty if yours is not listed. | > [!WARNING] > > **Transcript Language** is the setting behind most "the note is in the wrong language" and "the note says the opposite of what I said" reports. Check it first. ## Behavior | Setting | What it controls | Default | Recommendation | | - | - | - | - | | **Show Consent Prompt** | Pop-up before every recording. | On | Keep on unless consent is captured elsewhere. | | **Preserve Markdown Formatting** | Bold, bullets, and indentation kept when copying. | On | Turn off if your EHR shows stray symbols after paste. | | **Use Prior Context by Default** | Start each note with the patient's previous visits in context. | Off | Turn on for follow-up heavy practices. | | **Default Physician Term** / **Default Patient Term** | How the note refers to you and the patient ("Dr.", "Provider", "Client"). | Dr. / Patient | Therapy practices usually want "Client". | ## Retention and audio | Setting | What it controls | Default | Recommendation | | - | - | - | - | | **Automatically delete sessions** + **Delete after … days** | Retention preference, 1 to 90 days. | Off / 90 | Set according to your practice policy. | | **Enable dictation playback** | Store the audio so you or staff can replay it. | Off | Turn on only if you want playback. You must have patient consent to store audio. | ## Exports | Setting | What it controls | Default | | - | - | - | | **Signature** | Signature image appended to PDF and DOCX exports. | None | | **Include in exports** | Turns the signature on. | Off | ## PHI Filter Sidebar → **PHI Filter**. Add keywords (an address, a name) that should never appear in generated notes. > [!NOTE] > > Data retention lives here under your account, not under AI Front Desk. If clicking Settings takes you to Frontdesk settings, open **Account Settings** from the sidebar instead. # Setup checklist Source: https://docs.healos.ai/guides/scribe/setup Everything to do once before the first real patient. Most practices finish in 15 minutes. **1. Create the account** Go to **app.healos.ai** and choose **Sign up**. Sign up with **Google**, **Apple**, or **email**. > [!NOTE] > > Phone-number sign-up is not offered. You verify your phone in the next step. Phone sign-in works later for accounts that already have a verified phone. **2. Complete your profile** On the "Hello, welcome to HealOS" screen enter your **Specialty**, **First name**, **Last name**, and **Title** (MD, NP, and so on). > [!TIP] > > Specialty shapes every note. If your sub-specialty is not listed, choose **Other** and type it, for example "Hand Surgery". **3. Verify your phone** Enter your number and the 6-digit SMS code. It can take up to a minute to arrive. **4. Tell us about the practice** On "Tailor your experience", pick the number of clinicians and answer **What is your EHR?** Choose "I don't use an EHR" or "Other" if yours is not listed. **5. Create or join the practice** Enter the **Practice name** and add colleague emails. If you were invited, you will see **"You've been invited"** instead. Click **Accept**. **6. Set your defaults** Open **Account Settings** from the sidebar and set at least: * **Transcript Language**: the language spoken in your visits * **Default Template**: New Patient Visit or Follow-Up Patient Visit to begin with * **Default AI Model**: Detailed unless you are high volume Click **Save Changes**. Full list on the [Settings](/guides/scribe/settings) page. **7. Install the Chrome extension (if you chart in a web EHR)** Sidebar → **Chrome Extension** → **Get Healos.ai Chrome Extension**. Sign in on the HealOS website first; the extension unlocks automatically. Details on the [Chrome extension](/guides/scribe/chrome-extension) page. **8. Install the mobile app (optional)** Same login on iOS or Android. Sessions recorded on the phone appear on the web. ## Adding team members Admins add people from the organization settings. Invitees receive an email with an **Accept** link. > [!WARNING] > > If a team member signs in and sees a screen saying a product "isn't enabled for your account", the practice admin has not granted them access to that product yet. If you are the admin and cannot see the option, contact support. # Templates and dot phrases Source: https://docs.healos.ai/guides/scribe/templates Make the note sound like you: custom templates, section instructions, and reusable snippets. ## The two built-in templates **New Patient Visit** and **Follow-Up Patient Visit** are fixed. You cannot edit their sections. If you want a different structure, create a custom template and set it as your default. ## Create a custom template Sidebar → **Templates** → **Template Library**. **1. Start from a predefined template (fastest)** Open the **Predefined** tab, preview a template, click **Customize**. It is copied into your **Custom** tab as "Copy of …". Or start from scratch: **New Template** → name it, choose **Note** or **Document** → **Proceed**. **2. Add sections** Pick from the library on the right: Chief Complaint, HPI, Physical Exam, Assessment, Plan, and 200 more. **3. Set each section's instructions** Each section has a **format** (Paragraph, Bullet Points, or Static), a **title**, **content instructions**, optional **layout** notes, and an **example**. The instructions are where you control style. **4. Choose visibility and save** **Org shared** makes it available to the whole practice. **Private** keeps it yours. Click **Save Template**. It now appears in **Choose template** on the session screen. > [!TIP] > > **Generate Template** builds a template for you from a PDF of an existing note or pasted text. Pick a detail level (**Short**, **Moderate**, **Detailed**) and review the result. ## Make the note match how you dictate The most common request we get. Put these in a section's **content instructions**. > [accordion] Word-for-word dictation (imaging reports, procedure notes) > > Add a section for the report and paste: > > > When I dictate this section, transcribe it word-for-word exactly as spoken. Do not paraphrase, summarize, reorder, or rewrite it into narrative prose. Preserve my phrasing and terminology. Only remove filler words and apply dictated punctuation such as "period", "comma", and "new line". > > Adding a one-line example in your own style anchors the output further. > [accordion] No referral suggestions in your own specialty > > In the Plan section instructions: > > > The author is the \[specialty] specialist. Do not suggest referral to \[specialty]. > > Also make sure your **Specialty** setting is exact. Choose **Other** and type the sub-specialty if needed. > [accordion] Only what the patient confirmed > > > Record only conditions the patient confirmed. Do not list negatives or "denies" statements in this section. > [accordion] Layout: one item per line, flush left > > > Each item on its own line, flush left, no paragraphs. > > Or set the section format to **Bullet Points**. > [accordion] Boilerplate you say every time > > Use a dot phrase instead (below). Dot phrases insert verbatim by design. > [!NOTE] > > Support can set any of these up for you. Tell us which template you use. ## Dot phrases Reusable text snippets. Set up a short cue once, and HealOS expands it into the full text. Sidebar → **Dot Phrases** → **New dot phrase**. * **Content**: the full text to insert. * **Shorthand**: a short code, for example `nlchest`. In a note, type `. /nlchest` and pick it from the list. * **Verbal trigger** (optional): a phrase you say out loud during the visit, for example "normal chest exam". When the note generates, the content is added for you. > [accordion] When a verbal trigger will appear > > * The trigger is turned on, **and** > * You actually said it during the visit, **and** > * The content fits a section of the template you used, **and** > * The content makes sense for that visit. > [accordion] When it will not appear > > * You did not say the trigger, or said something different. > * The verbal trigger is turned off. > * The content has nowhere to go. "Great to see you too" has no section. A lung exam line will not appear in a mental-health template with no physical exam section. | Content | Lands in | Works in | | - | - | - | | Lungs clear to auscultation bilaterally; heart regular rate and rhythm. | Physical Exam | a medical visit template | | Endorses inattention, distractibility, and procrastination; denies hyperactivity. | ROS: ADHD | a psychiatry template | | Great to see you too | nowhere | will not appear | # Troubleshooting Source: https://docs.healos.ai/guides/scribe/troubleshooting What you see, what is usually going on, and what to do. ## Recording and audio > [accordion] “No speech detected” or a nearly empty note > > The microphone did not capture the conversation: device too far away, muted input, or another app using the mic. > > Check the mic picker (arrow next to **Start recording**), keep the device within a few feet, and re-record. **Regenerate Note** does not help when there is no audio. > [accordion] Two recordings for one visit, note failed > > **Start recording** was clicked twice while the browser's capture dialog looked stuck. > > Check the sessions list before starting again. End the duplicate and use **Regenerate Note** on the good one. > [accordion] “Recording Too Short” > > Under one minute of audio. Resume and keep going, or accept a thinner note. > [accordion] “Connection lost” banner while you are clearly online > > The browser is reporting the network as offline. VPNs and corporate networks can trigger this. > > Reload. If it persists, switch to **Offline** recording mode and tell support. Signing out and back in does not help. ## Note content > [accordion] Note came out in English but the patient spoke another language > > **Transcript Language** is on English (US). Go to Account Settings → **Transcript Language** → the spoken language → **Save Changes**. Set it before the visit. > [accordion] Note says the opposite of what was dictated, or garbled terms > > Same cause: wrong **Transcript Language**, or heavy mixing of two languages. For English dictation with an accent, "English (India)" or "English (UK)" often transcribes better than "English (US)". > [accordion] “The note rewrites what I dictated” or reads too narrative > > The default style is polished narrative. Add word-for-word instructions to that template section. See [Templates](/guides/scribe/templates). > [accordion] Note suggests referring to your own specialty > > The Specialty setting is too broad. Choose **Other** and type the exact sub-specialty, and add a Plan-section rule. See [Templates](/guides/scribe/templates). > [accordion] ICD-10 or CPT codes missing, “Needs Review” on every note > > A platform-side coding issue. Tell support. **Regenerate Note** once we confirm it is fixed. > [accordion] AI Editor accepted an edit but the section did not change > > An occasional partial apply. Re-check the section, re-request the single change, or edit manually. Reload if the editor stops responding. ## Extension and EHR > [accordion] “Could not find a suitable frame with note sections” > > The EHR chart editor is not open, or the EHR changed its page and the extension needs an update. > > Open the encounter or SOAP editor first. Check the version at `chrome://extensions`. Contact support if it worked yesterday. > [accordion] Extension shows the sign-in screen > > You are not signed in on app.healos.ai in the same browser. Sign in on the website, then reopen the panel. > [accordion] Session on the phone but not on the web > > Old app version. Update the app. ## Account and access > [accordion] “Session Limit Reached” > > The monthly session cap on the free plan. Choose **Upgrade Plan**, or ask the practice admin. > [accordion] Team member sees “isn't enabled for your account” > > Product access has not been granted for that user. The practice admin grants access; otherwise contact support. > [accordion] Password reset email never arrives > > The account was created with Google, Apple, or phone, or the email went to spam. Use the same button you signed up with. Check spam for mail from auth.healos.ai. Apple "Hide My Email" users: contact support. > [accordion] “This account is already linked to a different identity” > > You are signing in with a different method than the one used at sign-up. Use the original method (Google, Apple, email, or phone). Contact support to merge. ## When to contact support Use the in-app chat or [team@healos.ai](mailto:team@healos.ai) when: * Notes are slow or failing for everyone in the practice at the same time. * Codes disappear, the AI Editor stops responding, or an "offline" banner will not clear. * Extension insertion stops working with no change on your side. * You want us to set up a custom template, word-for-word sections, or a sub-specialty rule for you. > [!NOTE] > > Include the patient initials, the date and time of the visit, and what you saw on screen. We can trace any session from that. # Introduction Source: https://docs.healos.ai/introduction What you can build with the HealOS External API, and how a request flows The HealOS External API lets your software do what your staff does in the HealOS dashboard: keep patients, documents and appointments in step with your system, generate and read clinical notes, check insurance eligibility, and follow prior authorizations. > [card] [5-minute quickstart](/quickstart) > > Make your first calls with a test key and fake data. ## What you can build > [card] [Patients and scheduling](/making-requests) > > Create, update and look up patients and appointments, keyed by your own `external_id`. > [card] [Documents](/webhooks#document-upload-flow) > > Upload PDFs, images and DOCX files to a patient. HealOS extracts their text. > [card] [Clinical notes (AI Scribe)](/clinical-notes) > > Generate notes from text, audio or documents, then read or bulk-export them. > [card] [Eligibility](/benefits) > > Run real-time insurance eligibility checks and read past results. > [card] [Prior authorization](/prior-auth) > > Follow the prior-auth requests HealOS prepares and the payer's decision. > [card] [Webhooks](/webhooks) > > Get notified when a note is ready or a document finishes processing. > [card] [HealOS CLI](/cli) > > Use the API from your terminal or scripts: `npm install -g @healos/cli` ## How requests flow **1. Your server sends a request** Every call goes to `https://api.healos.ai/ext-api/v1` with your key in the `X-API-Key` header. Call the API from your server, never from a browser or mobile app. See [Authentication](/authentication). **2. HealOS checks the key, its scopes and your rate limit** The key decides which organization you act in and what you may do. A missing scope returns `403`; too many requests return `429`. **3. HealOS answers, or queues the work** Reads and simple writes answer straight away with `{ "data": ... }`. Note generation answers `202` and finishes in the background; a [webhook](/webhooks) tells you when it's done. ## Find your way | You want to | Go to | | - | - | | Make a first call | [Quickstart](/quickstart) | | Follow a complete task step by step | [Recipes](/recipes/document-to-note) | | See every endpoint with its scope, cost and Safety box | [API Reference](/api-reference) | | Understand an error | [Error catalog](/errors) | | Test without touching real patients | [Test mode](/test-mode) | | Review key handling and PHI | [Security and HIPAA](/security) | | Point an AI agent at these docs | [Docs for AI agents](/ai-agents) | > [!NOTE] > > The **Using HealOS** tab covers the dashboard for clinicians and front-desk > staff. These API pages are for developers. # Making Requests Source: https://docs.healos.ai/making-requests The proper way to call the Healos External API, end to end Every call to the Healos External API follows the same pattern. Read this once, and the rest of the [API Reference](/api-reference) is just details. ## Request Anatomy ``` METHOD {base_url}/{resource}[/{id}] X-API-Key: hlsk_your_key_here Content-Type: application/json ← writes only { ...json body... } ← writes only ``` * **Base URL**: `https://api.healos.ai/ext-api/v1`. Always use `https`. * **`X-API-Key`** is required on every request. See [Authentication](/authentication). * **`Content-Type: application/json`** is required for `POST`, `PATCH`, and `PUT`. ## Your First Call — List Patients ```bash theme={null} curl https://api.healos.ai/ext-api/v1/patients \ -H "X-API-Key: hlsk_your_key_here" ``` Response: ```json theme={null} { "data": [ { "id": "1743552000000", "name": "Maria Santos", "created_at": "2026-03-15T09:30:00.000Z" } ], "meta": { "page": 1, "limit": 20, "total_pages": 1 } } ``` > [!NOTE] > > Patient `id` is a BigInt serialized as a string. Always treat it as an > opaque string — don't parse it as a number, and don't assume a length. ## Pagination List endpoints accept `page` and `limit` query parameters. Defaults are `page=1` and `limit=20`. Use `meta.total_pages` to know when you've reached the end. ```bash theme={null} curl "https://api.healos.ai/ext-api/v1/patients?page=2&limit=50" \ -H "X-API-Key: hlsk_your_key_here" ``` ## Creating a Resource Write endpoints take a JSON body. The schema for each body is in the [API Reference](/api-reference) — stick to the documented fields. Extra fields are rejected with a `400` validation error. ```bash theme={null} curl https://api.healos.ai/ext-api/v1/patients \ -H "X-API-Key: hlsk_your_key_here" \ -H "Content-Type: application/json" \ -d '{"name": "Maria Santos"}' ``` Response (`201 Created`): ```json theme={null} { "data": { "id": "1743552000000", "name": "Maria Santos", "created_at": "2026-03-15T09:30:00.000Z", "pronouns": null, "notes": null, "consent": false } } ``` > [!NOTE] > > `POST`, `PATCH`, and `DELETE` require a `*:write` scope for the resource. > A key without it gets a `403`. See [Authentication → Scopes](/authentication#scopes). ## Reading One Resource By ID ```bash theme={null} curl https://api.healos.ai/ext-api/v1/patients/1743552000000 \ -H "X-API-Key: hlsk_your_key_here" ``` You can grab a patient's ID from the Healos web app — it's shown as a copy-to-clipboard badge next to the patient name in the visit and record headers. > [!NOTE] > > A `404` on a specific ID may mean the resource does not exist **or** > belongs to another user. This is intentional — see [Error Handling](/errors). ## External IDs Patients, appointments, and documents accept an optional `external_id` on create — a caller-supplied identifier (up to 255 characters) that lets you correlate Healos records with rows in your own system without storing the Healos `id`. ```bash theme={null} curl https://api.healos.ai/ext-api/v1/patients \ -H "X-API-Key: hlsk_your_key_here" \ -H "Content-Type: application/json" \ -d '{"name": "Maria Santos", "external_id": "PARTNER-12345"}' ``` `external_id` is **unique per organization** and **immutable** once set: * Sending `external_id` on `PATCH` is silently ignored. * Sending a value another record in the same org already uses returns `409 Conflict` with the existing record so you can reconcile: ```json theme={null} { "error": "external_id already in use", "existing": { "id": "481926357104938271", "external_id": "PARTNER-12345" } } ``` For document uploads (`multipart/form-data`), pass `external_id` as a form field alongside `file` and `patient_id`. ### Lookup by external\_id List endpoints accept `external_id=` as a query parameter. The response is the standard list shape — a one-item `data` array on hit, or `404` on miss — so you can use the same client code as paginated listing. ```bash theme={null} curl "https://api.healos.ai/ext-api/v1/patients?external_id=PARTNER-12345" \ -H "X-API-Key: hlsk_your_key_here" ``` > [!NOTE] > > Documents are scoped to a patient, so the lookup path is > `/patients/{patientId}/documents?external_id=...`. ## Handling Responses | Status | What it means | Where to look | | - | - | - | | `2xx` | Success. Body is `{ "data": ... }`, list endpoints also include `meta`. | — | | `400` | Validation error. Body includes a `details` map of field errors. | [Error Handling](/errors) | | `401` | Missing, invalid, expired, or revoked key. | [Authentication](/authentication) | | `403` | Key is valid but lacks the required scope. | [Authentication → Scopes](/authentication#scopes) | | `404` | Resource not found (or not yours). | [Error Handling](/errors) | | `429` | Rate limit exceeded. Honor the `Retry-After` header. | [Rate Limiting](/rate-limiting) | Every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` so you can pace yourself without waiting for a `429`. ## Next Steps > [card] [API Reference](/api-reference) > > Full endpoint listing with request and response schemas > [card] [Authentication](/authentication) > > API keys, scopes, and security best practices # Prior Authorization Source: https://docs.healos.ai/prior-auth Track prior-auth requests HealOS prepares and the payer's decision HealOS prepares prior authorizations on two tracks: * **CoverMyMeds** (`covermymeds`): medication requests. HealOS reads the chart, drafts the answers to the plan's questions, a clinician reviews them, and HealOS fills the CoverMyMeds form. * **Availity** (`availity`): procedure requests that an EHR workflow (eCW or ModMed) files in Availity. The prior-auth endpoints let you follow those requests and the payer's decision from your own system. Starting requests through the API is not available yet. | Endpoint | Scope | What it does | | - | - | - | | `GET /prior-auth/requests` | `prior_auth:read` | List requests from both tracks, newest change first | | `GET /prior-auth/requests/{requestId}` | `prior_auth:read` | Get one request | | `GET /prior-auth/requests/{requestId}/events` | `prior_auth:read` | What happened to a request | | `GET /prior-auth/workflows` | `prior_auth:read` | Your EHR → portal workflows and their last run | | `POST /prior-auth/status-checks` | `prior_auth:write` | Read Availity decisions now | > [!WARNING] > > A request names a drug or procedure, a payer and a diagnosis for one patient, so > responses are protected health information. Only use these endpoints under your > business associate agreement with HealOS. Chart data, drafted answers and portal > screenshots are never returned. ## Status and decision Each request has two independent fields. `status` is where HealOS is in the work: | `status` | Meaning | | - | - | | `in_progress` | HealOS is preparing or filling the request | | `needs_review` | A clinician must review the drafted answers in HealOS | | `ready_for_person` | The portal form is filled and saved; a person sends it | | `submitted` | Sent to the plan | | `needs_attention` / `failed` | HealOS stopped; open the request in the dashboard | `decision` is the payer's latest decision as the portal shows it: `pending`, `approved`, `denied`, `cancelled` or `closed`. It is `null` until the request reaches the plan. `decision_checked_at` says when HealOS last read it. HealOS reads CoverMyMeds decisions every hour and Availity decisions every day. `raw_status` is HealOS's internal status. Use it when you contact support, not for logic. ## List requests ```bash theme={null} curl "https://api.healos.ai/ext-api/v1/prior-auth/requests?decision=approved&limit=50" \ -H "X-API-Key: $HEALOS_API_KEY" ``` ```json theme={null} { "data": [ { "id": "5b0e3c1a-2f4d-4c1e-9a43-0d7e1b2c3a4f", "track": "availity", "status": "submitted", "raw_status": "submitted", "decision": "approved", "decision_checked_at": "2026-10-22T14:00:00.000Z", "payer": "UHC", "drug_name": null, "diagnosis_code": null, "portal_ref": "REF123", "authorization_id": "AUTH9", "effective_date": "2026-10-22", "expiration_date": "2027-01-22", "ehr_patient_id": null, "workflow_id": "0d6c…", "created_at": "2026-10-19T09:00:00.000Z", "updated_at": "2026-10-22T14:00:00.000Z" } ], "meta": { "page": 1, "limit": 50, "total_pages": 1 } } ``` Filters: `track`, `status`, `decision` and `updated_since` (ISO 8601). The list covers the 500 most recently changed requests per track. To stay in sync, store the time of your last sync and pass it as `updated_since`. ## Events `GET /prior-auth/requests/{requestId}/events` returns up to 100 events, newest first. Each has a `type`, a time `at`, and a `decision` on decision events. CoverMyMeds requests return HealOS's event log, for example `created`, `portal_draft_saved` and `portal_outcome_checked`. Availity requests return `started`, `finished` and `decision_changed`. ## Check decisions now ```bash theme={null} curl -X POST "https://api.healos.ai/ext-api/v1/prior-auth/status-checks" \ -H "X-API-Key: $HEALOS_API_KEY" ``` This returns `202` and reads the decisions of your open Availity requests in the background, the same as **Check status now** in the dashboard. It takes a few minutes. Read the results from the requests list afterwards. * `404`: your organization has no Availity workflow. * `409`: decisions were checked in the last 10 minutes, or a workflow is filling a form right now. Try again later. CoverMyMeds decisions are not part of this call. HealOS checks them every hour. # Quickstart Source: https://docs.healos.ai/quickstart Check your key, create a fake patient, generate a note and clean up, in about five minutes This quickstart makes six calls with **made-up data**: it checks your key, creates a fake patient, writes a short note for them, reads it back and then deletes the patient. Run it in a [test organization](/test-mode), not in the organization that holds your real patients. > [!WARNING] > > Step 4 generates a real note and uses **one Scribe session** from the > organization's plan. Every other step is free. ## Before you start 1. An org admin opens **Account Settings → API Keys** at [app.healos.ai/account-settings](https://app.healos.ai/account-settings) in the test organization and creates a key with these scopes: `patients:read`, `patients:write`, `notes:read`, `notes:write`. 2. Copy the key (it starts with `hlsk_` and is shown only once) and keep it in an environment variable, not in your code: ```bash theme={null} export HEALOS_API_KEY="hlsk_..." export HEALOS="https://api.healos.ai/ext-api/v1" ``` ## Steps **1. Check which organization the key acts in** ```bash theme={null} curl "$HEALOS/me" -H "X-API-Key: $HEALOS_API_KEY" ``` **Expect** `200` with `data.org.name` set to your **test** organization and the four scopes above. If it names your live organization, stop and create a key in the test organization instead. **2. Create a fake patient** ```bash theme={null} curl -X POST "$HEALOS/patients" \ -H "X-API-Key: $HEALOS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "first_name": "Testy", "last_name": "Quickstart", "date_of_birth": "1970-01-01", "phone": "+12025550123", "external_id": "quickstart-001" }' ``` **Expect** `201` with the new patient in `data`. Copy `data.id` (a numeric string) into `PATIENT_ID`: ```bash theme={null} export PATIENT_ID="" ``` Running this again returns `409` with `existing.id`, because `external_id` must be unique in the organization. Use that id. **3. Find the patient by your own id** ```bash theme={null} curl "$HEALOS/patients?external_id=quickstart-001" -H "X-API-Key: $HEALOS_API_KEY" ``` **Expect** `200` with a one-item `data` array. This is how you look up records without storing HealOS ids. **4. Generate a note from text** ```bash theme={null} curl -X POST "$HEALOS/notes/from-text" \ -H "X-API-Key: $HEALOS_API_KEY" \ -H "Content-Type: application/json" \ -d "{ \"patient_id\": \"$PATIENT_ID\", \"text\": \"Test visit with made-up details. Knee pain for two weeks, worse on stairs. No swelling. Plan: physiotherapy, follow up in 4 weeks.\" }" ``` **Expect** `202` with `data.session_id` and `data.status: "queued"`. Copy the session id: ```bash theme={null} export SESSION_ID="" ``` **5. Read the note** ```bash theme={null} curl "$HEALOS/sessions/$SESSION_ID/notes" -H "X-API-Key: $HEALOS_API_KEY" ``` **Expect** `200`. `data.notes` is empty while the note is being written and holds the note within about a minute. Repeat the call every 10 seconds until it appears. In production, use a `NOTE_CREATED` [webhook](/webhooks) instead of polling. **6. Clean up** ```bash theme={null} curl -X DELETE "$HEALOS/patients/$PATIENT_ID" -H "X-API-Key: $HEALOS_API_KEY" ``` **Expect** `200` with `{ "success": true }`. This permanently deletes the fake patient with its session and note. ## Expected outcomes | Step | Expected result | If you see something else | | - | - | - | | 1. `GET /me` | `200`, your test organization | `401`: the key is wrong, expired or revoked | | 2. Create patient | `201` | `409`: already created; use `existing.id`. `403`: the key lacks `patients:write` | | 3. Look up by `external_id` | `200`, one patient | `404`: the `external_id` doesn't match | | 4. Generate note | `202`, `status: "queued"` | `402`: no Scribe sessions left. `409`: a request for this patient is being submitted right now. Don't resend after a `202`; each call creates a new note | | 5. Read note | `200`, one note after about a minute | Empty `notes` for over 5 minutes: contact support with the `session_id` | | 6. Delete patient | `200`, `success: true` | `404`: already deleted | ## The same flow as a script The same six calls in JavaScript and Python. Both read the key from the `HEALOS_API_KEY` environment variable and use only made-up data. * **JavaScript:** save as `quickstart.mjs` and run it with Node.js 18 or later: `HEALOS_API_KEY=hlsk_... node quickstart.mjs`. * **Python:** install [requests](https://pypi.org/project/requests/) (`pip install requests`), save as `quickstart.py` and run it with Python 3.8 or later: `HEALOS_API_KEY=hlsk_... python quickstart.py`. ```javascript quickstart.mjs theme={null} const BASE = "https://api.healos.ai/ext-api/v1"; const headers = { "X-API-Key": process.env.HEALOS_API_KEY, "Content-Type": "application/json", }; async function call(method, path, body) { const res = await fetch(BASE + path, { method, headers, body: body ? JSON.stringify(body) : undefined, }); const json = await res.json(); if (!res.ok && res.status !== 409) { throw new Error(`${method} ${path} -> ${res.status}: ${json.error}`); } return { status: res.status, json }; } const me = await call("GET", "/me"); console.log("Organization:", me.json.data.org.name); const created = await call("POST", "/patients", { first_name: "Testy", last_name: "Quickstart", date_of_birth: "1970-01-01", external_id: "quickstart-001", }); const patientId = created.status === 409 ? created.json.existing.id : created.json.data.id; const queued = await call("POST", "/notes/from-text", { patient_id: patientId, text: "Test visit with made-up details. Knee pain for two weeks. Plan: physiotherapy.", }); const sessionId = queued.json.data.session_id; let notes = []; for (let i = 0; i < 30 && notes.length === 0; i++) { await new Promise((r) => setTimeout(r, 10_000)); notes = (await call("GET", `/sessions/${sessionId}/notes`)).json.data.notes; } console.log(notes.length ? notes[0].content : "Note not ready yet"); await call("DELETE", `/patients/${patientId}`); console.log("Deleted the test patient."); ``` ```python quickstart.py theme={null} import os import time import requests BASE = "https://api.healos.ai/ext-api/v1" http = requests.Session() http.headers["X-API-Key"] = os.environ["HEALOS_API_KEY"] def call(method, path, body=None): res = http.request(method, BASE + path, json=body, timeout=30) data = res.json() if not res.ok and res.status_code != 409: raise RuntimeError(f"{method} {path} -> {res.status_code}: {data.get('error')}") return res.status_code, data _, me = call("GET", "/me") print("Organization:", me["data"]["org"]["name"]) status, created = call("POST", "/patients", { "first_name": "Testy", "last_name": "Quickstart", "date_of_birth": "1970-01-01", "external_id": "quickstart-001", }) patient_id = created["existing"]["id"] if status == 409 else created["data"]["id"] _, queued = call("POST", "/notes/from-text", { "patient_id": patient_id, "text": "Test visit with made-up details. Knee pain for two weeks. Plan: physiotherapy.", }) session_id = queued["data"]["session_id"] notes = [] for _ in range(30): time.sleep(10) _, body = call("GET", f"/sessions/{session_id}/notes") notes = body["data"]["notes"] if notes: break print(notes[0]["content"] if notes else "Note not ready yet") call("DELETE", f"/patients/{patient_id}") print("Deleted the test patient.") ``` > [!NOTE] > > Both scripts send the note request once and never retry it: each call to > `POST /notes/from-text` creates a new note and uses a Scribe session. See > [Going to production](/going-to-production) for safe retries. ## Next steps > [card] [Recipes](/recipes/document-to-note) > > Complete tasks, step by step. > [card] [Making requests](/making-requests) > > Pagination, `external_id` and responses. > [card] [Error catalog](/errors) > > Every status and what to do. # Rate Limiting Source: https://docs.healos.ai/rate-limiting API request limits and rate limiting behavior The API limits how fast each API key can send requests, to keep the service stable. The limits below are approximate: they are counted per API server, so the exact point at which you get a `429` can vary slightly. Treat them as a pace to stay under, not as a guaranteed quota or a cap on billable requests. ## Limits | Parameter | Value | | - | - | | Requests per window | About **60** | | Window duration | **1 minute** | ### Endpoint limits Some endpoints call outside services that we pay for per request, so they have an extra per-key limit on top of the roughly 60 requests a minute above. A request counts against both. | Endpoint | Limit | Why | | - | - | - | | `POST /benefits/eligibility-checks` | About **10** per minute per API key | Each check is a paid payer request | | `POST /prior-auth/status-checks` | Once every **10 minutes** per organization (`409` before then) | Each run signs in to Availity | Every other endpoint has only the shared limit of about 60 per minute. Each endpoint page in the [API Reference](/api-reference) states its limit. ### Request size | Request | Largest body | | - | - | | JSON bodies | 1 MB | | Document upload (`POST /patients/{patientId}/documents`) | 10 MB | | Audio upload (`POST /notes/from-audio`) | 100 MB | Larger bodies return `413`. Going over the eligibility check limit also returns **HTTP 429**: ```json theme={null} { "error": "Too many requests. Please try again later." } ``` ### Concurrent uploads Uploads are held in memory while they are received, so the two upload endpoints (`POST /patients/{patientId}/documents` and `POST /notes/from-audio`) also limit how many uploads can be in progress at the same time. An upload counts from when the request arrives until the response is sent, and it counts against the requests-per-minute limit as well. | Limit | Value | | - | - | | Uploads in progress per API key | **2** at a time, across both upload endpoints | | Uploads in progress per organization | **4** at a time across all of its API keys (fewer for large audio files sent without a `Content-Length`) | | Uploads in progress per API server | A fixed number shared by all customers, sized to the server's memory | Like the rate limit, these are counted per API server, so the exact point at which you get a `429` can vary. A third upload sent while two are still in progress for the key, an upload over the organization's limit, or an upload sent while the server is at its own limit, is refused before its body is read and returns **HTTP 429** with a `Retry-After` header (in seconds): ```json theme={null} { "error": "Too many uploads in progress for this API key (limit 2 at a time). Retry after one finishes." } ``` ```json theme={null} { "error": "Too many uploads in progress for this organization. Retry after one finishes." } ``` ```json theme={null} { "error": "The server is busy with other uploads. Please retry shortly." } ``` To upload many files, send at most two at a time per key and start the next one when one finishes. ## Response Headers Every response includes rate limit headers: | Header | Description | | - | - | | `X-RateLimit-Limit` | Maximum requests allowed per window | | `X-RateLimit-Remaining` | Requests remaining in the current window | | `X-RateLimit-Reset` | Unix timestamp when the window resets | ## Exceeding the Limit When you exceed the rate limit, the API returns **HTTP 429** with a `Retry-After` header: ```json theme={null} { "error": "Rate limit exceeded. Please retry after the window resets." } ``` ## Best Practices * **Cache responses** when possible to reduce request volume. * **Use pagination** with reasonable page sizes (default: 20). * **Implement exponential backoff** when receiving 429 responses. * **Upload at most two files at a time** per API key. * **Monitor rate limit headers** to stay within bounds proactively. # Appointments for a date range Source: https://docs.healos.ai/recipes/appointments-date-range List every appointment between two dates, one day at a time Use this to pull a week's schedule into your system, or to reconcile HealOS appointments with yours. | | | | - | - | | **Scope** | `appointments:read` | | **Cost** | Free | | **Outside systems** | None. Reads appointments stored in HealOS. | | **Safety** | Read-only and safe to retry. | > [!WARNING] > > Filter with `date=YYYY-MM-DD`, one day per request. `GET /appointments` > accepts `start_date` and `end_date`, but does not apply them today: a > request with only those parameters returns every appointment. ## How the filter works * `date` matches appointments whose `start_at` falls on that calendar day in **UTC**. An appointment at 6 PM Pacific on 14 April is 01:00 UTC on 15 April, so it appears under `date=2026-04-15`. * Results are paginated (`page`, `limit` up to 100), newest `start_at` first. * Appointments are those in HealOS: created through the API or the dashboard. Appointments that exist only in your EHR are not listed. ## Steps **1. Ask for one day** ```bash theme={null} curl "https://api.healos.ai/ext-api/v1/appointments?date=2026-04-15&limit=100" \ -H "X-API-Key: $HEALOS_API_KEY" ``` **Expect** `200` with `data` (the appointments) and `meta` (`page`, `limit`, `total_pages`). **2. Read every page** While `meta.page` is less than `meta.total_pages`, ask again with `page=2`, `page=3` and so on. **3. Repeat for each day in the range** Move the `date` forward one day at a time until the end of the range. To cover a whole local day, also fetch the UTC day after it and keep only the appointments whose `start_at` falls inside your local day. ## Script Node.js 18 or later: `HEALOS_API_KEY=hlsk_... node appointments.mjs 2026-04-13 2026-04-19`. ```javascript appointments.mjs theme={null} const BASE = "https://api.healos.ai/ext-api/v1"; const [from, to] = process.argv.slice(2); // YYYY-MM-DD, inclusive, UTC days async function getPage(date, page) { const url = `${BASE}/appointments?date=${date}&limit=100&page=${page}`; const res = await fetch(url, { headers: { "X-API-Key": process.env.HEALOS_API_KEY } }); if (res.status === 429) { const wait = Number(res.headers.get("Retry-After") ?? 60); await new Promise((r) => setTimeout(r, wait * 1000)); return getPage(date, page); } if (!res.ok) throw new Error(`${res.status}: ${(await res.json()).error}`); return res.json(); } const all = []; for (let d = new Date(`${from}T00:00:00Z`); d <= new Date(`${to}T00:00:00Z`); d.setUTCDate(d.getUTCDate() + 1)) { const date = d.toISOString().slice(0, 10); for (let page = 1; ; page++) { const { data, meta } = await getPage(date, page); all.push(...data); if (page >= meta.total_pages) break; } } console.log(`${all.length} appointments`); for (const a of all) console.log(a.start_at, a.status, a.patient_name, a.appointment_type); ``` ## Expected outcomes | Case | Expected result | | - | - | | A day with appointments | `200`, `data` holds them, newest first | | A day with none | `200`, `data: []`, `meta.total_pages: 1` | | More than about 60 requests in a minute | `429` with `Retry-After`; the script waits and retries | | Key without `appointments:read` | `403` `Insufficient scope. Required: appointments:read` | Each appointment carries `id`, `patient_id`, `patient_name`, `provider_id`, `provider_name`, `appointment_type`, `visit_type`, `start_at`, `duration_minutes`, `status` (`SCHEDULED`, `COMPLETED`, `CANCELLED` or `NO_SHOW`), `notes`, `repeat_rule` and your `external_id`. See [List appointments](/api-reference/appointments/list-appointments) for the full schema. # Patient, document, note Source: https://docs.healos.ai/recipes/document-to-note Create a patient, upload a document and generate a clinical note from it Use this when you have a patient's paperwork (an intake form, referral letter or prior records) and want HealOS to write a note from it, with no recording. | | | | - | - | | **Scopes** | `patients:write`, `documents:read`, `documents:write`, `notes:read`, `notes:write` | | **Cost** | Step 4 runs AI note generation. Steps 1 to 3 and 5 are free. | | **Outside systems** | None. Nothing is sent to an EHR or payer. | | **Time** | Extraction 10 to 30 seconds per PDF; the note in about a minute. | > [!TIP] > > Try it in a [test organization](/test-mode) first, with a document that > holds only made-up details. ```bash theme={null} export HEALOS_API_KEY="hlsk_..." export HEALOS="https://api.healos.ai/ext-api/v1" ``` **1. Create the patient** ```bash theme={null} curl -X POST "$HEALOS/patients" \ -H "X-API-Key: $HEALOS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "first_name": "Testy", "last_name": "Recipe", "date_of_birth": "1970-01-01", "external_id": "test-pt-001" }' ``` **Expect** `201`. Save `data.id` as `PATIENT_ID`. If the patient already exists, you get `409` with `existing.id`; use that. **2. Upload the document** Send the file as `multipart/form-data`. PDF, JPEG, PNG and DOCX up to 10 MB are accepted, and the content must match the file extension. ```bash theme={null} curl -X POST "$HEALOS/patients/$PATIENT_ID/documents" \ -H "X-API-Key: $HEALOS_API_KEY" \ -F "file=@test-intake-form.pdf" \ -F "external_id=test-doc-001" ``` **Expect** `201`, `data.status: "pending"` and a `message` that ends in "text extraction started". If `message` doesn't mention extraction, start it yourself with [`POST .../documents/{documentId}/extract`](/api-reference/documents/extract-or-retry-document-text-extraction). **3. Wait for text extraction** Register a `DOCUMENT_STATUS_CHANGED` [webhook](/webhooks), or poll every few seconds: ```bash theme={null} curl "$HEALOS/patients/$PATIENT_ID/documents?external_id=test-doc-001" \ -H "X-API-Key: $HEALOS_API_KEY" ``` **Expect** `data[0].status` to move from `pending` to `processing` to `completed`, with `has_extracted_text: true`. On `failed`, read `extraction_error`. **4. Generate the note** ```bash theme={null} curl -X POST "$HEALOS/patients/$PATIENT_ID/notes/from-documents" \ -H "X-API-Key: $HEALOS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "balanced" }' ``` **Expect** `202` with `data.session_id`. Save it as `SESSION_ID`. > [!WARNING] > > Each call creates a new session and note. Don't retry after a `202`; > check the session in the next step. **5. Read the note** Wait for a `NOTE_CREATED` [webhook](/webhooks), or poll every 10 seconds: ```bash theme={null} curl "$HEALOS/sessions/$SESSION_ID/notes" -H "X-API-Key: $HEALOS_API_KEY" ``` **Expect** `200`. `data.notes` is empty until the note is written, then holds it with its `content` and codes. ## The same flow in Python The steps above as one script, using [requests](https://pypi.org/project/requests/) (`pip install requests`). It reads the key from `HEALOS_API_KEY` and expects a test file holding only made-up details next to it. ```python document_to_note.py theme={null} import os import time import requests BASE = "https://api.healos.ai/ext-api/v1" http = requests.Session() http.headers["X-API-Key"] = os.environ["HEALOS_API_KEY"] def check(res, allowed=()): if not res.ok and res.status_code not in allowed: raise RuntimeError(f"{res.request.method} {res.url} -> {res.status_code}: {res.json().get('error')}") return res.json() # 1. Create the patient (a 409 means it already exists: reuse it). res = http.post(f"{BASE}/patients", json={ "first_name": "Testy", "last_name": "Recipe", "date_of_birth": "1970-01-01", "external_id": "test-pt-001", }, timeout=30) body = check(res, allowed=(409,)) patient_id = body["existing"]["id"] if res.status_code == 409 else body["data"]["id"] # 2. Upload the document (a 409 means this external_id was already uploaded). with open("test-intake-form.pdf", "rb") as f: res = http.post( f"{BASE}/patients/{patient_id}/documents", files={"file": ("test-intake-form.pdf", f, "application/pdf")}, data={"external_id": "test-doc-001"}, timeout=60, ) check(res, allowed=(409,)) if res.status_code == 201 and "text extraction started" not in res.json().get("message", ""): document_id = res.json()["data"]["id"] check(http.post(f"{BASE}/patients/{patient_id}/documents/{document_id}/extract", timeout=60)) # 3. Wait for text extraction. for _ in range(60): docs = check(http.get( f"{BASE}/patients/{patient_id}/documents", params={"external_id": "test-doc-001"}, timeout=30, ))["data"] if docs[0]["status"] == "failed": raise RuntimeError(f"Extraction failed: {docs[0].get('extraction_error')}") if docs[0]["status"] == "completed": break time.sleep(5) else: raise RuntimeError("Extraction is still running; check the document later") # 4. Generate the note. Sent once: each call creates a new session and note. queued = check(http.post( f"{BASE}/patients/{patient_id}/notes/from-documents", json={"model": "balanced"}, timeout=60, )) session_id = queued["data"]["session_id"] # 5. Read the note. notes = [] for _ in range(30): time.sleep(10) notes = check(http.get(f"{BASE}/sessions/{session_id}/notes", timeout=30))["data"]["notes"] if notes: break print(notes[0]["content"] if notes else f"Note not ready yet; check session {session_id} later") ``` In production, replace the two polling loops with the `DOCUMENT_STATUS_CHANGED` and `NOTE_CREATED` [webhooks](/webhooks). ## Expected outcomes | Case | Expected result | What to do | | - | - | - | | Normal PDF with text | Document `completed`, then `202`, then one note | Nothing | | Scanned PDF or photo | Usually `completed` (text is read from the image) | If `failed`, upload a clearer copy | | File content doesn't match its extension | Upload `400` | Send the right extension | | File over 10 MB | Upload `413` | Split or compress it | | Same `external_id` uploaded twice | Upload `409` with `existing` | Use the existing document | | Note requested before any document is `completed` | `422`, no session created | Wait for extraction, then retry | | `template_id` not in your organization | `404` | Pick an id from [`GET /templates`](/templates) | | Key without `notes:write` | `403` `Insufficient scope. Required: notes:write` | Add the scope to the key | ## Related * [Clinical notes guide](/clinical-notes#generate-a-note-from-documents) * [Webhooks: document upload flow](/webhooks#document-upload-flow) * [Generate a note from documents](/api-reference/notes/generate-a-note-from-the-patients-documents) (reference) # Run an eligibility check Source: https://docs.healos.ai/recipes/eligibility-check Find the payer, check a patient's coverage and read the result Use this before a visit to confirm a patient's insurance is active and to see copays, deductibles and whether prior authorization is needed. | | | | - | - | | **Scopes** | `benefits:read`, `benefits:write` | | **Cost** | **Billable.** Step 2 is a paid request to the payer. Steps 1 and 3 are free. | | **Rate limit** | Step 2: about 10 per minute per key, on top of the shared limit of about 60 per minute | | **Outside systems** | **Yes.** Step 2 sends the member's details to the payer through our clearinghouse. | | **Time** | Usually a few seconds; allow up to a minute. | > [!WARNING] > > There is no test payer. A made-up member can't be checked and the request > can still be billed (see [Test mode](/test-mode#eligibility-checks)). Build > against the example response below, then run real checks under your > business associate agreement. ```bash theme={null} export HEALOS_API_KEY="hlsk_..." export HEALOS="https://api.healos.ai/ext-api/v1" ``` **1. Find the payer id** ```bash theme={null} curl "$HEALOS/benefits/payers/search?q=aetna" -H "X-API-Key: $HEALOS_API_KEY" ``` **Expect** `200` with a list such as `[{ "id": "60054", "name": "Aetna" }]`. Queries shorter than 2 characters return an empty list. Save the right `id` as the `payer_id`. **2. Run the check** For a patient already in HealOS, send `patient_id`. HealOS uses their name, date of birth, gender and the member id on their active insurance for this payer: ```bash theme={null} curl -X POST "$HEALOS/benefits/eligibility-checks" \ -H "X-API-Key: $HEALOS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "payer_id": "60054", "provider_name": "Riverside Family Medicine", "provider_npi": "1234567893", "patient_id": "481926357104938271" }' ``` Otherwise send `member_id`, `first_name`, `last_name` and `date_of_birth` (`YYYY-MM-DD`) instead of `patient_id`. `provider_npi` is the 10-digit NPI of the requesting provider or practice. **Expect** `200` with the saved check. Save `data.id` as `CHECK_ID`. > [!WARNING] > > Don't retry a request that returned `200` or a `4xx`: each request is a > new, billable check. Retry only after `502`, `503` or `504`, and wait > first. **3. Read the result** The `200` response already holds the result. Read it again at any time, free of charge: ```bash theme={null} curl "$HEALOS/benefits/eligibility-checks/$CHECK_ID" -H "X-API-Key: $HEALOS_API_KEY" ``` Look at these fields: | Field | What it tells you | | - | - | | `data.status` | The coverage status the payer reported, for example `Active` | | `data.result.plan` | Plan names, group number and coverage dates | | `data.result.benefits` | One entry per benefit: co-payment, co-insurance, deductible, out-of-pocket, network, amount and whether prior auth is required | | `data.result.issues`, `data.result.warnings` | Problems the payer reported, such as member not found | See [what `result` contains](/benefits#what-result-contains) for the full shape. ## The same flow in Python The steps above as one script, using [requests](https://pypi.org/project/requests/) (`pip install requests`). It reads the key and the HealOS patient id from environment variables, so nothing about a real patient lives in the code. > [!WARNING] > > Step 2 is a **billable** payer request every time it runs. The script sends > it once and retries only a `502`, `503` or `504`, once, after a wait. After a > timeout it stops and asks you to check the history instead of sending the > check again. ```python eligibility_check.py theme={null} import os import time import requests BASE = "https://api.healos.ai/ext-api/v1" http = requests.Session() http.headers["X-API-Key"] = os.environ["HEALOS_API_KEY"] patient_id = os.environ["HEALOS_PATIENT_ID"] # a patient already in HealOS # 1. Find the payer id (free). payers = http.get(f"{BASE}/benefits/payers/search", params={"q": "aetna"}, timeout=30).json()["data"] payer_id = payers[0]["id"] # pick the right one from the list in real code # 2. Run the check (billable). request = { "payer_id": payer_id, "provider_name": "Riverside Family Medicine", "provider_npi": "1234567893", "patient_id": patient_id, } try: res = http.post(f"{BASE}/benefits/eligibility-checks", json=request, timeout=90) if res.status_code in (502, 503, 504): time.sleep(30) res = http.post(f"{BASE}/benefits/eligibility-checks", json=request, timeout=90) except requests.Timeout: raise SystemExit( "No response. List this patient's recent checks before running another: " f"GET /benefits/eligibility-checks?patient_id={patient_id}" ) body = res.json() if not res.ok: raise SystemExit(f"{res.status_code} {body.get('code')}: {body.get('error')}") check_id = body["data"]["id"] # 3. Read the result (free; the response above already holds it). check = http.get(f"{BASE}/benefits/eligibility-checks/{check_id}", timeout=30).json()["data"] print("Coverage status:", check["status"]) for issue in (check.get("result") or {}).get("issues", []): print("Payer issue:", issue) ``` ## Expected outcomes | Case | Expected result | What to do | | - | - | - | | Member found, coverage active | `200`, `status` `Active`, benefits listed | Use the benefits | | Member found, coverage ended | `200`, a non-active `status` | Ask the patient for current insurance | | Payer can't match the member | `200` with `result.issues`, or `422` `PAYER_VALIDATION_ERROR` | Check member id, name and date of birth against the card | | Missing or malformed field | `400` `VALIDATION_ERROR` | Fix the request; no payer request was made | | `patient_id` not in your organization | `404` `PATIENT_NOT_FOUND` | No payer request was made | | More than 10 checks in a minute | `429` | Wait for the next minute | | Payer or clearinghouse slow or down | `502` or `504` | Wait, then retry once | | Eligibility checking unavailable | `503` `SERVICE_UNAVAILABLE` | Retry later | ## Read past checks Checks run in the HealOS dashboard and through the API share one history: ```bash theme={null} curl "$HEALOS/benefits/eligibility-checks?patient_id=481926357104938271" \ -H "X-API-Key: $HEALOS_API_KEY" ``` Reuse a recent check instead of running a new one when you can. ## Related * [Benefit verification guide](/benefits) * [Run an eligibility check](/api-reference/benefits/run-an-eligibility-check) (reference) # Receptionist call transcripts Source: https://docs.healos.ai/recipes/receptionist-call-transcripts Pull every AI Receptionist call, with its transcript and extracted details, into your own system Use this to build your own alerts, task rules or summaries from what the AI receptionist heard, or to keep a copy of every call next to the patient's record in your system. | | | | - | - | | **Scope** | `receptionist:read` | | **Cost** | Free | | **Outside systems** | None for the list and the call. The recording is read from HealOS storage or the voice provider. | | **Safety** | Read-only and safe to retry. Downloads are written to your recording access log. | ## What you get Three read-only endpoints: | Endpoint | Returns | | - | - | | [`GET /receptionist/calls`](/api-reference/receptionist/list-receptionist-calls) | Calls newest first: status, outcome, caller, duration, summary, whether a recording and transcript exist | | [`GET /receptionist/calls/{callId}`](/api-reference/receptionist/get-a-receptionist-call) | The call plus the full transcript and the extracted details | | [`GET /receptionist/calls/{callId}/recording`](/api-reference/receptionist/download-a-call-recording) | The audio | The dashboard's summary is two to three sentences and a follow-up task is only created when the AI judges the call needs one. The transcript and `extracted_data` are the raw material behind both, so your own rules can be as detailed as you like. ## Poll for new calls Page through calls received since your last run. `from_date` and `to_date` filter on `created_at`, the time HealOS received the call record, so keep the latest `created_at` you have seen and ask for everything after it. ```bash theme={null} curl -sS "https://api.healos.ai/ext-api/v1/receptionist/calls?from_date=2026-10-27T00:00:00Z&limit=100" \ -H "X-API-Key: $HEALOS_API_KEY" ``` ```json theme={null} { "data": [ { "id": "c0a80101-0000-4000-8000-000000000001", "direction": "inbound", "status": "completed", "outcome": "message_taken", "outcome_reason": null, "transfer_status": null, "caller_name": "Pat Example", "from_number": "+15555550100", "to_number": "+15555550199", "patient_id": "700000000000000001", "started_at": "2026-10-27T14:03:11.000Z", "ended_at": "2026-10-27T14:07:42.000Z", "duration_sec": 271, "summary": "Caller asked to reschedule a follow-up; no Tuesday slot was open, so a callback was requested.", "has_recording": true, "has_transcript": true, "review_status": "unreviewed", "created_at": "2026-10-27T14:07:50.000Z", "updated_at": "2026-10-27T14:08:02.000Z" } ], "meta": { "page": 1, "limit": 100, "total": 1, "total_pages": 1 } } ``` A call's `summary`, `outcome` and `extracted_data` are filled in by the post-call analysis, which runs within a minute of the call ending; until then they are `null`. Fetch such a call again later, or use the webhook below as the trigger. ## Or react to the post-call webhook In the dashboard, under **AI Receptionist → Settings → Automations**, turn on the post-call webhook and give it your URL. Within seconds of each call ending HealOS sends the call's `call_id`, outcome, summary and caller number. The webhook does not carry the transcript: use `call_id` to fetch it. ```bash theme={null} curl -sS "https://api.healos.ai/ext-api/v1/receptionist/calls/$CALL_ID" \ -H "X-API-Key: $HEALOS_API_KEY" ``` ```json theme={null} { "data": { "id": "c0a80101-0000-4000-8000-000000000001", "summary": "Caller asked to reschedule a follow-up; no Tuesday slot was open, so a callback was requested.", "transcript": [ { "speaker": "assistant", "message": "Thank you for calling. How can I help?" }, { "speaker": "user", "message": "I need to move my follow-up with Dr. Example." } ], "extracted_data": { "reason_for_call": "reschedule follow-up", "callback_requested": true, "appointment_requested": false } } } ``` (Other fields omitted. `speaker` is `user` for the caller and `assistant` for the AI receptionist.) ## Download the recording ```bash theme={null} curl -sS "https://api.healos.ai/ext-api/v1/receptionist/calls/$CALL_ID/recording" \ -H "X-API-Key: $HEALOS_API_KEY" \ -o "call-$CALL_ID.mp3" ``` The body is the audio, usually `audio/mpeg`. Each download is written to your organization's recording access log, the same as a download from the dashboard. ## From the CLI ```bash theme={null} healos receptionist calls list --from 2026-10-27 --outcome message_taken,could_not_book healos receptionist calls transcript c0a80101-0000-4000-8000-000000000001 healos receptionist calls recording c0a80101-0000-4000-8000-000000000001 --out call.mp3 ``` ## Keep in mind * Transcripts, summaries and recordings are protected health information. Store and transmit them as you would any patient record. * `patient_id` is set when the receptionist matched the caller to a chart; use it with [`GET /patients/{patientId}`](/api-reference/patients/get-patient-by-id). * `outcome` values: `booked`, `rescheduled`, `cancelled`, `confirmed`, `could_not_book`, `transferred`, `question_answered`, `message_taken`, `hung_up`, `other`. Filter the list with `outcome=message_taken,could_not_book` to find calls that need a human. # Security and HIPAA Source: https://docs.healos.ai/security Handle API keys, scopes and protected health information safely The External API reads and writes **protected health information (PHI)**: patient demographics, documents, clinical notes, eligibility results and prior-auth requests. Treat every key and every response accordingly. > [!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. ## API keys * **Who can create keys.** Only organization admins, in **Account Settings → API Keys** at [app.healos.ai/account-settings](https://app.healos.ai/account-settings). * **One organization per key.** A key reads and writes only the organization it was created in, across every provider in it. * **Shown once.** HealOS stores only a hash of the key. If you lose it, create a new one. * **Tied to its creator.** A key works only while the admin who created it is still an admin of the organization. Removing or demoting that admin turns their keys off (`401`). Create production keys from an admin account that will stay in place. * **Recognizable.** Keys start with `hlsk_`, so secret scanners and code review can spot a leaked one. ### Store keys safely * Keep keys in a secrets manager or environment variables on your server. Never put them in source code, browser or mobile apps, logs, tickets or chat. * Always call `https://api.healos.ai`. A request to `http://` sends the key unencrypted before it is redirected. * Use one key per integration or environment, with a clear label, so you can revoke one without breaking the others. ### Give each key the narrowest scopes Choose only the [scopes](/authentication#scopes) the integration needs. A reporting job that reads notes needs `notes:read` and nothing else. Avoid `*` (full access) outside short-lived testing. ### Set an expiry When you create a key, choose an expiry (7 days, 30 days, 90 days, 1 year, a custom date, or never). Prefer an expiry for any key that leaves your own servers, for example on a contractor's machine. An expired key returns `401`. ### Rotate a key **1. Create the new key** Create a key with the same scopes and a new label, for example "EHR sync (2026-11)". **2. Deploy it** Put the new key in your secrets store and roll it out. Call [`GET /me`](/api-reference/account/describe-the-calling-api-key) with it to confirm the organization and scopes. **3. Revoke the old key** Check the **Last used** column on the API Keys page has stopped moving for the old key, then revoke it. Revocation takes effect immediately. ### If a key leaks Revoke it at once in **Account Settings → API Keys**, create a replacement, and tell us at [support@healos.ai](mailto:support@healos.ai). Don't wait to confirm misuse first. ## Handling PHI from the API * **Store responses as PHI.** Notes, transcripts, documents, eligibility results and prior-auth requests all identify a patient. * **Log ids, not content.** Log HealOS ids and your `external_id` values, never names, dates of birth, note text or eligibility results. * **Webhooks carry ids, not content.** [Webhook](/webhooks) payloads hold identifiers and a URL to fetch; the content stays behind the authenticated API. Protect your webhook endpoint with a secret header and HTTPS. * **Test with fake data.** Build in a [test organization](/test-mode) with made-up patients. * **Delete what you no longer need.** [Deleting a patient](/api-reference/patients/delete-a-patient) through the API permanently removes them with their sessions and notes. ## AI tools and these docs Never paste API keys or real patient data into the docs search, the docs assistant, or any AI chat tool. Use placeholders such as `hlsk_...` and made-up patients when you ask for help. See [Docs for AI agents](/ai-agents). # Templates Source: https://docs.healos.ai/templates List the note templates your organization can generate with A template decides the sections and style of a generated note. `GET /templates` lists every template your organization can use, so you can show them in your own product or pick one when you regenerate a note. It needs the `notes:read` scope. The list contains: * **Built-in templates** (`type: "built_in"`): the HealOS templates every organization has, such as SOAP. * **Custom templates** (`type: "custom"`): templates created in your organization and shared with it. Private templates, which only one clinician can see, are not listed. ```bash theme={null} curl "https://api.healos.ai/ext-api/v1/templates?type=custom" \ -H "X-API-Key: $HEALOS_API_KEY" ``` ```json theme={null} { "data": [ { "id": "77777777-0000-0000-0000-000000000001", "name": "Follow-up Visit", "type": "custom", "document_type": "note", "description": "Subjective, Objective, Assessment, Plan", "sections": ["Subjective", "Objective", "Assessment", "Plan"], "includes_prior_visit": false } ], "meta": { "page": 1, "limit": 20, "total_pages": 1 } } ``` | Query | Description | | - | - | | `type` | `built_in` or `custom` to return only one kind. Omit for both. | | `page`, `limit` | Pagination. `limit` defaults to 20, maximum 100. | | Field | Description | | - | - | | `id` | Pass this as `template_id` when you [regenerate a note](/clinical-notes#regenerate-a-note). | | `document_type` | `note` for clinical notes, `document` for letters and forms. | | `description` | The template's section titles, in order (null if it has none). | | `sections` | The same section titles as a list. | | `includes_prior_visit` | Whether notes from this template include the patient's previous visit by default. | # Test mode Source: https://docs.healos.ai/test-mode How to test an integration today, and what still touches real systems > [!WARNING] > > HealOS has **no sandbox or test-mode keys yet**. Every key works against > production, and every call has real effects in the organization the key > belongs to. ## Test in a separate organization Until a sandbox exists, build and test against a **separate HealOS organization** that holds only fake data: 1. Create a second organization in the HealOS dashboard, for example "Acme Clinic (Test)". Ask your HealOS contact if you need help. 2. Create API keys **in that organization** (Account Settings → API Keys). A key only ever sees the organization it was created in, so a test key can't read or change your real patients. 3. Call [`GET /me`](/api-reference/account/describe-the-calling-api-key) first in every script and check that `data.org.name` is the test organization. 4. Use clearly fake data: names like "Testy Quickstart", a date of birth of `1970-01-01`, phone numbers in the fictional `555-01xx` range and `external_id` values starting with `test-`. ## What still has real effects in a test organization | Action | Real effect | How to limit it | | - | - | - | | Create, update or delete patients, documents, appointments | Changes the test organization only | None needed | | [Generate a note](/clinical-notes#generate-a-note-from-text) from text or audio | Uses one **Scribe session** from that organization's plan | Generate only the notes you need | | [Generate](/clinical-notes#generate-a-note-from-documents) or [regenerate](/clinical-notes#regenerate-a-note) a note | Runs AI note generation | Same as above | | [Run an eligibility check](/recipes/eligibility-check) | Sends a **billable** request to the real payer | See below | | [Check prior-auth decisions now](/prior-auth#check-decisions-now) | Signs in to Availity as the organization | Only works when the organization has an Availity workflow | | Webhooks | Sends events to the URL you register | Point test webhooks at a test endpoint | ### Eligibility checks Payers only answer for real members, so there is no way to run a meaningful eligibility check on made-up data. A made-up member usually comes back as a payer error (`422`) or a "not found" issue, and can still be billed. Build and test the code that handles the response with the [example response](/benefits#2-run-a-check), then run a small number of real checks under your business associate agreement. # Versioning and deprecation Source: https://docs.healos.ai/versioning How the API changes within v1, what counts as breaking, and how much notice you get The API has one version today, **v1**, and the version is part of every URL: ```text theme={null} https://api.healos.ai/ext-api/v1 ``` Nothing in v1 is deprecated. Every change is recorded in the [Changelog](/changelog). ## Changes that ship without notice Within v1 we only **add** things. These changes ship at any time and appear in the changelog afterwards: * new endpoints; * new optional request fields and query parameters; * new fields in responses; * new values in response enums, such as a new `status` or webhook event type; * new scopes. Existing keys don't get them, except keys with `*` (full access). Build your client so these never break it: * Ignore response fields you don't know. * Handle an unknown enum value, for example by logging it and treating it as "other", instead of failing. * Branch on the HTTP status and on `code` where one is given, not on the `error` text, which can change. See [Error catalog](/errors). ## Breaking changes A breaking change is one that can stop a working integration: * removing or renaming a field, endpoint or enum value; * making an optional field required, or adding a new required field; * changing a field's type or an endpoint's status codes; * rejecting input that used to be accepted. Breaking changes go into a **new version** (for example `/ext-api/v2`), not into v1. When that happens: 1. We announce it in the [Changelog](/changelog) **before** it ships, with what changes and what to do. 2. The old behaviour keeps working for **at least 6 months** after its replacement ships. 3. A deprecated endpoint says so on its reference page, and its responses carry `Deprecation` and `Sunset` headers ([RFC 8594](https://www.rfc-editor.org/rfc/rfc8594)) with the date it stops working. ### Security fixes The one exception is a fix that closes a security or abuse problem. We may then reject input that was never meant to work, without a new version or advance notice, and record it in the changelog the same day. The [input limits of October 27, 2026](/changelog) (page size cap, request size limits and file content checks) are an example. ## The OpenAPI document The [OpenAPI document](/api-reference) describes v1. Its `info.version` tracks changes to the document itself, not the API version in the URL. ## The CLI The [`healos` CLI](/cli) has its own version numbers on npm (`@healos/cli`). Its releases are listed in the [Changelog](/changelog). Update it by running the install command again. # Webhooks Source: https://docs.healos.ai/webhooks Receive real-time notifications when clinical notes and patient documents change state, instead of polling. Healos can POST an event to a URL you control whenever a clinical note or a patient document reaches a meaningful state. Register a webhook once and stop polling the [notes](/clinical-notes) and document endpoints. Every payload carries resource identifiers plus a `*_url` you can call — the webhook is a notification, not the content itself. Fetch the content over the authenticated External API using that URL. > [!NOTE] > > `patient_id` is a BigInt serialized as a string. Treat it as an opaque string, > same as elsewhere in the API. See [Making Requests](/making-requests). ## Event types | Event | Fires when | Pull the result from | | - | - | - | | `NOTE_CREATED` | A new clinical note is generated — a session is finalized, or a note is created via the API | `GET /notes/{noteId}` | | `NOTE_REGENERATED` | A note is regenerated, for example via `POST /sessions/{sessionId}/notes/regenerate` | `GET /notes/{noteId}` | | `NOTE_UPDATED` | An existing note is edited, saved, or reverted | `GET /notes/{noteId}` | | `DOCUMENT_STATUS_CHANGED` | A patient document's text extraction reaches a terminal state (`completed` or `failed`) | `GET /patients/{patientId}/documents` | ## Payloads Note events (`NOTE_CREATED`, `NOTE_REGENERATED`, `NOTE_UPDATED`) share one shape: ```json Note event theme={null} { "event": "NOTE_REGENERATED", "note_id": "926f1540-2878-44b9-a2ba-9b5c4268d268", "session_id": "0be8b728-ffba-4dfb-8826-08fd850a8dc9", "patient_id": "1770623537795188951", "template_id": "11eaa736-ee98-4f71-b543-ec0ae62e5030", "source": null, "note_url": "https://api.healos.ai/ext-api/v1/notes/926f1540-2878-44b9-a2ba-9b5c4268d268", "timestamp": "2026-08-05T12:42:46.582Z" } ``` `DOCUMENT_STATUS_CHANGED` reports the outcome of asynchronous text extraction: ```json Document event theme={null} { "event": "DOCUMENT_STATUS_CHANGED", "document_id": "4822e568-ffc7-492a-b919-d69279f1329c", "patient_id": "1770623537795188951", "external_id": "your-emr-doc-id", "status": "completed", "error": null, "document_url": "https://api.healos.ai/ext-api/v1/patients/1770623537795188951/documents?external_id=your-emr-doc-id", "timestamp": "2026-08-05T12:49:24.118Z" } ``` * `status` is `"completed"` or `"failed"`. On failure, `error` describes why. * `document_url` is a direct document lookup when you set `external_id` at upload time, otherwise it points at the patient's document collection. ## Document upload flow Text extraction runs asynchronously, so the upload response returns before the text is ready. Use the webhook to learn when it finishes. **1. Upload the document** `POST /patients/{patientId}/documents`, optionally with an `external_id` form field. It returns `201` immediately. The document is typically `pending`, though it may already be `processing`, `completed`, or `failed` if extraction outran the response. **2. Wait for the event** When extraction finishes, Healos fires `DOCUMENT_STATUS_CHANGED`. No polling loop required. **3. Read the outcome** On `"completed"`, the document endpoints report `has_extracted_text: true` and `extracted_text_length`. The extracted text itself is not returned by the API — it is used internally as patient context. > [!WARNING] > > Rarely, if extraction could not be queued, the upload still returns `201` but > its `message` omits "text extraction started" and no `DOCUMENT_STATUS_CHANGED` > will fire. Call > `POST /patients/{patientId}/documents/{documentId}/extract` to trigger it. You can still poll `GET /patients/{patientId}/documents?external_id=` if you prefer, and re-trigger extraction with the `extract` endpoint above. ## Registering a webhook Register and manage webhooks in the Healos dashboard at [app.healos.ai/webhooks](https://app.healos.ai/webhooks). **1. Open the Webhooks page** Sign in and go to **[app.healos.ai/webhooks](https://app.healos.ai/webhooks)**. **2. Create a webhook** Select **Create webhook** and fill in: * **Name** — a label for the webhook. * **URL** — your HTTPS destination. Must resolve to a public host (see [Security](#security)). * **Event type** — one of the events above. * **Format** — `JSON` (default), `XML`, or `Form Data`. * **Headers** *(optional)* — static headers sent with every delivery, for example a shared secret. **3. Save** Save the webhook. Deliveries begin on the next matching event. Webhooks you create are scoped to your account — you see and manage your own. ### With an API key You can also manage webhooks over the External API, with a key that has the `webhooks:read` and `webhooks:write` scopes: [list](/api-reference/webhooks/list-webhooks), [create](/api-reference/webhooks/create-a-webhook), [update or pause](/api-reference/webhooks/update-a-webhook) and [delete](/api-reference/webhooks/delete-a-webhook). A key manages the webhooks of the user who created it, the same ones that user sees on the dashboard. Header values are write-only over the API. From the terminal: `healos webhooks create`. ## Delivery semantics These guarantees apply to the note and document events on this page. * **Method** — `POST`, body encoded per the configured format, 30-second timeout. * **Retries** — up to 3 attempts with exponential backoff (1s, then 2s, capped at 5s). A `408`, `429`, or `5xx` response consumes a retry rather than counting as delivered. * **Guarantees** — at-least-once. A failed or timed-out delivery is retried with the identical payload. * **No redirects** — a `3xx` response is treated as an error, so a redirect can neither downgrade the delivery to HTTP nor re-route your payload. > [!WARNING] > > Deduplicate **retries** by the whole payload, or by the `event` + resource id + > `timestamp` triple — not by resource id alone. The same `note_id` legitimately > produces `NOTE_CREATED` and later `NOTE_REGENERATED` or `NOTE_UPDATED`, and the > same `document_id` can emit `failed` and later `completed` after extraction is > retried. Those are distinct events you must not collapse. ## Security * **HTTPS and public hosts only.** Destinations are validated at registration and again immediately before every delivery. Loopback, private, CGNAT, link-local, and cloud-metadata ranges are rejected, IPv6 transition addresses included. * **Identifiers, not content.** Payloads carry patient and resource identifiers, never clinical content. Fetch the content over the authenticated External API using the `*_url`. * **Verify the source.** Send a secret through a configured header and check it on your side before trusting a delivery.