# Receptiva developer docs > Receptiva is an AI phone receptionist for personal-injury law firms. These docs cover its MCP connector for Claude and ChatGPT and its REST API for a firm's own systems: how to connect, what each tool and endpoint returns, and what data leaves the firm. --- # Receptiva connector for Claude and ChatGPT > What the Receptiva MCP connector lets Claude or ChatGPT see and do for your firm today, and how to connect it in three steps. Source: https://www.receptiva.ai/docs The Receptiva connector is an MCP server that your AI assistant connects to. Once it is connected, Claude or ChatGPT can read your firm's account status, your receptionist's settings, your calls (with the caller's number and a summary of each) and your new leads, and answer questions about them in plain language. If your firm's owner turns it on, it can also read call transcripts and the full intake details of a lead. When you ask, it can also mark a lead as contacted, signed or rejected, and change your receptionist's office hours, team, call routing, alert emails, contact details, the email it gives callers, the facts about your firm it shares when a caller asks, its house rules (short standing preferences for how it responds), or its name. Settings changes are made on a draft that you see and confirm before it goes live, and the last change can be undone. It changes nothing else. The connector is included on every Receptiva plan and every trial. There is one address for every firm: ```text https://mcp.receptiva.ai/mcp ``` ## How it works 1. **Add the address in your AI app.** In Claude or ChatGPT, create a custom connector and paste the address above. 2. **Sign in to Receptiva.** Use Google or a one-time code sent to your email. There are no passwords. 3. **Choose your firms and press Allow.** The consent screen lists the firms on your account. Pick the ones the app may see. The consent screen spells out what the app will be able to do: - See your account status and receptionist settings - See your calls (caller numbers and summaries) and new leads - See call transcripts, recording links and full lead intake details once your firm's owner turns that on - Mark a lead contacted, signed or rejected when you ask - Change your receptionist's hours, team, routing, alert emails, the email callers are given, firm facts and house rules when you ask, and undo a change - Stay connected until you disconnect it Step-by-step guides: [Connect Claude](/docs/connect-claude) and [Connect ChatGPT](/docs/connect-chatgpt). ## What it can do today These are the tools available today. Your AI assistant picks the right one from your question, so you never need to name a tool. | Tool | What it does | Who can use it | | --- | --- | --- | | [`receptiva_get_pricing`](/docs/tools#receptiva_get_pricing) | Plans, included minutes, overage rate, setup fee and trial terms | Anyone connected, no firm needed | | [`receptiva_get_account_status`](/docs/tools#receptiva_get_account_status) | Your plan, trial days left, your firm's number, a setup checklist and the one next step | Firm owners and view-only members | | [`receptiva_get_receptionist`](/docs/tools#receptiva_get_receptionist) | How your receptionist is set up: office hours, the email and firm facts it gives callers, its house rules, who takes transferred calls, how each kind of caller is routed | Firm owners and view-only members | | [`receptiva_list_calls`](/docs/tools#receptiva_list_calls) | Recent calls, newest first, each with the caller's number, the name they gave and a summary. Includes calls where the caller hung up early, and can list only calls updated since a given time | Firm owners and view-only members | | [`receptiva_get_call`](/docs/tools#receptiva_get_call) | One call's summary and how it was routed. When the call was put through to someone at your firm, also a summary of their conversation, for firm owners with [full caller data](/docs/data-privacy#full-caller-data) turned on | Firm owners and view-only members | | [`receptiva_get_transcript`](/docs/tools#receptiva_get_transcript) | One call's transcript, turn by turn: the caller with the receptionist, and after a transfer the receptionist's briefing to your staff member and their conversation with the caller | Firm owners only, with [full caller data](/docs/data-privacy#full-caller-data) turned on | | [`receptiva_list_leads`](/docs/tools#receptiva_list_leads) | Captured leads with their status and the callback number and email the caller gave | Firm owners and view-only members | | [`receptiva_get_lead`](/docs/tools#receptiva_get_lead) | One lead with the full intake the receptionist gathered: incident, injuries, treatment, insurance and a narrative | Firm owners only, with [full caller data](/docs/data-privacy#full-caller-data) turned on | | [`receptiva_update_lead_status`](/docs/tools#receptiva_update_lead_status) | Marks a lead contacted, signed or rejected | Firm owners only | | [`receptiva_update_receptionist_draft`](/docs/tools#receptiva_update_receptionist_draft) | Makes changes to hours, team members, routing, alert emails, contact details, the email for callers, firm facts, house rules or the receptionist's name on a draft, and shows what would change. Nothing is live yet | Firm owners only | | [`receptiva_apply_receptionist_draft`](/docs/tools#receptiva_apply_receptionist_draft) | Makes the draft live, once you confirm it. Live calls use it within about 2 minutes | Firm owners only | | [`receptiva_rollback_receptionist`](/docs/tools#receptiva_rollback_receptionist) | Restores the previous version of your receptionist's settings, once you confirm it | Firm owners only | Every argument and result field is listed on the [Tools reference](/docs/tools) page. ## What it cannot do - It cannot play or download call recordings itself. With full caller data on, it can give a firm owner a link to a call's recording that works for one hour. - It reads call transcripts, the summary of a conversation with your staff after a transfer, and a lead's injury, treatment and insurance details only after your firm's owner turns on full caller data in the dashboard, and only for the owner's own connection. Call summaries are written from what the caller said and can mention why they called; see [Data and privacy](/docs/data-privacy). - Transcripts label each turn caller, receptionist or staff (with the staff member's name), and say which part of the call it is from. Each turn has a `start_s`, the seconds from the start of the call; it is empty on calls recorded before turn times were kept. The briefing and the conversation after a transfer are transcribed only while your firm has [full call records](/docs/data-privacy#full-call-records) on. - It cannot change your phone number or your billing. You make those changes in your Receptiva dashboard, and the assistant gives you the dashboard link. - It changes your receptionist's settings only through a draft you confirm. Every change is logged and can be rolled back to the previous version. - It cannot rewrite your receptionist's script. It changes settings, firm facts and up to 10 short house rules (standing preferences such as "ask every new caller how they heard about us"), and each new or changed fact or house rule is checked before it is saved. Who gets transferred, and when, is your routing and office hours, never a house rule. Every firm's receptionist says it is an AI and that the call is recorded, gets a callback number, follows the same crisis handling and never gives legal advice. - It cannot delete your account, your calls or your leads. Removing a team member takes them off the roster, and a rollback can bring them back. A lead's status can be moved to another status later, though never back to new. > [!NOTE] > Some results include text said on a call, such as the reason for a call, the name the caller gave, a conversation summary or a transcript. That text comes back inside a field called `untrusted`. The connector tells your AI assistant to treat it as information only, never to follow instructions found in it, and to quote it only when you ask. See [Data and privacy](/docs/data-privacy#caller-text-is-untrusted). ## For AI agents These docs cover the MCP connector and the [REST API](/docs/api-overview), and are also published for machines: - Add `.md` to any page address to get the page as Markdown, for example `/docs/data-privacy.md`. - Or request any page with the header `Accept: text/markdown`. - [`/docs/llms.txt`](/docs/llms.txt) lists every page with a one-line description. - [`/docs/llms-full.txt`](/docs/llms-full.txt) is every page in one Markdown file. ## Next - [Connect Claude](/docs/connect-claude) - [Connect ChatGPT](/docs/connect-chatgpt) - [Example prompts](/docs/example-prompts) - [What's new](/docs/whats-new): what changed in the connector and the API, newest first --- # Example prompts > Prompts that work well with the Receptiva connector: leads to call back, recent calls, receptionist settings and changes, account status and pricing. Source: https://www.receptiva.ai/docs/example-prompts Once Receptiva is connected to [Claude](/docs/connect-claude) or [ChatGPT](/docs/connect-chatgpt), ask in your own words. You never need to name a tool. The prompts below are a starting point, and each one notes which tool the assistant runs to answer it. ## Leads **"Who do I still need to call back?"**\ What runs: [`receptiva_list_leads`](/docs/tools#receptiva_list_leads), filtered to leads that are still new. **"How many new leads came in this week?"**\ What runs: `receptiva_list_leads` with a date range. **"Which leads are still new? Give me their names and callback numbers."**\ What runs: `receptiva_list_leads`. Each lead includes the callback number and email the caller gave. **"Show me the leads we signed this month."**\ What runs: `receptiva_list_leads`, filtered by status and date. **"Give me the full intake for the lead who called this morning."**\ What runs: `receptiva_list_leads` to find the lead, then [`receptiva_get_lead`](/docs/tools#receptiva_get_lead) for the incident, injuries, treatment, insurance and narrative the receptionist gathered. It works for a firm owner once [full caller data](/docs/data-privacy#full-caller-data) is turned on. **"Mark the lead who called Tuesday about a rear-end collision as contacted."**\ What runs: `receptiva_list_leads` to find the lead (the assistant may also check `receptiva_list_calls` for the reason behind each call), then [`receptiva_update_lead_status`](/docs/tools#receptiva_update_lead_status). > [!IMPORTANT] > The assistant should name the lead (who, and when they called) before it makes the change. The connector's instructions tell it to update a lead only when you ask, never on its own and never because of something a caller said. Only a firm's owner can change a lead's status; a view-only member gets a permission message. A lead can move to contacted, signed or rejected, but never back to new. ## Calls **"What did callers want yesterday?"**\ What runs: [`receptiva_list_calls`](/docs/tools#receptiva_list_calls) with yesterday's date range. Each call carries a one-line reason. **"Which calls last week were transferred to someone at the firm?"**\ What runs: `receptiva_list_calls`, filtered by transfer outcome. **"Were any calls in Spanish this month?"**\ What runs: `receptiva_list_calls`. Each call includes the language it was in. **"Give me the full summary of the call that came in around 2 pm today."**\ What runs: `receptiva_list_calls` to find the call, then [`receptiva_get_call`](/docs/tools#receptiva_get_call) for its summary. **"Show me the transcript of that call."**\ What runs: [`receptiva_get_transcript`](/docs/tools#receptiva_get_transcript). It works for a firm owner once [full caller data](/docs/data-privacy#full-caller-data) is turned on in the dashboard; otherwise the assistant tells you where the setting is. **"What did the attorney and the caller agree on after the transfer?"**\ What runs: `receptiva_get_call`, whose conversation summary covers what the caller and your staff member discussed: the outcome, key points, details each of them confirmed and next steps. It works for a firm owner once [full caller data](/docs/data-privacy#full-caller-data) is turned on, like a transcript. **"Show me word for word what our attorney told the caller."**\ What runs: `receptiva_get_transcript` with `segment` set to `conversation`, for the conversation after the call was put through. It needs full caller data on, like any transcript. **"Which calls came from 361-555-0142?"**\ What runs: `receptiva_list_calls`. Each call carries the number it came from and the callback number the caller gave. **"Did anyone hang up before the receptionist answered today?"**\ What runs: `receptiva_list_calls` with `answered` set to false. **"Did a transfer fail today because nobody picked up?"**\ What runs: `receptiva_list_calls`, filtered by transfer outcome. **"Why wasn't the call from this morning transferred?"**\ What runs: `receptiva_list_calls` to find the call, then `receptiva_get_call`, whose `explanation` is built from the receptionist's routing record (which category it used, whether the office was open, who was rung), not by AI. ## Receptionist **"What are our office hours, and who gets transferred calls?"**\ What runs: [`receptiva_get_receptionist`](/docs/tools#receptiva_get_receptionist). **"What happens when someone calls after hours?"**\ What runs: `receptiva_get_receptionist`, which includes how each kind of caller is routed. **"Who gets the call summaries by email?"**\ What runs: `receptiva_get_receptionist`. **"What does our receptionist tell callers who ask for our email or about parking?"**\ What runs: `receptiva_get_receptionist`, which includes the email the receptionist gives callers and the firm facts it shares when asked. ## Changing the receptionist **"Change our office hours to 9 am to 6 pm, Monday through Friday."**\ What runs: `receptiva_get_receptionist` to read the current hours, then [`receptiva_update_receptionist_draft`](/docs/tools#receptiva_update_receptionist_draft) to make the change on a draft. The assistant shows you what would change; once you confirm, [`receptiva_apply_receptionist_draft`](/docs/tools#receptiva_apply_receptionist_draft) makes it live. **"Add Dana Ruiz, our new paralegal, at 361-555-0142, and send calls from existing clients to her first."**\ What runs: `receptiva_get_receptionist`, then `receptiva_update_receptionist_draft` to add Dana and put her first in the routing for existing clients. After you confirm the change, `receptiva_apply_receptionist_draft`. **"When a caller asks for our email, give them info@smithlaw.com."**\ What runs: `receptiva_get_receptionist`, then `receptiva_update_receptionist_draft` to set the email the receptionist gives callers. This is not the address your call summaries go to; that one stays as it is. After you confirm, `receptiva_apply_receptionist_draft`. **"Tell callers we offer free consultations and that there's free parking behind the building."**\ What runs: `receptiva_get_receptionist`, then `receptiva_update_receptionist_draft` to add two firm facts, which the receptionist shares when a caller asks. Each new or changed fact is checked before it is saved; if one is refused (for example, it would promise an outcome or give out a staff member's direct number), the assistant tells you why and suggests a rewording. After you confirm, `receptiva_apply_receptionist_draft`. **"Ask every new caller how they heard about our firm."**\ What runs: `receptiva_get_receptionist` to read the current house rules, then `receptiva_update_receptionist_draft` with the full list of house rules, this one added (a change replaces the whole list). A house rule is a short standing preference about how the receptionist responds: one idea per rule, up to 10. Each new or changed rule is checked before it is saved; one that would change who gets transferred or when is refused with a pointer to your routing or office hours instead. After you confirm, `receptiva_apply_receptionist_draft`. **"Undo the last change to our receptionist."**\ What runs: `receptiva_get_receptionist` for the current version, then, once you confirm, [`receptiva_rollback_receptionist`](/docs/tools#receptiva_rollback_receptionist). It restores the previous version, which also undoes any change made since in the dashboard. Calling it again undoes the restore (it brings back the version you just replaced). > [!NOTE] > A request about how the receptionist behaves goes to an existing setting when one fits: "always transfer Spanish speakers to Ana" is routing. Information about your firm is a fact; a standing preference about how to respond, such as a question to ask or something to mention, is a house rule. If none of those covers it, the assistant says plainly that it can't be changed. Some behavior is the same for every firm: the receptionist says it is an AI and that the call is recorded, gets a callback number, follows the same crisis handling and never gives legal advice. > [!IMPORTANT] > The assistant should show you exactly what will change and wait for your yes before it applies a draft or rolls back. Changes reach live calls within about 2 minutes. Only a firm's owner can change settings; a view-only member gets a permission message. ## Account **"What's my next step with Receptiva?"**\ What runs: [`receptiva_get_account_status`](/docs/tools#receptiva_get_account_status). It returns the one next step and a link to your dashboard. **"How many trial days do I have left?"**\ What runs: `receptiva_get_account_status`. ## Pricing **"What does Receptiva cost, and does the trial need a card?"**\ What runs: [`receptiva_get_pricing`](/docs/tools#receptiva_get_pricing). It works for anyone connected, even before a firm is set up. ## More than one firm **"Show new leads for smith-law."**\ What runs: `receptiva_list_leads` with `org` set to `smith-law`, your firm's slug. If you have more than one firm and do not say which, the assistant will ask. > [!NOTE] > Some questions the connector will not answer. It returns call transcripts, a link to a call's recording, and a lead's injury, treatment or insurance details only when your firm's owner has turned on [full caller data](/docs/data-privacy#full-caller-data). Call summaries are written from what the caller said and can mention why they called; see [Data and privacy](/docs/data-privacy). It also cannot change your number or your billing: for those, the assistant points you to your Receptiva dashboard. ## Next - [Tools reference](/docs/tools) - [Data and privacy](/docs/data-privacy) - [Troubleshooting](/docs/troubleshooting) --- # Connect Receptiva to Claude > Add Receptiva as a custom connector in Claude, sign in, choose your firms, and ask your first question. Source: https://www.receptiva.ai/docs/connect-claude This guide adds Receptiva to Claude as a custom connector, so you can ask Claude about your firm's calls, leads and receptionist. ## Before you start You need three things: - **A Receptiva account.** If you already use Receptiva, you will sign in with the same Google account or email you use for your dashboard. If your firm is not on Receptiva yet, [set it up first](/setup). - **Claude**, on the web at claude.ai or in the desktop app. - **The connector address:** ```text https://mcp.receptiva.ai/mcp ``` ## Add the connector 1. In Claude, open **Settings**, then **Connectors**. 2. Choose **Add custom connector**. 3. Paste `https://mcp.receptiva.ai/mcp` as the connector address and add it. 4. Claude opens a Receptiva sign-in page. Sign in with Google or with a one-time code sent to your email. 5. On the consent screen, choose your firms and press **Allow**. Claude brings you back to the chat, connected. ## The consent screen The consent screen is where you decide what Claude may see. It shows the name the app gave itself, then what the app will be able to do: - See your account status and receptionist settings - See your calls (caller numbers and summaries) and new leads - See call transcripts, recording links and full lead intake details once your firm's owner turns that on - Mark a lead contacted, signed or rejected when you ask - Change your receptionist's hours, team, routing, alert emails, the email callers are given, firm facts and house rules when you ask, and undo a change - Stay connected until you disconnect it Below that it lists the firms on your account. If you have more than one, each has a checkbox; untick any firm Claude should not see. A firm where you are a view-only member is marked **view only**. For those firms the connection is read-only too: Claude can read calls and leads but cannot change a lead's status or your receptionist's settings. The connection belongs to you, the person who signed in, not to the firm. Each person at your firm who wants to use Claude connects with their own sign-in. If your account has no firm yet, the screen says so and points you to [setup](/setup) instead of showing an Allow button. Once your firm is set up, start the connection again from Claude. ## Your first prompt Try this in a new chat: ```text Where does my firm stand with Receptiva? ``` The connector's own instructions tell Claude to call [`receptiva_get_account_status`](/docs/tools#receptiva_get_account_status) first. It returns your plan, trial days left, your firm's number and the one next step, with a link to your dashboard. For more ideas, see [Example prompts](/docs/example-prompts). ## More than one firm If you connected more than one firm, Claude needs to know which one you mean. It will ask, or you can say it up front: "Show new leads for smith-law." Behind the scenes Claude passes the firm's slug (the short name shown under each firm on the consent screen) as the `org` argument. If you leave it out, the tool answers with the list of firms on your connection so Claude can ask you. ## Claude Code Claude Code can use the same connector: add `https://mcp.receptiva.ai/mcp` as an MCP server. > [!TIP] > Claude remembers a connector's list of tools. When Receptiva adds new tools, refresh the connector in claude.ai under **Settings**, then **Connectors**. You do not need to approve it again. In Claude Code, detach the connector and attach it again to see the new list. ## Disconnecting To remove Claude's access, open your Receptiva dashboard and go to **Integrations**. Under **Connected AI apps**, choose **Disconnect** next to the app. Disconnecting takes effect on Claude's next request. Claude will then report that the connection was invalidated and ask you to reconnect. To use Receptiva in Claude again, add the connector again; you will see the consent screen again, because every new connection is approved on its own. ## Next - [Example prompts](/docs/example-prompts) - [Data and privacy](/docs/data-privacy) - [Troubleshooting](/docs/troubleshooting) --- # Connect Receptiva to ChatGPT > Add Receptiva as a custom connector in ChatGPT, sign in, choose your firms, and ask your first question. Source: https://www.receptiva.ai/docs/connect-chatgpt This guide adds Receptiva to ChatGPT as a custom connector, so you can ask ChatGPT about your firm's calls, leads and receptionist. ## Before you start You need three things: - **A Receptiva account.** If you already use Receptiva, you will sign in with the same Google account or email you use for your dashboard. If your firm is not on Receptiva yet, [set it up first](/setup). - **ChatGPT**, with access to its settings. - **The connector address:** ```text https://mcp.receptiva.ai/mcp ``` ## Add the connector 1. In ChatGPT, open **Settings**, then **Apps & Connectors**. 2. If ChatGPT asks you to turn on developer mode before you can add a custom connector, turn it on. 3. Create a custom connector and paste `https://mcp.receptiva.ai/mcp` as its address. 4. ChatGPT opens a Receptiva sign-in page. Sign in with Google or with a one-time code sent to your email. 5. On the consent screen, choose your firms and press **Allow**. ChatGPT brings you back, connected. ## The consent screen The consent screen is the same one Claude users see. It shows the name the app gave itself, then what the app will be able to do: - See your account status and receptionist settings - See your calls (caller numbers and summaries) and new leads - See call transcripts, recording links and full lead intake details once your firm's owner turns that on - Mark a lead contacted, signed or rejected when you ask - Change your receptionist's hours, team, routing, alert emails, the email callers are given, firm facts and house rules when you ask, and undo a change - Stay connected until you disconnect it Below that it lists the firms on your account. If you have more than one, untick any firm ChatGPT should not see. A firm where you are a view-only member is marked **view only**, and ChatGPT's access to that firm is read-only too. The connection belongs to you, the person who signed in, not to the firm. If your account has no firm yet, the screen points you to [setup](/setup) instead of showing an Allow button. > [!NOTE] > Apps name themselves when they connect. The consent screen shows that name as a claim ("an app calling itself..."), and your dashboard lists it with the label "name set by the app". Only press Allow if you just started the connection from ChatGPT yourself. ## Your first prompt Try this in a new chat: ```text Where does my firm stand with Receptiva? ``` ChatGPT calls [`receptiva_get_account_status`](/docs/tools#receptiva_get_account_status), which returns your plan, trial days left, your firm's number and the one next step, with a link to your dashboard. See [Example prompts](/docs/example-prompts) for more. ## More than one firm If you connected more than one firm, name the one you mean, for example "Show new leads for smith-law". ChatGPT passes the firm's slug as the `org` argument. If it leaves it out, the tool answers with the list of firms on your connection so ChatGPT can ask you which one. ## Disconnecting Open your Receptiva dashboard and go to **Integrations**. Under **Connected AI apps**, find the app and choose **Disconnect**. Disconnecting takes effect on ChatGPT's next request: Receptiva refuses it from then on. To use Receptiva again, add the connector again and approve it on the consent screen. ## Next - [Example prompts](/docs/example-prompts) - [Data and privacy](/docs/data-privacy) - [Troubleshooting](/docs/troubleshooting) --- # REST API overview > How to call the Receptiva REST API from your own systems, covering the base URL, API key authentication, pagination, errors, rate limits and versioning. Source: https://www.receptiva.ai/docs/api-overview The REST API gives your own systems, such as a case-management system or a reporting script, the same calls and leads your firm sees in the Receptiva dashboard. It is for servers. For Claude and ChatGPT, use the [MCP connector](/docs) instead. ## Base URL ``` https://api.receptiva.ai ``` Every path starts with the version, `/v1`, so the calls list is `https://api.receptiva.ai/v1/calls`. Paths on these pages and in the API reference are written the same way, for example `GET /v1/calls`. Requests and responses are JSON over HTTPS. A machine-readable description of every endpoint is at `https://api.receptiva.ai/v1/openapi.json` (OpenAPI 3.1, no key needed), and the [API reference](/docs/api-reference) is generated from it. ## Authentication Send an API key as a bearer token on every request: ```bash curl https://api.receptiva.ai/v1/calls \ -H "Authorization: Bearer $RECEPTIVA_API_KEY" ``` Your firm's owner creates keys in the Receptiva dashboard under **Integrations**. See [API keys](/docs/api-keys). A key belongs to one firm, so there is no firm parameter. Keep keys on a server. Do not put one in a web page, a mobile app or a URL. ## Endpoints | Endpoint | What it returns | Permission | | --- | --- | --- | | `GET /v1/account` | Where the firm stands: plan, phone number, trial and the one next step. Also the firm's stable `org.id` and the calling key's own name, permissions and expiry (`api_key`). | `org:read` | | `GET /v1/receptionist` | The receptionist's live settings | `receptionist:read` | | `GET /v1/calls` | Calls, newest first, each with structured details (people, company, claim and case numbers). `caller_number` finds one caller's calls; `reference` finds the calls that quoted a claim or case number. | `calls:read` | | `GET /v1/calls/{call_id}` | One call, with how it was routed and, after a transfer, a summary of the conversation with your staff member (`untrusted.conversation_summary`) | `calls:read` | | `GET /v1/calls/{call_id}/transcript` | The call's transcript, turn by turn: the intake, and after a transfer the briefing and the conversation with your staff member. `segment` returns one part. Pages by `start_turn` and `limit` (see below). | `calls:transcript` | | `GET /v1/calls/{call_id}/recording` | The call's audio recording | `calls:recording` | | `POST /v1/calls/{call_id}/recording-link` | A link to the recording that works for one hour | `calls:recording` | | `GET /v1/recordings/{token}` | The audio behind a recording link. No key needed: the link is the credential. | none | | `GET /v1/leads` | New-client leads, newest first. `caller_number` finds one caller's leads; `external_id` finds the lead behind a record in your own system. | `leads:read` | | `GET /v1/leads/{lead_id}` | One lead with its full intake | `leads:narrative` | | `PATCH /v1/leads/{lead_id}` | Sets a lead's status, your own id for it (`external_id`) and a note on its status (`status_reason`), any of the three. Send `expected_status` with `status` to refuse the change if the lead has moved on. | `leads:write` | | `GET /v1/events` | Your firm's events, oldest first. Pass `after` to read the ones that came after an event you already have. See [Webhooks](/docs/webhooks). | `webhooks:read` | | `GET /v1/events/{event_id}` | One event | `webhooks:read` | | `GET /v1/webhook-endpoints` | Your webhook endpoints and their health. Never a signing secret. | `webhooks:read` | | `GET /v1/webhook-deliveries` | Webhook deliveries, newest first, with each attempt | `webhooks:read` | | `POST /v1/webhook-endpoints/{endpoint_id}/test` | Sends a test event to one endpoint | `webhooks:test` | | `POST /v1/webhook-deliveries/{delivery_id}/redeliver` | Sends a delivery's event to its endpoint again | `webhooks:test` | | `GET /v1/health` | `{"ok": true}`. No key needed. | none | The [API reference](/docs/api-reference) lists every parameter and response field. ## Pagination List endpoints return the newest items first and take two query parameters: - `limit`: how many items to return, from 1 to 100. The default is 20. - `cursor`: the `next_cursor` value from the previous page. The transcript is not a list and pages by turn, not by cursor: `GET /v1/calls/{call_id}/transcript` takes `start_turn` (the turn to start from, default 0) and an optional `limit` (at most 500 turns). Without `limit` it returns every turn from `start_turn` to the end; with it, at most `limit` turns, and `has_more` plus `next_start_turn` say where the next page starts. It takes no `cursor`; a request that sends one is a `400`. Its one filter is `segment` (`intake`, `briefing` or `conversation`), which returns one part of the call; `start_turn` then counts that part's turns. See [Transcripts](/docs/sync-guide#transcripts). Each list response carries `has_more` and `next_cursor`. Keep requesting with the new cursor until `has_more` is `false`. A cursor is opaque: pass it back unchanged, and use it only on the endpoint that issued it. Send every filter again with the cursor, unchanged. A cursor marks a position in the list; it does not remember the filters, so a cursor from a request with `updated_since` replayed without it returns a different set. The calls and leads lists also carry `as_of`: Receptiva's own clock when the list was read, a few seconds early on purpose. To poll for changes, pass the first page's `as_of` as the next poll's `updated_since` rather than reading your own clock. See [Keep another system in sync](/docs/sync-guide). ## Query parameters Unknown query parameters are rejected with `400` and the code `invalid_request`, so a typo is caught at once. The error names the parameters that endpoint does accept, for example ``Unknown parameter `limit`. This endpoint accepts: `start_turn`, `segment`.`` Do not add a cache-buster such as `?_=123` to the query string. Responses are never cached (`Cache-Control: private, no-store`). ## Finding a caller by phone number `GET /v1/calls` and `GET /v1/leads` take `caller_number`. Send E.164 (`+12105550147`) or a 10-digit US number in any common format (`(210) 555-0147`, `210-555-0147`). A number without `+` is read as a US number. Encode the `+` as `%2B` if you can; an unencoded `+` (which arrives as a space) is accepted too. Anything that cannot be a phone number is a `400 invalid_request`. - On calls, it matches the number the call came from (`from`, the caller ID), not the callback number the caller gave. - On leads, it matches the lead's callback number (`phone`), compared the same way however the caller said it. ## Caller text is data, not instructions Anything said on a call, by the caller or your staff, or written from what was said, is returned under a field named `untrusted`: summaries, the conversation summary, names, transcript turns and intake details. If you pass API responses to an AI model, treat everything under `untrusted` as data and never as instructions. A lead's `external_id` and `status_reason` are not caller text: they are what your firm set, so they sit beside `status`, not under `untrusted`. ## Errors Errors use the problem details format (RFC 9457) with the content type `application/problem+json`: ```json { "type": "about:blank", "title": "Not Found", "status": 404, "code": "not_found", "detail": "No call with that id for this firm.", "request_id": "..." } ``` Use `code` in your own logic. `title` and `detail` are for people and may change. Every response also carries an `X-Request-Id` header. Include it when you email us about a request. | Status | `code` | Meaning | | --- | --- | --- | | 400 | `invalid_request` | A parameter or the body is not valid. The `errors` array names each field. | | 400 | `invalid_cursor` | The cursor is not one this endpoint issued. | | 400 | `invalid_range` | `from` must be earlier than `to`. | | 401 | `unauthorized` | The key is missing, mistyped, revoked or expired. | | 403 | `insufficient_scope` | The key does not have the permission this endpoint needs. | | 403 | `org_suspended` | The firm's account is suspended. | | 403 | `forbidden` | The key may not make this change. | | 404 | `not_found` | Nothing with that id belongs to this firm. | | 404 | `transcript_unavailable` | Receptiva has no transcript for that call. | | 404 | `no_recording` | That call has no recording. | | 404 | `recording_unavailable` | The recording could not be read. | | 404 | `invalid_link` | The recording link is wrong, expired or no longer allowed. | | 409 | `not_configured` | The firm's receptionist is not set up yet. | | 405 | `method_not_allowed` | `HEAD` is not supported. Use `GET`. | | 409 | `status_conflict` | The lead's status is no longer the `expected_status` you sent, or it changed while the request ran. Nothing was changed; the answer's `lead` member is the lead as it is now. | | 415 | `unsupported_media_type` | A request body was sent without `Content-Type: application/json`. | | 429 | `rate_limited` | Too many requests. Wait for the time in `Retry-After`. | | 500 | `internal_error` | Something went wrong on our side. Email us the request id. | | 503 | `unavailable` | A temporary problem on our side. Retry after a short wait. | A request for another firm's call or lead answers `not_found`, the same as an id that does not exist. ## Rate limits Each key may make 60 requests per minute. Once a key is accepted, every response says where it stands: | Header | Meaning | | --- | --- | | `RateLimit-Limit` | Requests allowed per minute | | `RateLimit-Remaining` | Requests left in the current minute | | `RateLimit-Reset` | Seconds until the count resets | Over the limit, the API answers `429` with a `Retry-After` header in seconds. There is also a limit of 120 requests per minute per IP address, shared with the MCP connector. ## Timestamps Every timestamp the API returns is ISO 8601 with an explicit offset. Most end in `+00:00`, for example `2026-10-03T00:24:58.248695+00:00`; a few, such as a recording link's `expires_at`, end in `Z`, for example `2026-10-03T01:24:58.000Z`. Both are valid ISO 8601 and both mean UTC, so parse them with an ISO 8601 parser rather than comparing them as text. Timestamps you send, such as `from`, `to` and `updated_since`, need an offset too: `Z` or `±HH:MM`. In a URL a `+` means a space, so write a positive offset as `%2B`: `2026-10-02T14:00:00%2B02:00`. Using `Z` avoids the problem. If a `+` does arrive as a space in the offset, for example when you send a response's `updated_at` back unencoded, the API reads it as `+`. Anything else that is not a valid timestamp is rejected with `invalid_request`. ## Versioning The version is in the path (`/v1`). Within a version, changes are additive: new endpoints, new optional parameters and new response fields. Write clients that ignore fields they do not know. A change that would break existing clients ships as a new version. ## Next - [API keys](/docs/api-keys) - [Keep another system in sync](/docs/sync-guide) - [API reference](/docs/api-reference) --- # API keys > How a firm owner creates and revokes Receptiva API keys, what each permission allows, and how to store a key safely. Source: https://www.receptiva.ai/docs/api-keys An API key lets one of your own systems call the [REST API](/docs/api-overview) for your firm. Only the firm's owner can create or revoke keys. ## Create a key 1. Sign in to your firm's Receptiva dashboard as the owner. 2. Open **Integrations** and find **API keys**. 3. Give the key a name that says what uses it, for example "CRM sync", and choose its permissions. 4. Copy the key and store it in your system's secret storage. The full key is shown once, when you create it. Receptiva stores only a one-way hash of it, so nobody, including Receptiva staff, can show it to you again. If you lose a key, revoke it and create a new one. Keys start with `rcp_live_`. A firm can have up to 10 active keys. Use a separate key for each system, so you can revoke one without interrupting the others. ## Permissions You choose one of four sets when you create a key. | Set | What the key can do | | --- | --- | | Read, without transcripts | Read the account status, receptionist settings, calls with their summaries, and leads. No transcripts, no recordings and no full lead intake. | | Read without transcripts, and update leads | Everything in Read, without transcripts, and set a lead's status to contacted, signed or rejected. No transcripts, no recordings and no full lead intake. | | Read | Read, without transcripts, plus call transcripts, call recordings and each lead's full intake. | | Read and update leads | Everything in Read, and set a lead's status to contacted, signed or rejected. | Every set also lets the key read your firm's [webhook](/docs/webhooks) endpoints, deliveries and events, send a test event and resend a delivery. Keys created before webhooks were available do not have this; create a new key to use it. Each endpoint names the permission it needs, as a scope such as `calls:read`. A request with a key that lacks it answers `403` with the code `insufficient_scope`. A key can read its own permissions at `GET /v1/account`: `api_key` there lists its name, its `scopes` and when it expires, so an integration can check what it may do before it starts. | Scope | Allows | | --- | --- | | `org:read` | `GET /v1/account` | | `receptionist:read` | `GET /v1/receptionist` | | `calls:read` | Listing calls and reading one call | | `calls:transcript` | Reading a call's transcript | | `calls:recording` | Playing a call's recording and creating a recording link. Keys created before recordings were available do not have it; create a new key to use recordings. | | `leads:read` | Listing leads | | `leads:narrative` | Reading one lead with its full intake | | `leads:write` | Setting a lead's status | | `webhooks:read` | Listing your webhook endpoints, their deliveries and your firm's events. See [Webhooks](/docs/webhooks). | | `webhooks:test` | Sending a test event to an endpoint and resending a delivery. It cannot add, change or delete an endpoint. | Transcripts, recordings and lead intake hold what callers said about their injuries and treatment. A key in the Read set or the Read and update leads set can read them, whatever the **Full caller data for AI assistants** setting says. That setting applies only to AI assistants connected through the MCP connector, because a key sends data to a system your firm runs. If the system does not need transcripts, recordings or intake, choose Read, without transcripts, or Read without transcripts, and update leads if it writes lead statuses back. ## Revoke a key In **Integrations**, choose **Revoke** next to the key. It stops working on its next request and cannot be turned back on. Revoke a key when the system that used it is retired, when someone who had access to it leaves, or if it may have been exposed, for example pasted into a chat or committed to a code repository. ## Rotate a key To replace a key without interrupting the system that uses it: 1. Create a second key with the same permissions. 2. Deploy the new key to the system, in place of the old one. 3. In **Integrations**, check that the new key's last-used time has moved, which shows the system is using it. 4. Revoke the old key. A firm can have up to 10 active keys, so there is room for the second key while both exist. If the firm is at the limit, revoke a key nothing uses first. ## Keep keys safe - Store keys in a secrets manager or environment variable on a server. - Never put a key in browser or mobile code, or in a URL. - Give each system its own key with the smallest set of permissions it needs. - The dashboard shows when each key was last used. Revoke keys nothing uses. ## What is recorded Receptiva records who created and who revoked each key in its audit log. Every call and lead read made with a key is recorded there too, with the key's id, the same way reads through the connector are. See [Data and privacy](/docs/data-privacy). ## Next - [REST API overview](/docs/api-overview) - [Keep another system in sync](/docs/sync-guide) --- # Keep another system in sync > A step-by-step recipe for copying Receptiva calls and leads into a case-management system with the REST API, using updated_since and stable call ids. Source: https://www.receptiva.ai/docs/sync-guide This page is a recipe for keeping a case-management system, CRM or spreadsheet in step with your firm's Receptiva calls and leads. It is written so a developer, or an AI coding assistant, can build the integration from it. You need an [API key](/docs/api-keys). The Read set covers everything on this page except writing lead statuses back, which needs Read and update leads. A sync that needs no transcripts, recordings or full lead intake can use Read without transcripts, and update leads: it reads calls and leads and writes statuses back, and nothing more. ## The short version 1. Poll `GET /v1/calls?updated_since=` every few minutes. 2. Follow `next_cursor` until `has_more` is `false`, sending the same filters each time. 3. Save each call under its `call_id`. If you already have that `call_id`, replace your copy. 4. For calls with a `lead_id`, fetch the lead with `GET /v1/leads/{lead_id}` (with its full intake), or with `GET /v1/leads?call_id=` (without it). 5. Poll `GET /v1/leads?updated_since=` too, to catch lead status changes made outside your system. Save each lead under its `lead_id`. 6. When you write a status back, send `expected_status` with the status you last saw, and your own matter id as `external_id`. ## Identify a call by call_id Every call has a `call_id` that never changes. Use it as the key in your own system. The same call can come back on a later poll when its record changes, so write your sync as "insert or replace by `call_id`", never "always insert". ## Poll for changes ```bash curl "https://api.receptiva.ai/v1/calls?updated_since=2026-10-02T14:00:00Z&limit=100" \ -H "Authorization: Bearer $RECEPTIVA_API_KEY" ``` `updated_since` returns every call whose record changed at or after that time. Each call carries `updated_at`. - Every list response carries `as_of`: Receptiva's own clock when the list was read, set half a minute early on purpose. Keep the `as_of` of the first page of each poll, and once the poll has finished without errors, use it as `updated_since` on the next one. Do not use your own server's clock: it can drift from Receptiva's. - `as_of` is in UTC with a `Z`, so it goes into the URL as it is. If you send a time with an offset instead, write `+` as `%2B`. - The filter is deliberately broad. A call's record also changes when Receptiva finishes processing it shortly after it ends, so you may receive a call again with nothing important changed. That is expected, and replacing by `call_id` makes it harmless. - A call appears a short time after it ends. It is not available while it is in progress. Until Receptiva has finished processing it, the call has `processing_complete: false`, and its lead may not exist yet. Its `updated_at` moves when processing finishes, so the next poll returns it again, complete. - Missed calls, where the caller hung up before the receptionist spoke, are listed too, with `answered: false`. A poll every 5 minutes uses a small fraction of the limit of 60 requests per minute. ## What each call gives you | Field | Use | | --- | --- | | `call_id` | Your key for the call | | `started_at`, `duration_s` | When and how long. `timezone` on the response is the firm's timezone. | | `from`, `callback_number` | The caller's number and the number they asked to be called back on. Match these to a client in your system, or find the caller's other calls with `caller_number` (below). | | `callback_extension` | The extension the caller gave with `callback_number`, digits only (`"12"`), or `null`. Dial `callback_number`, then the extension. It is never part of `callback_number`. | | `answered` | Whether the receptionist answered. `false` is a missed call: the caller hung up before the receptionist spoke. | | `category`, `urgency`, `language` | What kind of call it was. The [API reference](/docs/api-reference) lists the values; new ones may appear, so treat a value you do not know as `other`, `normal` or `unknown` | | `outcome` | The transfer outcome: whether the receptionist put the caller through to your staff. `connected`, `declined` (a staff member answered and asked for a message instead), `caller_gone` (the caller hung up on hold), `no_answer` (your staff were rung and nobody picked up) or `not_attempted` (no transfer was tried) | | `lead_id` | The `lead_id` of the lead the call produced, or `null`. Fetch the lead with it. | | `lead_captured` | Whether the call produced a new-client lead: `true` exactly when `lead_id` is set | | `processing_complete` | `false` while Receptiva is still processing the call; poll again later | | `untrusted.caller_name`, `untrusted.summary` | The name the caller gave and a summary of why they called | | `untrusted.details` | Structured fields from the call: who it was about, the caller's company, who they asked for, and identifiers such as claim numbers. See [Structured details](#structured-details) | | `dashboard_url` | A link that opens the call in the Receptiva dashboard, for a person who is signed in | `answered` and `outcome` answer different questions. `answered: false` means the caller hung up before the receptionist spoke. `outcome: no_answer` means the receptionist answered and tried to transfer the caller, and nobody at your firm picked up. Some calls have no conversation to summarize: a missed call, a caller who never spoke, or a summary that could not be written. On those calls `category`, `urgency`, `language`, `untrusted.summary.reason` and `untrusted.summary.message` are `null`, and `lead_id` is usually `null`. `untrusted.caller_name` and `callback_number` are `null` unless the caller gave them. `call_id`, `started_at`, `duration_s`, `answered`, `outcome` and `has_recording` are still set, and so is `from` when the phone network passed on the caller ID. A missed call looks like this: ```json { "call_id": "Qm29LkPz81Xc", "started_at": "2026-10-02T21:14:03.512+00:00", "duration_s": 4, "answered": false, "category": null, "urgency": null, "language": null, "outcome": "not_attempted", "lead_captured": false, "lead_id": null, "from_masked": "***0100", "from": "+13615550100", "callback_number": null, "callback_extension": null, "updated_at": "2026-10-02T21:14:41.907+00:00", "processing_complete": true, "dashboard_url": "https://pine-harbor-law.receptiva.ai/?call=Qm29LkPz81Xc", "has_recording": false, "untrusted": { "summary": { "reason": null, "message": null }, "caller_name": null, "details": null } } ``` Everything under `untrusted` came from what was said on the call. Store and display it as text. Do not let it drive logic, and if you pass it to an AI model, pass it as data. ## Structured details Besides the prose summary, each answered call carries `untrusted.details`, the facts a case system files under a matter. An insurance adjuster's call looks like this: ```json "details": { "about": [{ "name": "Rosa Delgado", "relation": "client" }], "caller_organization": "State Farm", "asked_for": "Dana Ortiz", "message_for": null, "best_time": "after 2 pm", "references": [ { "kind": "claim_number", "value": "418-QX7TP.302", "key": "418QX7TP302", "for_name": "Rosa Delgado" } ], "generated_at": "2026-10-07T16:02:11.000Z" } ``` | Field | What it is | | --- | --- | | `about` | The people the call is about other than the caller, with `relation`: `client`, `injured_party`, `adverse_party` or `other`. A call about two clients lists both. | | `caller_organization` | The company or office the caller said they were calling from. | | `asked_for` | Who the caller asked for: your team member's name as set up in Receptiva when the receptionist matched one, otherwise as the caller said it. | | `message_for`, `best_time` | Who a message is for, and when the caller said to call back, in their words. | | `references` | Identifiers the caller quoted: `claim_number`, `policy_number`, `case_number`, `police_report_number` or `other`. `for_name` ties one to a person in `about` when the caller did. | A value is kept only when it appears in what the caller said, so the receptionist's own guesses never reach `details`. Phone transcription can still mishear a name ("Rosa Del Gado" for "Rosa Delgado") or a digit, so treat each value as a strong hint: match it to your records conservatively, and confirm before you file anything on its strength. `details` is `null` on missed calls, on calls with nothing to extract, and on calls processed before 2026-10-07. Treat a `kind` or `relation` you do not know as `other`; new ones may be added. ## The conversation after a transfer When the receptionist put the caller through to someone at your firm, `GET /v1/calls/{call_id}` also carries `untrusted.conversation_summary`: an AI-written summary of what the caller and that staff member discussed. | Field | Use | | --- | --- | | `staff_name` | Who the caller spoke with | | `summary` | What was discussed, in a few sentences. `null` when no summary could be written, for example when nobody picked up; `outcome` is then empty and the lists are empty. | | `outcome` | How the conversation ended, in a few words | | `key_points`, `next_steps` | Short lines, at most 8 each | | `confirmed_details` | Facts stated in the conversation, such as a consult time, each with a `label`, a `value` and `said_by` (`caller` or `staff`) | | `conversation_status` | `complete`, or `partial` / `failed` when part of the conversation was not transcribed; `null` when no conversation with staff was recorded (for example nobody picked up) | | `covers` | The parts of the call's transcript when the summary was written: `intake`, `briefing`, `conversation`. The summary is about the `conversation`; the transcript's own `covers` is authoritative. | | `generated_at` | When the summary was written | It is written from that conversation only. `untrusted.summary` is still the summary of the caller's call with the receptionist, and the lead is unchanged. `conversation_summary` is `null` on calls where nobody was briefed or put through, on calls from before full call records, and on calls made while full call records were off. It is only on one call's detail, never on the calls list, so fetch the call when you want it. It is in place once `processing_complete` is `true`. ## Fetch several known calls at once To refresh calls you already know about, pass up to 50 ids: ```bash curl "https://api.receptiva.ai/v1/calls?ids=A7HdLS3aFzA4,Qm29LkPz81Xc" \ -H "Authorization: Bearer $RECEPTIVA_API_KEY" ``` An id that matches no call for your firm is left out of the result. ## Find a caller's earlier calls To see everything one person has called about, filter the calls list by the number the call came from: ```bash curl "https://api.receptiva.ai/v1/calls?caller_number=%2B12105550147" \ -H "Authorization: Bearer $RECEPTIVA_API_KEY" ``` `caller_number` takes E.164 (`+12105550147`) or a 10-digit US number in any common format (`(210) 555-0147`, `210-555-0147`); a number without `+` is read as a US number. On calls it matches `from`, the caller ID. It does not match `callback_number`, the number a caller asked to be called back on, which may be someone else's phone. To find leads by the number the caller gave, use the same filter on the leads list: `GET /v1/leads?caller_number=%2B12105550147`. Pages, `limit` and `cursor` work as on any list. ## Find calls by claim or case number `reference` finds the calls where a caller quoted an identifier: ```bash curl "https://api.receptiva.ai/v1/calls?reference=418-QX7TP.302" \ -H "Authorization: Bearer $RECEPTIVA_API_KEY" ``` It matches `details.references[].key`: case, spaces and punctuation are ignored, so `418-QX7TP.302`, `418 qx7tp 302` and `418QX7TP302` find the same calls. A misheard character does not match. To catch near-misses, fetch the calls you care about (by `caller_number`, or by date) and compare `key` values in your own code, conservatively. A value with no letters or digits is a `400 invalid_request`. ## Transcripts Fetch a transcript only when a person needs it: ```bash curl https://api.receptiva.ai/v1/calls/A7HdLS3aFzA4/transcript \ -H "Authorization: Bearer $RECEPTIVA_API_KEY" ``` A transcript has up to three parts, in this order. Each turn says which one it belongs to in `segment`: | `segment` | What it holds | | --- | --- | | `intake` | The caller and the receptionist | | `briefing` | The receptionist briefing a member of your staff before putting the call through, one block for each person the receptionist briefed. `briefings` lists each block with the person's `name`, how the attempt ended (`outcome`), its first turn (`start_turn`) and its `turn_count`. | | `conversation` | The caller and that staff member, after the call was put through | Each turn has a `speaker` (`caller`, `receptionist` or `staff`), `speaker_name` (the staff member's name, as it appears in your receptionist's settings, on a `staff` turn; `null` otherwise), the `segment`, the `text`, and `start_s`, the seconds from the start of the call. `start_s` is `null` on calls recorded before turn times were added. Consecutive pieces of speech from the same speaker in the same part are joined into one turn. Beside the turns, the response says what the transcript holds: - `covers`: the parts this call has, for example `["intake"]` or `["intake", "briefing", "conversation"]`. - `connected_name`: who the caller was put through to, or `null`. - `conversation_status`: `complete`, `partial` or `failed` (part or all of the conversation was not transcribed), `not_enabled` (your firm has full call records turned off, so only the intake is transcribed), or `null` when there was no conversation with staff. - `notice`: a sentence to show with the transcript when part of the conversation was not transcribed, otherwise `null`. If your integration was built for transcripts with only `caller` and `receptionist` turns, handle the new `staff` value. To keep only the caller's call with the receptionist, pass `segment=intake`: ```bash curl "https://api.receptiva.ai/v1/calls/A7HdLS3aFzA4/transcript?segment=intake" \ -H "Authorization: Bearer $RECEPTIVA_API_KEY" ``` `segment=conversation` returns only what the caller and your staff member said. With `segment`, `turn_count` and `start_turn` count that part's turns only, while `covers` and `briefings` still describe the whole call (a briefing's `start_turn` is its place in the whole transcript). For example, with `briefings[0].start_turn` of `12`, `?start_turn=12` (no `segment`) starts at that briefing; do not combine it with `segment=briefing`, where `start_turn=12` would skip the first 12 briefing turns. Because pieces of speech are now joined into whole turns, an intake can have slightly fewer turns than before. See [What's new](/docs/whats-new) for the full list of changes. The transcript pages by turn rather than by cursor. Without `limit`, one response holds every turn from `start_turn` (default 0) to the end, and `turn_count` says how many turns the whole transcript has. To skip turns you already have, pass `start_turn`, for example `?start_turn=40`. For smaller pages, add `limit` (at most 500 turns): `?limit=50` returns the first 50 turns with `has_more: true` and `next_start_turn: 50`, which you pass as `start_turn` for the next page with the same `limit` and `segment`. Recordings are the caller's call only. The receptionist's briefing to your staff member is included in the transcript as `segment: briefing`; neither the briefing nor your staff member's side of the conversation is in the recording. ## Recordings Each call carries `has_recording`. There are two ways to play one, and both need the `calls:recording` permission. **From a server.** Download the audio with your key. The response is the audio file, Opus audio in an Ogg file (`audio/ogg`), and `Range` requests work: ```bash curl https://api.receptiva.ai/v1/calls/A7HdLS3aFzA4/recording \ -H "Authorization: Bearer $RECEPTIVA_API_KEY" -o call.ogg ``` **In a browser.** A web page must never hold your API key. When a person presses play, have your server ask for a link and hand it to the page's audio player: ```bash curl -X POST https://api.receptiva.ai/v1/calls/A7HdLS3aFzA4/recording-link \ -H "Authorization: Bearer $RECEPTIVA_API_KEY" ``` The response has a `url` and an `expires_at`. The link plays that one call, needs no key, and stops working after one hour, or sooner if the key that created it is revoked. Create a link when someone presses play. Do not store links. Playing a link in a browser: - Put the `url` in an `