# Revox API documentation --- > Revox API docs for developers and AI agents. Index: https://www.getrevox.com/docs/api/llms.txt · Everything in one file: https://www.getrevox.com/docs/api/llms-full.txt · OpenAPI 3.1: https://www.getrevox.com/openapi.json · MCP server: https://www.getrevox.com/api/mcp-servers/generic/mcp > Base URL https://www.getrevox.com/api · Auth: `Authorization: Bearer $REVOX_API_KEY` --- ## Revox API Revox places AI phone calls. You describe the conversation in an **assistant** (prompt, voice, first sentence, what to extract after the call), then ask Revox to **call** a phone number with it, one call at a time or in **campaigns** of thousands of contacts. After the call you get the outcome, the transcript, the recording and the data the assistant extracted. These docs are written for developers and for AI agents: every page also exists in Markdown. ### At a glance - Base URL: `https://www.getrevox.com/api` - Auth header: `Authorization: Bearer $REVOX_API_KEY` - Content type: `application/json` - OpenAPI 3.1: `https://www.getrevox.com/openapi.json` - For agents: `https://www.getrevox.com/docs/api/llms.txt` - MCP server: `https://www.getrevox.com/api/mcp-servers/generic/mcp` ### Authentication Every request carries an API key as a Bearer token: `Authorization: Bearer YOUR_API_KEY`. Create keys in the dashboard, under [API keys](https://www.getrevox.com/dashboard?goto=api-keys). A key belongs to one organization: everything you create with it (assistants, calls, campaigns) lives in that organization. Keep it on your server, never in a browser or a mobile app. [Check an API key](https://www.getrevox.com/docs/api/authentication/check-an-api-key.md) tells you whether a key works. ### Quickstart: place a call and get its result #### 1. Create an assistant: `POST /assistants` A `name`, a `prompt` and a `voice`: the voice's language is the language of the call. You can skip this step and send an inline `assistant` when you place the call. ```bash curl -X POST "https://www.getrevox.com/api/assistants" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Appointment reminders", "prompt": "You are Julie, the assistant of the Acme dental practice. You call {{first_name}} to remind them of their appointment on {{appointment_date}} and ask them to confirm it. If they cannot come, offer to call them back to set a new date and ask when suits them best. Keep the call short and friendly.", "first_sentence": "Bonjour {{first_name}}, ici Julie du cabinet dentaire Acme. Je vous appelle au sujet de votre rendez-vous.", "first_sentence_mode": "static", "voice": { "provider": "cartesia", "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6" }, "webhook_url": "https://example.com/webhooks/revox", "structured_output_config": [ { "name": "appointment_confirmed", "type": "boolean", "description": "True when the person confirmed they will come.", "required": true }, { "name": "preferred_callback_time", "type": "datetime", "description": "When the person wants to be called back to set a new date, if they asked to." } ] }' ``` #### 2. Place the call: `POST /call` The `phone_number` in E.164 format and the `assistant_id`. `prompt_variables` fills the `{{variables}}` of the prompt for this contact. The response holds the `call` and its `id` right away: the call itself happens next. ```bash curl -X POST "https://www.getrevox.com/api/call" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone_number": "+33612345678", "assistant_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "prompt_variables": { "first_name": "Marie", "appointment_date": "Thursday, November 12 at 10am" }, "metadata": { "crm_id": "lead_48213" } }' ``` #### 3. Get the result: `GET /call/{id}` Poll the call every 5 to 10 seconds until its `status` is `completed`, `cancelled` or `errored`, or set the assistant's `webhook_url` and Revox POSTs the call to you (see [Webhooks](https://www.getrevox.com/docs/api/webhooks.md)). Then read `outcome` and `outcome_summary`, and the latest attempt's transcript, recording and `structured_output` in `last_call_attempt`. ```bash curl -X GET "https://www.getrevox.com/api/call/8d2f6b1a-4c9e-4f37-b215-6a0e9c3d7f12" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Calls and attempts A call is an order that can take several attempts: when nobody answers, Revox calls back following the assistant's `call_retry_config`, inside its calling windows, sometimes over days. Each dial is an attempt in `call_attempts`. A call's final statuses are `completed`, `cancelled` or `errored`; a callee who asks to be called back at a given time sends the call back to `scheduled` when attempts are left. To call a list, [create a campaign](https://www.getrevox.com/docs/api/campaigns/create-a-campaign.md) with an assistant and its contacts (nothing is dialed yet), then [launch its calls](https://www.getrevox.com/docs/api/campaigns/launch-a-campaigns-calls.md). Revox paces them (`max_concurrent_calls`), respects calling windows and retries, and keeps the campaign's [statistics](https://www.getrevox.com/docs/api/campaigns/get-campaign-statistics.md). ### Conventions - Revox IDs (calls, assistants, campaigns…) are UUIDs; a voice id is its provider's. Phone numbers are E.164: `+33612345678`. - Timestamps are ISO 8601 in UTC. Send them ending in `Z` (`2026-11-09T08:30:00Z`): offsets such as `+01:00` are rejected. - Field names are snake_case, except a few camelCase ones (in the voice endpoints, and `unpatchedCallsNotice`), written as each page shows them. - Unknown body fields are ignored without an error: copy field names from the pages. - Endpoints that say "No body" take none: send the request without one. - Use `https://www.getrevox.com/api`: `getrevox.com` answers with a 301 redirect, which most HTTP clients replay as a GET. ### Errors Errors use standard status codes. Their JSON body carries `error` (a message), except validation failures and unexpected errors, which carry `message`: - `400`: a field or parameter failed validation: `message: "Request validation failed"` and `bodyErrors.issues` (or `queryParameterErrors.issues`), each with the `path` of the field and a `message`. A request the API understands but refuses (an empty campaign name, nothing to launch, a call that cannot be paused now) is also a 400, with `error`. - `401`: the API key is missing or invalid. - `402`: the organization has run out of credits (`code: "INSUFFICIENT_BALANCE"`). - `403`: the resource belongs to another organization. - `404`: the resource does not exist in your organization. - `409`: the resource's state forbids it, for example cancelling a finished call. - `500`: unexpected server error, `{"message": "Server Error"}`. Retry later. - `502`: a provider Revox relies on failed (voice cloning). Retry later. ### SDKs Official SDKs, generated from this API, may lag behind this reference: ```bash npm install @revoxai/sdk # TypeScript pip install revox # Python gem install revox # Ruby ``` ### For AI agents - If your client speaks MCP, the [MCP server](https://www.getrevox.com/docs/api/mcp.md) covers the main workflow as tools (assistants, voices, calendars, single calls and their results), guides prompt writing and can wait for a call to finish. Running campaigns (it can only list them), phone numbers, exports and voice cloning are REST only. - Every page exists in Markdown: add `.md` to its URL, or send `Accept: text/markdown`. [llms.txt](https://www.getrevox.com/docs/api/llms.txt) indexes them with recipes; [llms-full.txt](https://www.getrevox.com/docs/api/llms-full.txt) has everything in one file. - Field descriptions are the source of truth: they say what `null` and an omitted field mean when the two differ, and the "Before you call" box of an endpoint lists the rules the schema cannot express. ### Reference #### Authentication Every request carries an API key as a Bearer token. Check that a key is valid before storing it. - [Check an API key](https://www.getrevox.com/docs/api/authentication/check-an-api-key.md): `GET /auth-status`. Check that your API key is valid, e.g. before storing it: a 200 with authenticated true means it is; any other answer means the key was not accepted. #### Calls A call is one order to call one phone number with an assistant. Revox dials it inside the calling windows, calls back when nobody answers, and records each dial as an attempt with its transcript, recording and extracted data. - [Place a call](https://www.getrevox.com/docs/api/calls/place-a-call.md): `POST /call`. Place an outbound call with a saved assistant (assistant_id) or a configuration for this call only (assistant). - [Get call by ID](https://www.getrevox.com/docs/api/calls/get-call-by-id.md): `GET /call/{id}`. Returns a call with its status, outcome and attempts, each with its transcript, recording and extracted data. - [Find which phone numbers are on the do-not-call list](https://www.getrevox.com/docs/api/calls/find-which-phone-numbers-are-on-the-do-not-call-list.md): `POST /calls/screen-do-not-call`. Returns the subset of the submitted numbers that must not be called. - [Search calls](https://www.getrevox.com/docs/api/calls/search-calls.md): `POST /call/search`. Search your organization's calls, most recent activity first by default. - [Get a link to listen to a live call and jump in](https://www.getrevox.com/docs/api/calls/get-a-link-to-listen-to-a-live-call-and-jump-in.md): `POST /call/{id}/live-link`. Returns a short-lived web page URL for one call that is ringing or on the line. - [Export calls history](https://www.getrevox.com/docs/api/calls/export-calls-history.md): `POST /call/export`. Export calls as a CSV file, one line per call, selected with the filters of [`POST /call/search`](https://www.getrevox.com/docs/api/calls/search-calls.md). - [Pause a call](https://www.getrevox.com/docs/api/calls/pause-a-call.md): `POST /call/{id}/pause`. Pause a call waiting for its next attempt (status scheduled or initializing): nothing is dialed until [`POST /call/{id}/resume`](https://www.getrevox.com/docs/api/calls/resume-a-paused-call.md). - [Resume a paused call](https://www.getrevox.com/docs/api/calls/resume-a-paused-call.md): `POST /call/{id}/resume`. Resume a previously paused call. - [Cancel a call](https://www.getrevox.com/docs/api/calls/cancel-a-call.md): `POST /call/{id}/cancel`. Stop a call's future attempts. - [Get phone number history across the organization](https://www.getrevox.com/docs/api/calls/get-phone-number-history-across-the-organization.md): `GET /calls/phone-history`. Returns a map of phone numbers to the number of calls and associated campaigns across the entire organization. - [The Call object](https://www.getrevox.com/docs/api/objects/call.md): One order to call one phone number with an assistant. - [The CallAttempt object](https://www.getrevox.com/docs/api/objects/call-attempt.md): One dial of a call's phone number, with what answered, the transcript, the recording and the extracted data. - [The CallRetryConfigOverride object](https://www.getrevox.com/docs/api/objects/call-retry-config-override.md): Retry settings for this call only, over the assistant's call_retry_config (or the campaign's, when the call names a campaign). #### Assistants An assistant is the voice agent that places and answers calls: its prompt, voice, first sentence and LLM, the data it extracts after each call, its tools and the calendars it books meetings on. - [Create an assistant](https://www.getrevox.com/docs/api/assistants/create-an-assistant.md): `POST /assistants`. Create a voice agent: the prompt the LLM follows, how it opens the call, its voice (Cartesia, ElevenLabs and Gradium), the data to extract after each call and where to post the result. - [Get assistant by ID](https://www.getrevox.com/docs/api/assistants/get-assistant-by-id.md): `GET /assistants/{id}`. Retrieve a single assistant by its unique ID. - [Get assistants](https://www.getrevox.com/docs/api/assistants/get-assistants.md): `GET /assistants`. Retrieve all assistants associated with your account. - [Check an assistant's setup](https://www.getrevox.com/docs/api/assistants/check-an-assistants-setup.md): `POST /assistants/{id}/setup-check`. Check a saved assistant for the setup mistakes that break real calls: a persona whose gender doesn't match the voice, a prompt that transfers or books with no transfer destination or calendar connected, template text left in, the wrong language, wording that reads wrong once variables are filled. - [Update an assistant](https://www.getrevox.com/docs/api/assistants/update-an-assistant.md): `PATCH /assistants/{id}`. Update one or more fields of an assistant: only the fields you send change. - [Delete an assistant](https://www.getrevox.com/docs/api/assistants/delete-an-assistant.md): `DELETE /assistants/{id}`. Permanently delete an assistant by its ID. - [Clone an assistant](https://www.getrevox.com/docs/api/assistants/clone-an-assistant.md): `POST /assistants/{id}/clone`. Create a copy of an assistant with its whole configuration and its calendars (on the same connected accounts), named after it with " (Copy)" appended. - [Turn the public demo page on or off](https://www.getrevox.com/docs/api/assistants/turn-the-public-demo-page-on-or-off.md): `POST /assistants/{id}/demo-page`. The demo page lets anyone with its link call the assistant and see the calls it placed, with their transcripts and recordings. - [Get assistant statistics](https://www.getrevox.com/docs/api/assistants/get-assistant-statistics.md): `GET /assistants/{id}/statistics`. Report on the inbound calls the assistant received, whatever their status: the total, the weekly volume over the last 12 weeks and the weekly average since the assistant went into service, the weekday and hour they arrive, and how long the answered ones lasted. - [Add a calendar to an assistant](https://www.getrevox.com/docs/api/assistants/add-a-calendar-to-an-assistant.md): `POST /assistants/{id}/calendars`. Add a calendar on a provider, before any account is connected to it. - [Create an invite link for a calendar](https://www.getrevox.com/docs/api/assistants/create-an-invite-link-for-a-calendar.md): `POST /assistants/{id}/calendars/{calendarId}/invite`. A link for the owner of an account to connect it to the calendar, on the calendar's provider, without a Revox account: give them invite.url. - [List an assistant's calendars](https://www.getrevox.com/docs/api/assistants/list-an-assistants-calendars.md): `GET /assistants/{id}/calendars`. The calendars the assistant books meetings on during a call, in the order they were added. - [List what a calendar can book on](https://www.getrevox.com/docs/api/assistants/list-what-a-calendar-can-book-on.md): `GET /assistants/{id}/calendars/{calendarId}/options`. The calendars (Google) or event types (Calendly, Cal.com) of the account connected to the calendar, to pick the one it books on with PUT .../selection. - [Change a calendar's settings](https://www.getrevox.com/docs/api/assistants/change-a-calendars-settings.md): `PATCH /assistants/{id}/calendars/{calendarId}`. The settings of its provider: opening hours, meeting length and Meet link for Google Calendar, the event type for Calendly and Cal.com. - [Connect an account to a calendar](https://www.getrevox.com/docs/api/assistants/connect-an-account-to-a-calendar.md): `PUT /assistants/{id}/calendars/{calendarId}/connection`. Connect the calendar to an account your organization already uses on its provider. - [Remove a calendar from an assistant](https://www.getrevox.com/docs/api/assistants/remove-a-calendar-from-an-assistant.md): `DELETE /assistants/{id}/calendars/{calendarId}`. The agent stops booking on it. - [Disconnect a calendar's account](https://www.getrevox.com/docs/api/assistants/disconnect-a-calendars-account.md): `DELETE /assistants/{id}/calendars/{calendarId}/connection`. The calendar keeps its handle, which the agent then treats as not available, and waits for an account. - [Revoke a calendar's invite link](https://www.getrevox.com/docs/api/assistants/revoke-a-calendars-invite-link.md): `DELETE /assistants/{id}/calendars/{calendarId}/invite`. The calendar's invite link stops working right away, and its `invite` becomes null. - [Pick what a calendar books on](https://www.getrevox.com/docs/api/assistants/pick-what-a-calendar-books-on.md): `PUT /assistants/{id}/calendars/{calendarId}/selection`. Set the calendar (Google) or event type (Calendly, Cal.com) of the connected account the calendar books on, with an id from GET .../options. - [List an assistant's pronunciations](https://www.getrevox.com/docs/api/assistants/list-an-assistants-pronunciations.md): `GET /assistants/{id}/pronunciations`. The words the assistant's voice must say a specific way, with the text sent to the voice in their place. - [Set how the voice says a word](https://www.getrevox.com/docs/api/assistants/set-how-the-voice-says-a-word.md): `PUT /assistants/{id}/pronunciations`. Stores the version of a word the user chose by ear. - [Remove a pronunciation](https://www.getrevox.com/docs/api/assistants/remove-a-pronunciation.md): `DELETE /assistants/{id}/pronunciations/{pronunciationId}`. The voice says the word as written again. - [Suggest versions of a word to choose by ear](https://www.getrevox.com/docs/api/assistants/suggest-versions-of-a-word-to-choose-by-ear.md): `POST /assistants/{id}/pronunciations/suggest`. Hears how the word must sound (a recording of someone saying it, or `sounds_like`), writes up to five ways to spell it for the assistant's voice, the word as written first, and returns each one said by that voice in `sentence`. - [Hear the voice say a word or one of its versions](https://www.getrevox.com/docs/api/assistants/hear-the-voice-say-a-word-or-one-of-its-versions.md): `POST /assistants/{id}/pronunciations/say`. Returns the assistant's voice saying `text` exactly as sent, without applying any of its pronunciations: the word as written is how callers hear it before one is set. - [The Assistant object](https://www.getrevox.com/docs/api/objects/assistant.md): The voice agent that places and answers calls: its prompt, voice and LLM, how it opens and ends a call, the data it extracts, and the tools and calendars it uses. - [The AssistantCalendar object](https://www.getrevox.com/docs/api/objects/assistant-calendar.md): A calendar an assistant books meetings on during calls: one provider, one connected account, and the calendar or event type of that account it books on. - [The AssistantSetupIssue object](https://www.getrevox.com/docs/api/objects/assistant-setup-issue.md): A setup mistake found by [`POST /assistants/{id}/setup-check`](https://www.getrevox.com/docs/api/assistants/check-an-assistants-setup.md), with the edit that fixes it when one is known. - [The CallRetryConfig object](https://www.getrevox.com/docs/api/objects/call-retry-config.md): When and how often a call is dialed: the calling windows and allowed days, the delay between two attempts and the maximum number of attempts. - [The StructuredOutputField object](https://www.getrevox.com/docs/api/objects/structured-output-field.md): One value to extract from a call (an entry of an assistant's structured_output_config), or one parameter of a custom tool (an entry of its input_schema). #### Campaigns A campaign calls a list of contacts with one assistant: Revox paces the calls, retries them inside the calling windows and keeps the campaign's statistics. - [Create a campaign](https://www.getrevox.com/docs/api/campaigns/create-a-campaign.md): `POST /campaigns`. Create an outbound calling campaign. - [Get campaign by ID](https://www.getrevox.com/docs/api/campaigns/get-campaign-by-id.md): `GET /campaigns/{id}`. Retrieve the full details of a single campaign by its unique ID. - [List campaigns](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md): `GET /campaigns`. Retrieve all campaigns for your organization, including both active and completed ones. - [Update a campaign](https://www.getrevox.com/docs/api/campaigns/update-a-campaign.md): `PATCH /campaigns/{id}`. Update a campaign's name, outbound number, retry configuration (calling hours, retry delay, max attempts) and concurrency cap. - [Delete a campaign](https://www.getrevox.com/docs/api/campaigns/delete-a-campaign.md): `DELETE /campaigns/{id}`. Permanently delete a campaign and all its associated rows. - [Launch a campaign's calls](https://www.getrevox.com/docs/api/campaigns/launch-a-campaigns-calls.md): `POST /campaigns/{id}/launch-calls`. Send the campaign's calls matching a selection. - [Cancel a campaign](https://www.getrevox.com/docs/api/campaigns/cancel-a-campaign.md): `POST /campaigns/{id}/cancel`. Cancel a running or scheduled campaign. - [Pause a running campaign](https://www.getrevox.com/docs/api/campaigns/pause-a-running-campaign.md): `POST /campaigns/{id}/pause`. Pause a running campaign so no further calls are placed. - [Resume a paused campaign](https://www.getrevox.com/docs/api/campaigns/resume-a-paused-campaign.md): `POST /campaigns/{id}/resume`. Resume a paused campaign. - [Export campaign rows](https://www.getrevox.com/docs/api/campaigns/export-campaign-rows.md): `GET /campaigns/{id}/export`. Export all rows of a campaign as a CSV file for offline analysis or reporting. - [Get campaign statistics](https://www.getrevox.com/docs/api/campaigns/get-campaign-statistics.md): `GET /campaigns/{id}/statistics`. Campaign report: a four-step funnel (contacts called, reached, real conversations, hot leads), the calling effort, inbound calls, the calls your team joined live, the outcome breakdown and the hot leads to follow up. - [Add contacts to a campaign](https://www.getrevox.com/docs/api/campaigns/add-contacts-to-a-campaign.md): `POST /campaigns/{id}/rows`. Append contacts to an existing campaign. - [Get campaign rows](https://www.getrevox.com/docs/api/campaigns/get-campaign-rows.md): `GET /campaigns/{id}/rows`. Retrieve all contact rows for a campaign. - [The Campaign object](https://www.getrevox.com/docs/api/objects/campaign.md): A list of contacts called by one assistant, with its calling windows, retries and concurrency cap, and where its contacts stand. #### Voices The voices an assistant can speak with: preset voices from Cartesia, ElevenLabs and Gradium, plus the voices you cloned. A voice's language is the language of the calls made with it. - [Get voice by ID](https://www.getrevox.com/docs/api/voices/get-voice-by-id.md): `GET /voices/{id}`. Retrieve details for a single voice by its unique ID and provider. - [Get voices](https://www.getrevox.com/docs/api/voices/get-voices.md): `GET /voices`. Retrieve all voices available for AI calls: the preset voices from Cartesia, ElevenLabs and Gradium, and your organization's cloned voices. - [Delete a voice](https://www.getrevox.com/docs/api/voices/delete-a-voice.md): `DELETE /voices/{id}`. Delete a cloned voice. - [Generate voice preview](https://www.getrevox.com/docs/api/voices/generate-voice-preview.md): `POST /voices/preview`. Generate a short audio sample of a voice. - [Clone a voice](https://www.getrevox.com/docs/api/voices/clone-a-voice.md): `POST /voices/clone`. Clone a voice from an audio recording. - [The Voice object](https://www.getrevox.com/docs/api/objects/voice.md): A voice an assistant can speak with: a preset voice of its provider, or a voice your organization cloned. #### Phone Numbers Your organization's phone numbers: the caller ID of outbound calls, and the assistant that answers inbound calls on each number. - [Get phone numbers](https://www.getrevox.com/docs/api/phone-numbers/get-phone-numbers.md): `GET /phone-numbers`. List the phone numbers of your organization: the numbers calls can be placed from (from_phone_number) and received on, with the assistant that answers each one's inbound calls and its spam reputation. - [Update a phone number](https://www.getrevox.com/docs/api/phone-numbers/update-a-phone-number.md): `PATCH /phone-numbers/{id}`. Rename a phone number, or choose which assistant answers its inbound calls. - [Delete a phone number](https://www.getrevox.com/docs/api/phone-numbers/delete-a-phone-number.md): `DELETE /phone-numbers/{id}`. Remove a phone number from your organization: no call can be placed from it or received on it through Revox anymore. - [The PhoneNumber object](https://www.getrevox.com/docs/api/objects/phone-number.md): A phone number of your organization: a caller ID for outbound calls and, for an owned number, a line whose inbound calls an assistant can answer. #### Users The user the API key belongs to. - [Get the current user](https://www.getrevox.com/docs/api/users/get-the-current-user.md): `GET /users/me`. Get the user the API key or session belongs to, with their organization ID. - [The User object](https://www.getrevox.com/docs/api/objects/user.md): The current authenticated user. - [The OrgMember object](https://www.getrevox.com/docs/api/objects/org-member.md): A member of the current organization. #### Usage What your organization consumed: credits (1 credit = 1 worked contact), calls and time on the line, over any period and per assistant and campaign, with the balance and the date it runs out at the recent pace. - [Get credit and call usage](https://www.getrevox.com/docs/api/usage/get-credit-and-call-usage.md): `GET /usage`. Credits used, calls placed, calls answered and time on the line over a period, point by point and per assistant and campaign, compared with the period just before. - [The Usage object](https://www.getrevox.com/docs/api/objects/usage.md) --- ## Webhooks When an assistant has a `webhook_url`, Revox sends an HTTP `POST` with a JSON body to that URL after its calls. Set it with [Create an assistant](https://www.getrevox.com/docs/api/assistants/create-an-assistant.md) or [Update an assistant](https://www.getrevox.com/docs/api/assistants/update-an-assistant.md). Inbound calls send it too, to the `webhook_url` of the assistant that answers. When a prospect calls back after an outbound call (within 2 days on a shared Revox number, 30 days on a number dedicated to your organization), the inbound `call` has `callback_from` set to that outbound call and carries its `metadata`, so you can tie it back to your own records. - **When**: Revox POSTs the call to the assistant's webhook_url once, when the call reaches its final status (completed or errored), after the post-call analysis. Not after each attempt, and not when the call is cancelled. - **Request**: POST, `Content-Type: application/json`, body `{ call, assistant }`. - **Multi-step assistants**: One request per step the call went through whose assistant has a `webhook_url`, each with its own `assistant`. - **Test calls**: Calls tested from the dashboard send it too: their `call.channel` is `web`. - **Retries**: None when your endpoint answers with an error status. A network error, or no answer within the 3 minutes that also cover Revox's own processing, is retried, so the same call can arrive twice: answer within seconds, and deduplicate on `call.id` and `assistant.id`. - **Signature**: Requests are not signed: put a secret token in the URL (`?token=…`) and check it, or fetch the call again with `GET /call/{id}` before acting on it. ### Example payload ```json { "call": { "id": "8d2f6b1a-4c9e-4f37-b215-6a0e9c3d7f12", "organization_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "from_phone_number": "+33199001234", "to_phone_number": "+33612345678", "direction": "outbound", "channel": "phone", "status": "completed", "is_completed": true, "is_cancelled": false, "cancel_reason": null, "retries_stopped": false, "callback_from": null, "calls_count": 1, "last_call_attempt": { "id": "c41f9a2e-7d3b-4e85-a6f0-1b2c3d4e5f60", "phone_number": "+33612345678", "status": "completed", "dial_error": null, "result": "human", "recording_url": "https://recordings.example.com/7c9e6679-7425-40de-944b-e07fc1f90ae7.wav", "started_at": "2026-11-09T08:30:02Z", "answered_at": "2026-11-09T08:30:09Z", "ended_at": "2026-11-09T08:31:47Z", "transcript": [ { "role": "assistant", "content": "Bonjour Marie, ici Julie du cabinet Acme. Je vous appelle pour confirmer votre rendez-vous de jeudi à 10 heures." }, { "role": "user", "content": "Oui, c'est bien noté, merci." } ], "post_call_transcript": [ { "role": "assistant", "content": "Bonjour Marie, ici Julie du cabinet Acme. Je vous appelle pour confirmer votre rendez-vous de jeudi à 10 heures." }, { "role": "user", "content": "Oui, c'est bien noté, merci." } ], "structured_output": { "appointment_confirmed": true, "preferred_callback_time": null }, "assistants_used": [ "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "b7e2d4c9-1a3f-4e6b-8d5c-2f9a0c7e1b43" ], "assistant_names": { "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34": "Reception", "b7e2d4c9-1a3f-4e6b-8d5c-2f9a0c7e1b43": "Appointment booking" }, "ended_by": "agent", "end_reason": "tool_end_call", "transferred_to": null, "handled_by_human": false, "handled_by_ai": true, "handled_by_user": null, "sms_log": [ { "id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "type": "in_call", "to_phone_number": "+33612345678", "message_body": "Votre rendez-vous du jeudi 12 novembre à 10h au cabinet dentaire Acme est confirmé.", "provider": "twilio", "provider_message_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "provider_status": "delivered", "provider_error_code": null, "created_at": "2026-11-05T09:00:00Z" } ], "actions": [ { "id": "d4c3b2a1-9e8f-4a7b-8c6d-5e4f3a2b1c0d", "phase": "in_call", "tool_name": "send_sms", "arguments": { "message": "Votre rendez-vous du jeudi 12 novembre à 10h au cabinet dentaire Acme est confirmé." }, "status": "succeeded", "error": null, "created_at": "2026-11-05T09:00:00Z" } ], "email_log": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "from_address": "Appointment reminders ", "to_emails": ["jane@example.com"], "subject": "Your appointment tomorrow", "resend_message_id": "d4c3b2a1-9e8f-4a7b-8c6d-5e4f3a2b1c0d", "calendar_invite_at": "2026-11-05T09:00:00Z", "created_at": "2026-11-05T09:00:00Z" } ] }, "call_retry_config": { "calling_windows": [ { "calling_window_start_time": "09:00", "calling_window_end_time": "18:00", "retry_delay_seconds": 7200 } ], "max_retry_attempts": 1, "allowed_days": [ "monday", "tuesday", "wednesday", "thursday", "friday" ], "excluded_dates": ["2026-11-05"], "call_twice_in_a_row": false }, "llm_model": { "type": "recommended" }, "call_attempts": [ { "id": "c41f9a2e-7d3b-4e85-a6f0-1b2c3d4e5f60", "phone_number": "+33612345678", "status": "completed", "dial_error": null, "result": "human", "recording_url": "https://recordings.example.com/7c9e6679-7425-40de-944b-e07fc1f90ae7.wav", "started_at": "2026-11-09T08:30:02Z", "answered_at": "2026-11-09T08:30:09Z", "ended_at": "2026-11-09T08:31:47Z", "transcript": [ { "role": "assistant", "content": "Bonjour Marie, ici Julie du cabinet Acme. Je vous appelle pour confirmer votre rendez-vous de jeudi à 10 heures." }, { "role": "user", "content": "Oui, c'est bien noté, merci." } ], "post_call_transcript": [ { "role": "assistant", "content": "Bonjour Marie, ici Julie du cabinet Acme. Je vous appelle pour confirmer votre rendez-vous de jeudi à 10 heures." }, { "role": "user", "content": "Oui, c'est bien noté, merci." } ], "structured_output": { "appointment_confirmed": true, "preferred_callback_time": null }, "assistants_used": [ "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "b7e2d4c9-1a3f-4e6b-8d5c-2f9a0c7e1b43" ], "assistant_names": { "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34": "Reception", "b7e2d4c9-1a3f-4e6b-8d5c-2f9a0c7e1b43": "Appointment booking" }, "ended_by": "agent", "end_reason": "tool_end_call", "transferred_to": null, "handled_by_human": false, "handled_by_ai": true, "handled_by_user": null, "sms_log": [ { "id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "type": "in_call", "to_phone_number": "+33612345678", "message_body": "Votre rendez-vous du jeudi 12 novembre à 10h au cabinet dentaire Acme est confirmé.", "provider": "twilio", "provider_message_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "provider_status": "delivered", "provider_error_code": null, "created_at": "2026-11-05T09:00:00Z" } ], "actions": [ { "id": "d4c3b2a1-9e8f-4a7b-8c6d-5e4f3a2b1c0d", "phase": "in_call", "tool_name": "send_sms", "arguments": { "message": "Votre rendez-vous du jeudi 12 novembre à 10h au cabinet dentaire Acme est confirmé." }, "status": "succeeded", "error": null, "created_at": "2026-11-05T09:00:00Z" } ], "email_log": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "from_address": "Appointment reminders ", "to_emails": ["jane@example.com"], "subject": "Your appointment tomorrow", "resend_message_id": "d4c3b2a1-9e8f-4a7b-8c6d-5e4f3a2b1c0d", "calendar_invite_at": "2026-11-05T09:00:00Z", "created_at": "2026-11-05T09:00:00Z" } ] } ], "assistant": { "id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "prompt": "You are Julie from Acme. You call {{first_name}} to confirm tomorrow's appointment.", "post_call_prompt": "Send the appointment address by SMS if asked.", "first_sentence": "Hello {{first_name}}, this is Julie from Acme.", "first_sentence_mode": "generated", "end_of_call_sentence": "Thank you, have a good day.", "voice": { "provider": "cartesia", "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6", "speed": 1, "volume": 1, "model": "sonic-3" }, "voice_languages": [ { "language": "en", "voice": { "provider": "cartesia", "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6", "speed": 1, "volume": 1, "model": "sonic-3" } } ], "cartesia_dictionary_pronunciation_id": "6f9a3c1e-2b7d-4e58-9a10-3d2c4b5e6f70", "llm_model": { "type": "recommended" }, "webhook_url": "https://example.com/revox-webhook", "max_call_duration_secs": 600, "max_duration_end_message": "Thank you, have a good day.", "structured_output_config": [ { "name": "budget", "type": "string", "description": "Books a slot in the agenda.", "required": false, "enum_options": ["enum option"] } ], "structured_output_prompt": "Send the appointment address by SMS if asked.", "call_retry_config": { "calling_windows": [ { "calling_window_start_time": "09:00", "calling_window_end_time": "18:00", "retry_delay_seconds": 7200 } ], "max_retry_attempts": 1, "allowed_days": [ "monday", "tuesday", "wednesday", "thursday", "friday" ], "excluded_dates": ["2026-11-05"], "call_twice_in_a_row": false }, "timezone": "Europe/Paris", "background_sound": "audio/office.ogg", "background_sound_volume": 1, "thinking_sound": "city-ambience.ogg", "thinking_sound_volume": 1, "thinking_sound_probability": 0, "transfer_destinations": [ { "label": "Main line", "phone_number": "+33612345678" } ], "human_transfer_mode": "warm", "warm_transfer_summary_instructions": "Send the appointment address by SMS if asked.", "warm_transfer_voice_speed": 1, "ivr_navigation_enabled": true, "voicemail_message": "Thank you, have a good day.", "stt_context": { "general": [{ "key": "crm_id", "value": "lead_8812" }], "terms": ["term"] }, "stt_model": "stt-rt-v4", "first_sentence_delay_ms": 400, "calendars": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "assistant_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "handle": "google_calendar_jane_at_example.com", "provider": "google-calendar", "status": "ready", "connection": { "provider": "google-calendar", "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "settings": { "calendar_id": "primary", "time_zone": "Europe/Paris", "duration_minutes": 30, "days": [1, 2, 3, 4, 5], "start_time": "09:00", "end_time": "18:00", "google_meet": false, "location": "{{site_address}}" } }, "account_label": "Main line", "connected_via_invite": false, "invite": { "url": "https://example.com", "status": "completed", "created_at": "2026-11-05T09:00:00Z", "expires_at": "2026-11-05T09:00:00Z" }, "created_at": "2026-11-05T09:00:00Z" } ], "calendly": null, "cal": null, "google_calendar": null, "hubspot": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "precall_lookup_enabled": true, "meeting_links": [ { "slug": "jane-martin", "label": "Main line", "duration_ms": 1800000, "is_fallback": false, "booking_url": "https://example.com" } ], "post_call_sync": { "enabled": true, "field_mapping": [ { "source": "email", "hubspot_property": "email" } ] } }, "slack": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "channels": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "name": "Appointment reminder" } ] }, "teams": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "channels": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "name": "Appointment reminder", "team_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "team_name": "Sales" } ] }, "zoho": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "module": "Leads", "log_call_activity": false, "field_mapping": [ { "source": "email", "zoho_field": "Email" } ], "template": "{{outcome}}: {{summary}}\n{{call_url}}" }, "custom_tools": [ { "name": "appointment_reminder", "description": "Books a slot in the agenda.", "method": "GET", "url": "https://example.com", "headers": [{ "key": "crm_id", "value": "lead_8812" }], "query_params": [ { "key": "crm_id", "value": "lead_8812" } ], "body_template": "{\"email\": \"{{email}}\", \"name\": \"{{first_name}}\"}", "input_schema": [ { "name": "budget", "type": "string", "description": "Books a slot in the agenda.", "required": false, "enum_options": ["enum option"] } ] } ], "from_phone_number": "+33187654321", "demo_page_url": "https://example.com", "precall_lookup_url": "https://example.com", "precall_lookup_headers": [ { "key": "crm_id", "value": "lead_8812" } ], "organization_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "name": "Appointment reminders", "is_inbound_receptionist": false, "created_by": { "id": "5a7c9e1b-3d5f-4a2c-8e6b-0f1a2b3c4d5e", "email": "jane@example.com", "first_name": "Marie", "last_name": "Martin" }, "created_at": "2026-11-05T09:00:00Z", "updated_at": "2026-11-05T09:02:41Z" }, "prompt_version": { "id": "6f9a3c1e-2b7d-4e58-9a10-3d2c4b5e6f70", "number": 1, "latest_number": 1 }, "campaign": { "id": "8e1f2a3b-4c5d-4e6f-9a0b-1c2d3e4f5a6b", "name": "Appointment reminder", "status": "completed" }, "scheduled_at": "2026-11-09T08:30:00Z", "created_at": "2026-11-06T16:12:45Z", "updated_at": "2026-11-09T08:32:20Z", "metadata": { "crm_id": "lead_48213" }, "prompt_variables": { "first_name": "Marie", "company": "Acme" }, "transfer_destinations": [ { "label": "Main line", "phone_number": "+33612345678" } ], "contact": { "first_name": "Marie", "last_name": "Martin", "email": "jane@example.com", "company": "Acme", "job_title": "Office manager" }, "first_sentence_delay_ms": 400, "outcome": "interested", "outcome_summary": "Marie confirmed her appointment on Thursday at 10:00 and asked for the address by text message.", "do_not_call": false, "assignee": { "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "email": "jane@example.com", "first_name": "Marie", "last_name": "Martin" } }, "assistant": { "id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "prompt": "You are Julie from Acme. You call {{first_name}} to confirm tomorrow's appointment.", "post_call_prompt": "Send the appointment address by SMS if asked.", "first_sentence": "Hello {{first_name}}, this is Julie from Acme.", "first_sentence_mode": "generated", "end_of_call_sentence": "Thank you, have a good day.", "voice": { "provider": "cartesia", "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6", "speed": 1, "volume": 1, "model": "sonic-3" }, "voice_languages": [ { "language": "en", "voice": { "provider": "cartesia", "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6", "speed": 1, "volume": 1, "model": "sonic-3" } } ], "cartesia_dictionary_pronunciation_id": "6f9a3c1e-2b7d-4e58-9a10-3d2c4b5e6f70", "llm_model": { "type": "recommended" }, "webhook_url": "https://example.com/revox-webhook", "max_call_duration_secs": 600, "max_duration_end_message": "Thank you, have a good day.", "structured_output_config": [ { "name": "budget", "type": "string", "description": "Books a slot in the agenda.", "required": false, "enum_options": ["enum option"] } ], "structured_output_prompt": "Send the appointment address by SMS if asked.", "call_retry_config": { "calling_windows": [ { "calling_window_start_time": "09:00", "calling_window_end_time": "18:00", "retry_delay_seconds": 7200 } ], "max_retry_attempts": 1, "allowed_days": [ "monday", "tuesday", "wednesday", "thursday", "friday" ], "excluded_dates": ["2026-11-05"], "call_twice_in_a_row": false }, "timezone": "Europe/Paris", "background_sound": "audio/office.ogg", "background_sound_volume": 1, "thinking_sound": "city-ambience.ogg", "thinking_sound_volume": 1, "thinking_sound_probability": 0, "transfer_destinations": [ { "label": "Main line", "phone_number": "+33612345678" } ], "human_transfer_mode": "warm", "warm_transfer_summary_instructions": "Send the appointment address by SMS if asked.", "warm_transfer_voice_speed": 1, "ivr_navigation_enabled": true, "voicemail_message": "Thank you, have a good day.", "stt_context": { "general": [{ "key": "crm_id", "value": "lead_8812" }], "terms": ["term"] }, "stt_model": "stt-rt-v4", "first_sentence_delay_ms": 400, "calendars": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "assistant_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "handle": "google_calendar_jane_at_example.com", "provider": "google-calendar", "status": "ready", "connection": { "provider": "google-calendar", "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "settings": { "calendar_id": "primary", "time_zone": "Europe/Paris", "duration_minutes": 30, "days": [1, 2, 3, 4, 5], "start_time": "09:00", "end_time": "18:00", "google_meet": false, "location": "{{site_address}}" } }, "account_label": "Main line", "connected_via_invite": false, "invite": { "url": "https://example.com", "status": "completed", "created_at": "2026-11-05T09:00:00Z", "expires_at": "2026-11-05T09:00:00Z" }, "created_at": "2026-11-05T09:00:00Z" } ], "calendly": null, "cal": null, "google_calendar": null, "hubspot": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "precall_lookup_enabled": true, "meeting_links": [ { "slug": "jane-martin", "label": "Main line", "duration_ms": 1800000, "is_fallback": false, "booking_url": "https://example.com" } ], "post_call_sync": { "enabled": true, "field_mapping": [ { "source": "email", "hubspot_property": "email" } ] } }, "slack": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "channels": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "name": "Appointment reminder" } ] }, "teams": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "channels": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "name": "Appointment reminder", "team_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "team_name": "Sales" } ] }, "zoho": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "module": "Leads", "log_call_activity": false, "field_mapping": [ { "source": "email", "zoho_field": "Email" } ], "template": "{{outcome}}: {{summary}}\n{{call_url}}" }, "custom_tools": [ { "name": "appointment_reminder", "description": "Books a slot in the agenda.", "method": "GET", "url": "https://example.com", "headers": [{ "key": "crm_id", "value": "lead_8812" }], "query_params": [ { "key": "crm_id", "value": "lead_8812" } ], "body_template": "{\"email\": \"{{email}}\", \"name\": \"{{first_name}}\"}", "input_schema": [ { "name": "budget", "type": "string", "description": "Books a slot in the agenda.", "required": false, "enum_options": ["enum option"] } ] } ], "from_phone_number": "+33187654321", "demo_page_url": "https://example.com", "precall_lookup_url": "https://example.com", "precall_lookup_headers": [ { "key": "crm_id", "value": "lead_8812" } ], "organization_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "name": "Appointment reminders", "is_inbound_receptionist": false, "created_by": { "id": "5a7c9e1b-3d5f-4a2c-8e6b-0f1a2b3c4d5e", "email": "jane@example.com", "first_name": "Marie", "last_name": "Martin" }, "created_at": "2026-11-05T09:00:00Z", "updated_at": "2026-11-05T09:02:41Z" } } ``` ### Payload fields - `call` ([Call](https://www.getrevox.com/docs/api/objects/call.md)): The call, as [`GET /call/{id}`](https://www.getrevox.com/docs/api/calls/get-call-by-id.md) returns it. Its latest attempt, with the transcript, recording and extracted data, is call.last_call_attempt. - `assistant` ([Assistant](https://www.getrevox.com/docs/api/objects/assistant.md) | null): The assistant whose webhook_url receives the request, as [`GET /assistants/{id}`](https://www.getrevox.com/docs/api/assistants/get-assistant-by-id.md) returns it: the call's assistant, or the step of a multi-step flow. Null for a call placed with an inline assistant. --- ## MCP server Revox runs an MCP server (Model Context Protocol) that exposes this API as tools. Connect Claude, ChatGPT, Cursor, Codex or any MCP client to it and ask in plain words: create an assistant, pick its voice, connect a calendar, place a test call. ### Server URL ``` https://www.getrevox.com/api/mcp-servers/generic/mcp ``` Streamable HTTP. Claude Code: `claude mcp add --transport http revox https://www.getrevox.com/api/mcp-servers/generic/mcp`. ### Authentication - **OAuth**: clients that support it (Claude, ChatGPT, Cursor) open a Revox sign-in window the first time. Nothing to configure. - **API key**: send `Authorization: Bearer YOUR_API_KEY`, the same key as the REST API. - If you belong to several organizations, use the organization's own URL, shown in the dashboard on the [MCP page](https://www.getrevox.com/dashboard?goto=mcp). ### How the tools work together The server sends these instructions to the client when it connects: > Revox places AI phone calls and manages the voice assistants that make them. > > Before writing or changing an assistant's prompt (revox_create_assistant, or revox_update_assistant with prompt or first_sentence), call revox_get_prompt_guide and follow it: it is Revox's prompt-creation guide for phone conversations (identity and opener, turns, qualification, objections, actions, end of call). Pass its guide_version as prompt_guide_version: those tools refuse a prompt without it. > > After your last change to an assistant, call revox_check_assistant_setup and fix what it reports before handing the assistant over. > > To place a call, use revox_make_call, then revox_wait_for_call to get the outcome, transcript and extracted data. > > You cannot play audio: to choose a voice, call revox_pick_voice and give the user its url, then revox_wait_for_voice_pick. After creating or updating an assistant, give the user its test_url to try it live in the browser. > > You cannot sign in to a calendar account: to add a calendar, call revox_connect_calendar and give the user its url, then revox_wait_for_calendar. revox_list_assistant_tools lists what an assistant's prompts can mention as @name, including its calendars. ### Tools #### Calls - `revox_get_call` (read only): Get a call by ID. Use this to poll for completion after revox_make_call (MCP has no webhooks). Arguments: `id`. - `revox_wait_for_call` (read only): Poll a call until it completes, is cancelled, or the server time window expires (~240 s). If the result contains `_retry: true`, call this tool again with the same id to keep waiting. Arguments: `id`, `poll_interval_secs`. - `revox_make_call`: Place a call. Returns immediately with call id. Provide either assistant_id or prompt (not both). With assistant_id, personalize the call with prompt_variables (the assistant's {{variables}}); the assistant's own config is used and the inline fields (prompt, voice, first sentence, structured output, webhook, custom tools...) are ignored. With prompt, the inline fields configure this one call. Voice is optional: if voice_provider/voice_id are omitted, a voice is auto-selected based on the target phone number's country (e.g. a French number gets a French voice). Use metadata to attach your own ids, from_phone_number to choose the caller ID, scheduled_at to call later. Use call_retry_config to change this call's number of attempts or to skip dates such as public holidays (excluded_dates, with skip_calling_window false). To know when the call is done, use revox_wait_for_call or poll revox_get_call manually: the result carries the outcome, summary, transcript, extracted structured_output and the tools the agent ran. Arguments: `phone_number`, `prompt_variables`, `metadata`, `from_phone_number`, `scheduled_at`, `concurrency`, `skip_calling_window`, `timezone`, `call_retry_config`, `assistant_id`, `prompt`, `voice_provider`, `voice_id`, `voice_volume`, `first_sentence`, `first_sentence_mode`, `end_of_call_sentence`, `voicemail_message`, `max_call_duration_secs`, `structured_output_config`, `structured_output_prompt`, `webhook_url`, `custom_tools`, `post_call_prompt`, `transfer_destinations`, `human_transfer_mode`, `warm_transfer_summary_instructions`, `warm_transfer_voice_speed`. - `revox_get_calls` (read only): Search/list calls Arguments: `query`, `statuses`, `directions`, `results`, `outcomes`, `assistant_ids`, `campaign_ids`, `from_phone_numbers`, `assignee_ids`, `variables`, `to_phone_number`, `call_ids`, `page`, `page_size`, `sort_by`, `sort_direction`. #### Assistants - `revox_list_assistants` (read only): Get all assistants for the organization. Each comes with its dashboard_url and test_url (opens the page with the web test call ready). - `revox_get_assistant` (read only): Get an assistant by ID, with its dashboard_url and test_url (opens the page with the web test call ready). Arguments: `id`. - `revox_get_prompt_guide` (read only): Revox's prompt-creation guide (in French): the rules for an assistant's prompt on a phone call (identity and opener, personalization with variables, turns, qualification, objections, transfers and bookings, end of call) and the checks before delivering it. You MUST call this before revox_create_assistant, and before revox_update_assistant changes prompt or first_sentence, then write the prompt following it. It returns a guide_version to pass as prompt_guide_version. Pass the paths matching the case to also get their examples. Arguments: `paths`. - `revox_create_assistant`: Create a new assistant. You MUST call revox_get_prompt_guide first and write the prompt following it; pass its guide_version as prompt_guide_version. Set voice_provider and voice_id for a specific accent (e.g. French): let the user choose by ear with revox_pick_voice, or use revox_list_voices and pick a voice whose language matches your prompt. custom_tools are HTTP endpoints the agent can call during the conversation; webhook_url receives each call's report when it ends; precall_lookup_url (inbound calls) is queried before answering to fill the prompt variables. To transfer calls to a human, set transfer_destinations (label + E.164 number each) and human_transfer_mode (warm: the AI briefs the colleague before connecting, the default; cold: direct SIP transfer); the prompt must say when to transfer and, with several destinations, which label to pick. post_call_prompt sets what happens once the call has ended (emails, SMS, Slack or Teams messages, CRM): read its description for how to write it and which tools exist. To text the person during the call instead, write in the prompt when to use @send_sms (only works when the number can receive SMS). For the assistant to book meetings, add its calendars with revox_connect_calendar. revox_list_assistant_tools lists everything its prompts can mention as @name, including those calendars. The result carries the assistant's dashboard_url and test_url: give the user test_url so they can talk to the assistant right away in their browser (web test call). Arguments: `prompt_guide_version`, `name`, `prompt`, `timezone`, `first_sentence`, `first_sentence_mode`, `end_of_call_sentence`, `voicemail_message`, `max_call_duration_secs`, `structured_output_config`, `structured_output_prompt`, `webhook_url`, `custom_tools`, `post_call_prompt`, `transfer_destinations`, `human_transfer_mode`, `warm_transfer_summary_instructions`, `warm_transfer_voice_speed`, `precall_lookup_url`, `precall_lookup_headers`, `voice_provider`, `voice_id`, `voice_speed`, `voice_volume`, `voice_model`. - `revox_update_assistant`: Update an assistant by ID. Only the fields you pass change. To change prompt or first_sentence, you MUST call revox_get_prompt_guide first, rework the text following it, and pass its guide_version as prompt_guide_version. Include voice_provider and voice_id to change the voice (e.g. to a French accent). custom_tools replaces the whole list (null removes them all); precall_lookup_url and precall_lookup_headers take null to remove the inbound lookup. To transfer calls to a human, set transfer_destinations (label + E.164 number each) and human_transfer_mode (warm: the AI briefs the colleague before connecting, the default; cold: direct SIP transfer); the prompt must say when to transfer and, with several destinations, which label to pick. transfer_destinations: null removes the transfer. post_call_prompt sets what happens once the call has ended (emails, SMS, Slack or Teams messages, CRM): read its description for how to write it and which tools exist. To text the person during the call instead, write in the prompt when to use @send_sms (only works when the number can receive SMS). For the assistant to book meetings, add its calendars with revox_connect_calendar. revox_list_assistant_tools lists everything its prompts can mention as @name, including those calendars. The result carries the assistant's dashboard_url and test_url: give the user test_url so they can talk to the assistant right away in their browser (web test call). Arguments: `id`, `prompt_guide_version`, `name`, `prompt`, `timezone`, `first_sentence`, `first_sentence_mode`, `end_of_call_sentence`, `voicemail_message`, `max_call_duration_secs`, `structured_output_config`, `structured_output_prompt`, `webhook_url`, `custom_tools`, `post_call_prompt`, `transfer_destinations`, `human_transfer_mode`, `warm_transfer_summary_instructions`, `warm_transfer_voice_speed`, `precall_lookup_url`, `precall_lookup_headers`, `voice_provider`, `voice_id`, `voice_speed`, `voice_volume`, `voice_model`. - `revox_check_assistant_setup` (read only): Check a saved assistant for the setup mistakes that break real calls (persona gender vs voice, transfer or booking with nothing connected, leftover template text, wrong language, wording that reads wrong once variables are filled). Call it once after your last revox_create_assistant or revox_update_assistant, not after each edit: a fresh check takes a few seconds. Apply each issue's fix with revox_update_assistant (a text fix replaces `find` with `replace` in `field`; a voice fix switches to `voice`), then check again. An empty list means nothing major was found. Arguments: `id`, `locale`. - `revox_list_assistant_tools` (read only): Everything an assistant's prompts can name as @name: call_tools for its prompt (the built-in actions, its calendars under their generated handles, its custom tools), post_call_tools for its post_call_prompt. Each has its mention, a description, an example, and whether it is available on this assistant, with the setup it lacks otherwise. A calendar appears once an account is connected to it. Call this before writing a prompt that uses them. Arguments: `assistant_id`. #### Voices - `revox_list_voices` (read only): Get available voices (Cartesia, ElevenLabs and Gradium). - `revox_get_voice` (read only): Get a voice by ID and provider. Arguments: `id`, `provider`. - `revox_pick_voice`: You cannot play audio, so let the user listen and choose: this returns a url to a Revox page where they audition voices and validate one. Give the user the url (ask them to open it and validate a voice), then call revox_wait_for_voice_pick with the pick_id: it returns the voice once validated, as voice_provider, voice_id, voice_speed, voice_volume and voice_model, to pass to revox_create_assistant or revox_update_assistant. Prefer this over choosing from revox_list_voices whenever the user cares about the voice. Arguments: `language`, `purpose`. - `revox_wait_for_voice_pick` (read only): Wait until the user validates a voice on the revox_pick_voice page, or the server time window expires (~240 s). If the result contains `_retry: true`, the user has not chosen yet: call this tool again with the same pick_id (or ask them where they are). Once chosen, it returns immediately with the voice; the user can validate another one on the same page, and calling this again returns the latest. Arguments: `pick_id`. #### Calendars - `revox_list_calendars` (read only): The calendars an assistant books meetings on: their status (not_connected, needs_setup, ready), the mention the prompt uses, the connected account, the settings, and the link to connect them (invite.url) with what to do next. Arguments: `assistant_id`. - `revox_connect_calendar`: You cannot sign in to a calendar account, so the user does: this returns a url to a Revox page where they (or a colleague, no Revox account needed) connect their Google Calendar, Calendly or Cal.com account and pick what to book on. Pass provider to add a new calendar to the assistant, or calendar_id for a new link to one with no account (the previous link stops working). Anyone holding the link can connect an account, so give it only to the person concerned. Give the user the url, then call revox_wait_for_calendar. An assistant can have several calendars: call this once per calendar. Arguments: `assistant_id`, `provider`, `calendar_id`. - `revox_wait_for_calendar` (read only): Wait until the calendar from revox_connect_calendar is ready to take bookings, or the server time window expires (~240 s). If the result contains `_retry: true`, it is not ready yet: follow its next_step, then call this tool again with the same ids (or ask the user where they are). Once ready, it returns the calendar with its mention, the @handle generated from the connected account. Arguments: `assistant_id`, `calendar_id`. - `revox_get_calendar_options` (read only): The calendars (Google) or event types (Calendly, Cal.com) of the connected account, to pass one to revox_select_calendar_option. A notice says when the account's plan will stop bookings: tell the user. An option with bookable false is a Google calendar shared read-only: it cannot be picked, so if it is the one the user wants, tell them to ask its owner for "Make changes to events". Arguments: `assistant_id`, `calendar_id`. - `revox_select_calendar_option`: Pick the calendar or event type of the connected account, with an id from revox_get_calendar_options. Arguments: `assistant_id`, `calendar_id`, `option_id`. - `revox_update_calendar_settings`: Google Calendar: opening hours, meeting length, Meet link and the meeting location (it can use the call's variables, e.g. '{{site_address}}'). Calendly and Cal.com: the event type. Settings replace the current ones as a whole and must match the calendar's provider: start from connection.settings in revox_list_calendars. The calendar must have an account connected. Arguments: `assistant_id`, `calendar_id`, `settings`. - `revox_disconnect_calendar`: The calendar keeps its handle, which the agent treats as not available, and its link is revoked. Use revox_connect_calendar with its calendar_id to connect another account, which gives it that account's handle: update the prompt if it mentions the old one. Ask the user first. Arguments: `assistant_id`, `calendar_id`. - `revox_remove_calendar`: The agent stops booking on it. The account connection is deleted too, unless another calendar still uses it. Update the prompt if it mentions this calendar. Ask the user first. Arguments: `assistant_id`, `calendar_id`. #### Campaigns - `revox_list_campaigns` (read only): Get all campaigns for the organization. #### Account - `revox_auth_status` (read only): Check if the API key is valid. - `revox_create_api_key`: Create a Revox API key for the organization, to configure another tool or service (env var, CI secret, integration). The full key is returned only in this response and no tool can show it again: store it right away where it is needed, do not repeat it to the user unless they ask. The user can revoke it from dashboard_url. Arguments: `name`. - `revox_get_live_call_link` (read only): Get a short-lived web page URL to listen to a call that is ringing or on the line, and take over from the AI to talk to the person (microphone required), or hang up. Give the url to the user to open in their browser: you cannot listen yourself. Fails when the call is not live (queued, between attempts, ended): check its status with revox_get_call. The url is a credential scoped to this one call, so do not store or share it beyond the user. Arguments: `id`, `expires_in_seconds`. - `revox_set_demo_page`: The demo page lets anyone with its link call the assistant and see the calls it placed, with their transcripts and recordings. Off by default. `enabled: true` turns it on with a new link; calling it again regenerates the link and the previous one stops working at once. `enabled: false` turns it off. Arguments: `id`, `enabled`. - `revox_list_pronunciations` (read only): The words the assistant's voice must say a specific way (company, person or place names), chosen by ear in the dashboard: the text sent to the voice in their place, and voice_changed when the assistant's voice changed since. To add or change one, send the user to the prompt editor: select the word, say it, pick the version that sounds right. Arguments: `assistant_id`. - `revox_remove_pronunciation`: The voice says the word as written again. Arguments: `assistant_id`, `pronunciation_id`. - `revox_get_current_user` (read only): Get the authenticated user. - `revox_get_balance` (read only): Get organization balance (in euro cents). - `revox_get_usage` (read only): Credits used (1 credit = 1 worked contact = €0.50 excl. VAT), calls, answered calls and time on the line over a period, point by point and per assistant and campaign, compared with the period just before; plus the credits left and the date they run out at the recent pace. Without arguments: the current month so far. Use it to answer 'how much did we spend', 'which campaign used the most credits' or 'how long will our credits last'. Arguments: `from`, `to`, `granularity`, `timezone`. --- ## Check an API key `GET https://www.getrevox.com/api/auth-status` Check that your API key is valid, e.g. before storing it: a 200 with authenticated true means it is; any other answer means the key was not accepted. ### Request ```bash curl -X GET "https://www.getrevox.com/api/auth-status" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Body No body: send the request without one. ### Response 200 ```json { "authenticated": true } ``` - `authenticated` (boolean): True if the API key is still valid. ### Errors - `401` Missing or invalid API key: `{"error":"Unauthorized, invalid API key"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Place a call `POST https://www.getrevox.com/api/call` Place an outbound call with a saved assistant (assistant_id) or a configuration for this call only (assistant). The call is dialed right away or at scheduled_at, inside the calling windows, and called back when nobody answers, as call_retry_config allows: it can take several days. The response comes back at once with the call; follow it with [`GET /call/{id}`](https://www.getrevox.com/docs/api/calls/get-call-by-id.md) or the assistant's webhook_url. ### Before you call - Send exactly one of `assistant_id` (a saved assistant) and `assistant` (a configuration for this call only). With both, `assistant` is ignored; with neither, the request fails with 400. - `campaign` requires `assistant_id` and cannot be combined with `concurrency`. - Send in `prompt_variables` every `{{variable}}` the assistant's prompt and first sentence use. A missing or empty one is not rejected: the prompt reads `(name: not provided)` in its place, and a static first sentence or voicemail message leaves it out. - `scheduled_at` is UTC and ends in `Z` (`2026-11-09T08:30:00Z`): an offset such as `+01:00` is rejected. Omit it to call right away, or when the next calling window opens. - A time outside the calling windows or allowed days (by default Monday to Friday, 10:00 to 18:00 in the call's timezone) waits for the next window: 9:30 on a Saturday becomes Monday 10:00. To dial at that exact time, also send `skip_calling_window: true` (first dial only; retries follow the windows). - The response comes back at once, before anything is dialed. To get the result, poll [`GET /call/{id}`](https://www.getrevox.com/docs/api/calls/get-call-by-id.md) until `status` is `completed`, `cancelled` or `errored`, or set the assistant's `webhook_url` to receive the call once it is over. With retries, a call can take several days. ### Request #### Example: Saved assistant Calls with the assistant of the Create an assistant example. prompt_variables fill its {{first_name}} and {{appointment_date}}; metadata comes back as sent on the call. ```bash curl -X POST "https://www.getrevox.com/api/call" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone_number": "+33612345678", "assistant_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "prompt_variables": { "first_name": "Marie", "appointment_date": "Thursday, November 12 at 10am" }, "metadata": { "crm_id": "lead_48213" } }' ``` #### Example: Inline assistant A configuration for this call only, nothing saved. The French voice makes it a call in French; the static first sentence is spoken word for word. ```json { "phone_number": "+33612345678", "assistant": { "prompt": "You are Julie, the assistant of the Acme dental practice. You call {{first_name}} to confirm their appointment on {{appointment_date}}. If they cannot come, offer to call them back to set a new date.", "first_sentence": "Bonjour {{first_name}}, ici Julie du cabinet dentaire Acme.", "first_sentence_mode": "static", "voice": { "provider": "cartesia", "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6" } }, "prompt_variables": { "first_name": "Marie", "appointment_date": "jeudi 12 novembre à 10 heures" } } ``` #### Example: Scheduled, grouped in a campaign Dialed on November 9 at 08:30 UTC, and counted in the campaign named in campaign.name, created by the first call that names it. ```json { "phone_number": "+33698765432", "assistant_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "prompt_variables": { "first_name": "Jane", "appointment_date": "Friday, November 13 at 3pm" }, "scheduled_at": "2026-11-09T08:30:00Z", "campaign": { "name": "November reminders" } } ``` ### Body JSON. - `phone_number` (string, required): The phone number to call, in E.164 format (e.g. +33612345678). - `skip_calling_window` (boolean, optional): Bypass the calling-window check for this call's first dial so it dials even outside the assistant's calling windows, allowed days and excluded_dates. Retries, if any, follow them again. Use for immediate 'call now' dials. - `timezone` (string | null, optional): IANA timezone of this call, in place of its campaign's or assistant's timezone. Examples: 'America/Los_Angeles', 'Europe/Paris'. The call runs in exactly this one timezone: its calling windows and allowed days are read in it, the agent tells the date and offers calendar slots in it, and callbacks and extracted datetimes are interpreted in it. Omitted or null: the campaign's timezone, else the assistant's. It is never derived from the phone number. - `from_phone_number` (string, optional): Caller ID of the call, in E.164 format: one of your organization's numbers ([`GET /phone-numbers`](https://www.getrevox.com/docs/api/phone-numbers/get-phone-numbers.md)). Omitted: the assistant's from_phone_number, or else a Revox number chosen for the destination. - `call_twice_in_a_row` (boolean, optional): Double call for this call only, in place of the assistant's call_retry_config.call_twice_in_a_row. True: if the first attempt reaches nobody (no answer, declined, voicemail, call screening nobody took), the second attempt is dialed within seconds, from the same caller number. Each call is an attempt: the double call counts as 2 when both calls happen, so true raises a max_retry_attempts of 1 to 2. Omitted: the assistant's setting. - `call_retry_config` (CallRetryConfigOverride, optional) - `call_retry_config.max_retry_attempts` (integer, optional): Maximum number of call attempts for this call, first call included (1 = a single call, no retry), in place of the assistant's or campaign's max_retry_attempts. Still capped by the organization's plan: 5 on Starter, 8 on Business. Omitted: the assistant's or campaign's value. > 0. - `call_retry_config.excluded_dates` (array of string (date), optional): Calendar dates on which this call must not be placed, such as public holidays, as 'YYYY-MM-DD' (e.g. ['2026-12-25']). Added to the assistant's or campaign's own excluded_dates, never replacing them. Read in the call's timezone (the timezone field, else the assistant's, else the callee's from their number). A first dial or retry that would land on one of these dates waits for the next open window after it. Up to 366 dates. At most 366 items. - `prompt_variables` (object, optional): Values of the assistant's {{variables}} for this call, keyed by variable name, whether the call uses assistant_id or an inline assistant. Send every variable the prompt and first sentence use. A missing or empty one is not rejected: the prompt reads '(name: not provided)' in its place, and a static first sentence leaves it out. Keys: Variable name, as written between the braces: name for {{name}}. - `metadata` (object, optional): Your own key/value pairs to store with the call, e.g. your CRM ID. They come back as sent on the call. Keys: A key of your choice. - `assistant_id` (string (uuid), optional): ID of a saved assistant to place the call with ([`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md)). Send it or assistant, not both. - `assistant` (object, optional): A configuration for this call only, when you do not use a saved assistant. Ignored when assistant_id is sent. Same fields as the body of [Create an assistant](https://www.getrevox.com/docs/api/assistants/create-an-assistant.md) except `name`; required here: `prompt`. - `concurrency` (object, optional): Limit the number of concurrent calls for a given concurrency key. The limit itself is set server-side; omit this to leave the call ungrouped (bounded only by your organization's limit). - `concurrency.key` (string, required): Groups this call with every other call sharing the same key, for concurrency purposes. - `campaign` (object, optional): Group this call under a campaign, to follow its statistics in the dashboard. Nothing to create beforehand: the campaign exists as soon as a call names it, and it uses the assistant of that first call. Requires assistant_id, and cannot be combined with concurrency: the call follows the campaign's own concurrency limit, retry settings and pause. Returns 409 when the campaign was cancelled or uses another assistant. Calling the same number twice in a campaign counts as one contact. - `campaign.name` (string, required): The campaign's name, case-insensitive. Created on first use, reused by every later call that sends it. 1 to 255 characters. - `scheduled_at` (string (date-time), optional): When to place the call: ISO 8601 in UTC ending in Z, e.g. 2026-11-09T08:30:00Z; offsets such as +01:00 are rejected. Omitted: right away, or when the next calling window opens. ### Response 200 - `call` ([Call](https://www.getrevox.com/docs/api/objects/call.md)) ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["phone_number"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `402` Not enough credits on the organization: `{"error":"Insufficient credits. Please buy credits to make calls.","code":"INSUFFICIENT_BALANCE"}` - `404` Not found in your organization: `{"error":"Not found"}` - `409` Conflicts with the resource's current state: `{"error":"Conflicts with the resource's current state"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Get call by ID `GET https://www.getrevox.com/api/call/{id}` Returns a call with its status, outcome and attempts, each with its transcript, recording and extracted data. Poll it after [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md) until status is final: completed, cancelled, errored. ### Before you call - `status` is final once it is `completed`, `cancelled` or `errored`: nothing changes after that, so stop polling. Until then, poll every few seconds. - `outcome` and `outcome_summary` describe the whole call. The transcript, recording and extracted data belong to each attempt: read `last_call_attempt.transcript` (live), `last_call_attempt.post_call_transcript` (more accurate, after the call), `last_call_attempt.recording_url` and `last_call_attempt.structured_output`. - `outcome` can be set before the call is final: with `requested_callback_later`, when the callee gave a time and attempts are left, the call goes back to `scheduled` for the callback. - `is_completed` and `is_cancelled` are deprecated: read `status`. `is_completed` stays false for a cancelled or errored call. ### Request ```bash curl -X GET "https://www.getrevox.com/api/call/8d2f6b1a-4c9e-4f37-b215-6a0e9c3d7f12" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the call, as returned by [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md) or [`POST /call/search`](https://www.getrevox.com/docs/api/calls/search-calls.md). ### Body No body: send the request without one. ### Response 200 - `call` ([Call](https://www.getrevox.com/docs/api/objects/call.md)) ### Errors - `403` The resource belongs to another organization: `{"error":"Unauthorized, you are not the owner of this resource"}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Find which phone numbers are on the do-not-call list `POST https://www.getrevox.com/api/calls/screen-do-not-call` Returns the subset of the submitted numbers that must not be called. Unlike /calls/phone-history, which only knows numbers the organization has already called, this screens any number, so a contact imported for the first time can be caught before the campaign is created. ### Before you call - A campaign whose contacts include a do-not-call number is refused: screen the numbers first and leave out those in `blocked`. ### Request ```bash curl -X POST "https://www.getrevox.com/api/calls/screen-do-not-call" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone_numbers": ["+33612345678", "+33698765432"] }' ``` ### Body JSON. - `phone_numbers` (array of string, required): The phone numbers to screen, up to 20,000. International (E.164) format; a number that cannot be parsed is ignored. At most 20000 items. ### Response 200 ```json { "blocked": ["+33612345678"] } ``` - `blocked` (array of string): The submitted numbers on the do-not-call list, in E.164 format. Empty when none is. --- ## Search calls `POST https://www.getrevox.com/api/call/search` Search your organization's calls, most recent activity first by default. Filters, page and page_size are JSON body fields, and every filter is optional. Each entry is a full call, with its attempts. ### Before you call - Filters, `page` and `page_size` are JSON body fields, not query parameters. Every filter is optional: `{}` returns the 50 most recently updated calls. - There is no date filter. To read the calls since a date, keep the default sort (`updated_at`, newest first) and stop paging once `updated_at` is older than your cutoff. - Unknown body fields are ignored, not rejected: a misspelled filter returns unfiltered results. - Values within one filter are combined with OR, different filters with AND, except `variables`, whose entries must all match. ### Request The 20 most recently updated calls whose outcome is interested or requested_callback_later. ```bash curl -X POST "https://www.getrevox.com/api/call/search" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "outcomes": ["interested", "requested_callback_later"], "sort_by": "updated_at", "sort_direction": "desc", "page_size": 20 }' ``` ### Body JSON. - `query` (string, optional): Free-text search. A call matches when it contains every word of the query (3 characters or more, in any order) in its phone numbers, contact identity, metadata or prompt variable values, or in the extracted data of its last attempt. A phone number typed with spaces or a leading 0 is matched on its digits. - `statuses` (array of enum (10 values), optional, default []): Keep calls in any of these statuses. A scheduled call of a paused campaign counts as 'paused'. - `"initializing"`: Being created, not scheduled yet. Newer calls start as scheduled instead. - `"queued_for_calling"`: Its turn came: the attempt is about to dial, within your concurrent call limit. - `"calling"`: An attempt is in progress: the phone is ringing or a conversation is going on. - `"post_processing"`: The phone conversation is over; the transcript, outcome and extracted data are being computed. It can no longer be paused or cancelled. - `"not_launched"`: Created but never sent: a campaign call waiting for [`POST /campaigns/{id}/launch-calls`](https://www.getrevox.com/docs/api/campaigns/launch-a-campaigns-calls.md). It is not dialed until then. - `"scheduled"`: Waiting to be dialed at scheduled_at (the first attempt, a retry or a requested callback). A call due outside its calling windows waits for the next one. - `"paused"`: No new attempt is made until it is resumed ([`POST /call/{id}/resume`](https://www.getrevox.com/docs/api/calls/resume-a-paused-call.md), or resuming its campaign). - `"completed"`: Final. Revox will not dial it again: a person or a phone menu answered, or the last attempt allowed by call_retry_config was made. outcome and last_call_attempt tell how it went. - `"cancelled"`: Final. Cancelled before it completed: by a user ([`POST /call/{id}/cancel`](https://www.getrevox.com/docs/api/calls/cancel-a-call.md), the dashboard, a campaign cancel), or because the prospect called back (see cancel_reason). - `"errored"`: Final. The call could not be placed and will not be retried: the number does not exist, the destination cannot be called, the organization ran out of credits, or an internal error stopped it. - `directions` (array of ("inbound" | "outbound"), optional, default []): Keep calls in any of these directions. - `"inbound"`: Someone called one of your numbers and an assistant answered. - `"outbound"`: Revox called the number: from [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md), a campaign or the dashboard. - `results` (array of enum (6 values), optional, default []): Keep calls whose last attempt has one of these results (who answered: human, voicemail, IVR...). 'none' matches calls whose last attempt has no result yet, or no attempt at all. - `"IVR"`: An automated phone menu answered (e.g. 'press 1 for sales'). - `"voicemail"`: A voicemail or an answering machine answered. - `"human"`: A person answered. - `"unknown"`: Silence, or audio that could not be classified. - `"screening-filter"`: A call screening assistant (Apple or Google) answered for the person and asked who is calling and why. - `"none"`: The last attempt has no result yet, or there is no attempt. - `outcomes` (array of enum (6 values), optional, default []): Keep calls with one of these business outcomes. 'none' matches calls without an outcome, 'do_not_call' calls whose number is on the do-not-call list (those match no other outcome value). - `"not_interested"`: The person declined, refused or showed no interest. - `"interested"`: The person engaged and is a lead to follow up: the strongest outcome the AI assigns. - `"completed"`: A person from your team talked to the prospect: they joined the call, the call was transferred to them, or they set this outcome by hand. Never assigned by the AI. - `"requested_callback_later"`: The person asked to be called back later. When they gave a time and attempts are left, the call is scheduled again for that time. - `"none"`: The call has no outcome. - `"do_not_call"`: The number is on the do-not-call list. Such a call matches no other outcome value. - `assistant_ids` (array of string, optional, default []): Keep calls placed with one of these assistants. A step of a multi-step flow matches the calls that went through it. 'none' matches calls whose assistant was deleted. - `campaign_ids` (array of string, optional, default []): Keep calls of one of these campaigns. With this filter, a call superseded by the prospect calling back is left out, so each contact is listed once. - `from_phone_numbers` (array of string, optional, default []): Keep calls whose from_phone_number is one of these numbers (your number for an outbound call, the caller's for an inbound one), in E.164 format, exact match. - `assignee_ids` (array of (string | "none"), optional, default []): Keep calls assigned to one of these team members (user IDs, see the call's assignee.id). 'none' matches unassigned calls. - `variables` (array of object, optional): Keep calls whose metadata (or, when the metadata has no such key, prompt variables) hold all these values. - `variables.key` (string, required): Name of the metadata entry or prompt variable. - `variables.value` (string, required): Value it must have, compared case-insensitively and ignoring surrounding spaces. - `to_phone_number` (string, optional): Keep calls whose to_phone_number is this number (the person called for an outbound call, your number for an inbound one), in E.164 format, exact match. Ignored by [`POST /call/export`](https://www.getrevox.com/docs/api/calls/export-calls-history.md). - `call_ids` (array of string, optional): Keep only the calls with these IDs. Ignored by [`POST /call/export`](https://www.getrevox.com/docs/api/calls/export-calls-history.md). - `page` (integer, optional, default 1): Page number, starting at 1. Default: 1. ≥ 1. - `page_size` (integer, optional, default 50): Number of calls per page, 1 to 100. Default: 50. - `sort_by` (string, optional): Sort order. 'updated_at' (the default): most recent activity. 'duration': talk time of the last attempt, calls without one last. 'priority': a fixed order for working a campaign (live calls, then calls a person from your team joined, hot leads, calls a person answered, queued, scheduled, the rest), which ignores sort_direction. 'structured_output.': a value extracted from the last attempt. - `sort_direction` ("asc" | "desc", optional): 'asc' or 'desc' (the default). ### Response 200 - `calls` (array of [Call](https://www.getrevox.com/docs/api/objects/call.md)): The calls of the requested page, in the requested order. - `total_count` (number): Number of calls matching the filters, all pages together. --- ## Get a link to listen to a live call and jump in `POST https://www.getrevox.com/api/call/{id}/live-link` Returns a short-lived web page URL for one call that is ringing or on the line. Whoever opens it hears the call live, follows the transcript, and can take over from the AI with one click to talk to the person on the line, or hang up. No Revox account is needed: the URL is the credential, scoped to this call only. Typical use: a "Listen" button on a CRM record calls this endpoint when clicked, then opens the returned `url` in a new tab. Request a fresh link on every click rather than storing one. Send `{}` as the body for the default lifetime. Returns 409 when the call is not live (still queued, between attempts, or ended) and 404 when the call does not exist in your organization. ### Request ```bash curl -X POST "https://www.getrevox.com/api/call/8d2f6b1a-4c9e-4f37-b215-6a0e9c3d7f12/live-link" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "expires_in_seconds": 98 }' ``` ### Path parameters - `id` (string, required): The ID of the call. It must be live: ringing or on the line. ### Body JSON. - `expires_in_seconds` (integer, optional): How long the link can be opened, in seconds, from 30 to 3600. Default 300 (5 minutes). Keep it short: anyone holding the link can listen to the call and talk to the person on the line. Expiry only stops new openings: a page already connected to the call stays connected until the call ends. ### Response 200 ```json { "url": "https://example.com", "expires_at": "2026-11-05T09:00:00Z" } ``` - `url` (string (uri)): Web page to open in a browser to listen to the live call and, with one click, take over from the AI and talk to the person on the line (microphone required). No Revox account needed: the URL is the credential, so open it directly and do not store or forward it. - `expires_at` (string (date-time)): When the link stops opening (ISO 8601, UTC). Request a new link for the call after that. ### Errors - `404` Not found in your organization: `{"error":"Not found"}` - `409` Conflicts with the resource's current state: `{"error":"Conflicts with the resource's current state"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Export calls history `POST https://www.getrevox.com/api/call/export` Export calls as a CSV file, one line per call, selected with the filters of [`POST /call/search`](https://www.getrevox.com/docs/api/calls/search-calls.md). Large exports are split into files of at most 4 MB: when the response carries a non-null next_offset, call the endpoint again with that value as offset to get the next file. ### Before you call - A large export is split into files of at most 4 MB. While `next_offset` is not null, call again with the same `filters` and `offset` set to `next_offset`. ### Request One line per call of the campaign whose outcome is interested, with a column per extracted value and per metadata key. ```bash curl -X POST "https://www.getrevox.com/api/call/export" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "filters": { "campaign_ids": ["9b2d7e41-6c3f-4a8e-b5d0-2f7a1c9e4b63"], "outcomes": ["interested"] }, "include_structured_output_fields": true, "include_metadata": true }' ``` ### Body JSON. - `filters` (object, required): Which calls to export, as in [`POST /call/search`](https://www.getrevox.com/docs/api/calls/search-calls.md); page and page_size select the window of calls to export. to_phone_number and call_ids are not applied. - `filters.query` (string, optional): Free-text search. A call matches when it contains every word of the query (3 characters or more, in any order) in its phone numbers, contact identity, metadata or prompt variable values, or in the extracted data of its last attempt. A phone number typed with spaces or a leading 0 is matched on its digits. - `filters.statuses` (array of enum (10 values), optional, default []): Keep calls in any of these statuses. A scheduled call of a paused campaign counts as 'paused'. - `"initializing"`: Being created, not scheduled yet. Newer calls start as scheduled instead. - `"queued_for_calling"`: Its turn came: the attempt is about to dial, within your concurrent call limit. - `"calling"`: An attempt is in progress: the phone is ringing or a conversation is going on. - `"post_processing"`: The phone conversation is over; the transcript, outcome and extracted data are being computed. It can no longer be paused or cancelled. - `"not_launched"`: Created but never sent: a campaign call waiting for [`POST /campaigns/{id}/launch-calls`](https://www.getrevox.com/docs/api/campaigns/launch-a-campaigns-calls.md). It is not dialed until then. - `"scheduled"`: Waiting to be dialed at scheduled_at (the first attempt, a retry or a requested callback). A call due outside its calling windows waits for the next one. - `"paused"`: No new attempt is made until it is resumed ([`POST /call/{id}/resume`](https://www.getrevox.com/docs/api/calls/resume-a-paused-call.md), or resuming its campaign). - `"completed"`: Final. Revox will not dial it again: a person or a phone menu answered, or the last attempt allowed by call_retry_config was made. outcome and last_call_attempt tell how it went. - `"cancelled"`: Final. Cancelled before it completed: by a user ([`POST /call/{id}/cancel`](https://www.getrevox.com/docs/api/calls/cancel-a-call.md), the dashboard, a campaign cancel), or because the prospect called back (see cancel_reason). - `"errored"`: Final. The call could not be placed and will not be retried: the number does not exist, the destination cannot be called, the organization ran out of credits, or an internal error stopped it. - `filters.directions` (array of ("inbound" | "outbound"), optional, default []): Keep calls in any of these directions. - `"inbound"`: Someone called one of your numbers and an assistant answered. - `"outbound"`: Revox called the number: from [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md), a campaign or the dashboard. - `filters.results` (array of enum (6 values), optional, default []): Keep calls whose last attempt has one of these results (who answered: human, voicemail, IVR...). 'none' matches calls whose last attempt has no result yet, or no attempt at all. - `"IVR"`: An automated phone menu answered (e.g. 'press 1 for sales'). - `"voicemail"`: A voicemail or an answering machine answered. - `"human"`: A person answered. - `"unknown"`: Silence, or audio that could not be classified. - `"screening-filter"`: A call screening assistant (Apple or Google) answered for the person and asked who is calling and why. - `"none"`: The last attempt has no result yet, or there is no attempt. - `filters.outcomes` (array of enum (6 values), optional, default []): Keep calls with one of these business outcomes. 'none' matches calls without an outcome, 'do_not_call' calls whose number is on the do-not-call list (those match no other outcome value). - `"not_interested"`: The person declined, refused or showed no interest. - `"interested"`: The person engaged and is a lead to follow up: the strongest outcome the AI assigns. - `"completed"`: A person from your team talked to the prospect: they joined the call, the call was transferred to them, or they set this outcome by hand. Never assigned by the AI. - `"requested_callback_later"`: The person asked to be called back later. When they gave a time and attempts are left, the call is scheduled again for that time. - `"none"`: The call has no outcome. - `"do_not_call"`: The number is on the do-not-call list. Such a call matches no other outcome value. - `filters.assistant_ids` (array of string, optional, default []): Keep calls placed with one of these assistants. A step of a multi-step flow matches the calls that went through it. 'none' matches calls whose assistant was deleted. - `filters.campaign_ids` (array of string, optional, default []): Keep calls of one of these campaigns. With this filter, a call superseded by the prospect calling back is left out, so each contact is listed once. - `filters.from_phone_numbers` (array of string, optional, default []): Keep calls whose from_phone_number is one of these numbers (your number for an outbound call, the caller's for an inbound one), in E.164 format, exact match. - `filters.assignee_ids` (array of (string | "none"), optional, default []): Keep calls assigned to one of these team members (user IDs, see the call's assignee.id). 'none' matches unassigned calls. - `filters.variables` (array of object, optional): Keep calls whose metadata (or, when the metadata has no such key, prompt variables) hold all these values. - `filters.variables.key` (string, required): Name of the metadata entry or prompt variable. - `filters.variables.value` (string, required): Value it must have, compared case-insensitively and ignoring surrounding spaces. - `filters.to_phone_number` (string, optional): Keep calls whose to_phone_number is this number (the person called for an outbound call, your number for an inbound one), in E.164 format, exact match. Ignored by [`POST /call/export`](https://www.getrevox.com/docs/api/calls/export-calls-history.md). - `filters.call_ids` (array of string, optional): Keep only the calls with these IDs. Ignored by [`POST /call/export`](https://www.getrevox.com/docs/api/calls/export-calls-history.md). - `filters.page` (integer, optional, default 1): Page number, starting at 1. Default: 1. ≥ 1. - `filters.page_size` (integer, optional, default 50000): Number of calls in the exported window, 1 to 50,000. Default: 50,000. 1 to 50000. - `filters.sort_by` (string, optional): Sort order. 'updated_at' (the default): most recent activity. 'duration': talk time of the last attempt, calls without one last. 'priority': a fixed order for working a campaign (live calls, then calls a person from your team joined, hot leads, calls a person answered, queued, scheduled, the rest), which ignores sort_direction. 'structured_output.': a value extracted from the last attempt. - `filters.sort_direction` ("asc" | "desc", optional): 'asc' or 'desc' (the default). - `offset` (integer, optional, default 0): Number of already-exported rows to skip, within the filters' page/page_size window. Pass the next_offset value from the previous response to fetch the next file of a split export. ≥ 0. - `include_structured_output_fields` (boolean, optional): Add one column per value extracted from the last attempt, named structured_output-. - `include_metadata` (boolean, optional): Add one column per metadata key, named metadata-. ### Response 200 ```json { "csv": "id,to_phone_number,status,outcome\n6f9a3c1e,+33612345678,completed,interested", "filename": "calls-2026-11-05.csv", "next_offset": 1 } ``` - `csv` (string): The CSV file content, one line per call, with a header line. - `filename` (string): Suggested file name, e.g. 'revox-call-history-.csv', with the row range appended for a split export. - `next_offset` (integer | null): Non-null when the export was split because this file reached the 4MB cap: pass it as offset in a follow-up call to get the next file. Null when this file completes the export. --- ## Pause a call `POST https://www.getrevox.com/api/call/{id}/pause` Pause a call waiting for its next attempt (status scheduled or initializing): nothing is dialed until [`POST /call/{id}/resume`](https://www.getrevox.com/docs/api/calls/resume-a-paused-call.md). A call being dialed or in conversation cannot be paused (400): cancel it, or pause its campaign. ### Request ```bash curl -X POST "https://www.getrevox.com/api/call/8d2f6b1a-4c9e-4f37-b215-6a0e9c3d7f12/pause" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the call, as returned by [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md) or [`POST /call/search`](https://www.getrevox.com/docs/api/calls/search-calls.md). ### Body No body: send the request without one. ### Response 200 ```json { "success": true } ``` - `success` (boolean): True when the operation succeeded. ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["phone_number"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Resume a paused call `POST https://www.getrevox.com/api/call/{id}/resume` Resume a previously paused call. The retry loop will continue from where it left off. ### Request ```bash curl -X POST "https://www.getrevox.com/api/call/8d2f6b1a-4c9e-4f37-b215-6a0e9c3d7f12/resume" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the call, as returned by [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md) or [`POST /call/search`](https://www.getrevox.com/docs/api/calls/search-calls.md). ### Body No body: send the request without one. ### Response 200 ```json { "success": true } ``` - `success` (boolean): True when the operation succeeded. ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["phone_number"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Cancel a call `POST https://www.getrevox.com/api/call/{id}/cancel` Stop a call's future attempts. A call that has not started dialing yet is cancelled right away. A call whose attempt is already in progress is not hung up: that attempt finishes, and no retry or callback is scheduled after it. Returns 409 when the call can no longer be cancelled: its conversation is over and being analysed (post_processing), or it is in a final status. ### Request ```bash curl -X POST "https://www.getrevox.com/api/call/8d2f6b1a-4c9e-4f37-b215-6a0e9c3d7f12/cancel" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the call, as returned by [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md) or [`POST /call/search`](https://www.getrevox.com/docs/api/calls/search-calls.md). ### Body No body: send the request without one. ### Response 200 ```json { "success": true } ``` - `success` (boolean): True when the operation succeeded. ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["phone_number"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - `409` Conflicts with the resource's current state: `{"error":"Conflicts with the resource's current state"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Get phone number history across the organization `GET https://www.getrevox.com/api/calls/phone-history` Returns a map of phone numbers to the number of calls and associated campaigns across the entire organization. Useful for detecting contacts that have already been reached. ### Request ```bash curl -X GET "https://www.getrevox.com/api/calls/phone-history" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Body No body: send the request without one. ### Response 200 ```json { "phone_history": { "+33612345678": { "count": 3, "campaigns": [ { "id": "8e1f2a3b-4c5d-4e6f-9a0b-1c2d3e4f5a6b", "name": "Appointment reminder" } ], "last_called_at": "2026-11-05T09:00:00Z", "last_outcome": "interested", "reached_human": true, "do_not_contact": false, "hot": false } } } ``` - `phone_history` (object): Call history of every number the organization has called, keyed by phone number in E.164 format. Only completed attempts of calls that were not deleted count. Keys: Phone number, in E.164 format. - `phone_history.count` (number): Completed call attempts to this number, all calls together. - `phone_history.campaigns` (array of object): The campaigns this number was called from, each listed once. - `phone_history.campaigns.id` (string): ID of the campaign. - `phone_history.campaigns.name` (string): Name of the campaign. - `phone_history.last_called_at` (string | null): When the most recent completed attempt started (ISO 8601). - `phone_history.last_outcome` (enum (4 values) | null, default null): Business outcome of the call of the most recent attempt. Null when that call has none. - `"not_interested"`: The person declined, refused or showed no interest. - `"interested"`: The person engaged and is a lead to follow up: the strongest outcome the AI assigns. - `"completed"`: A person from your team talked to the prospect: they joined the call, the call was transferred to them, or they set this outcome by hand. Never assigned by the AI. - `"requested_callback_later"`: The person asked to be called back later. When they gave a time and attempts are left, the call is scheduled again for that time. - `phone_history.reached_human` (boolean): True when a person answered at least one of the attempts. - `phone_history.do_not_contact` (boolean): True when the number is on the organization's do-not-call list: it must not be called again. - `phone_history.hot` (boolean): True when a call to this number ever ended with the outcome 'interested' or 'completed'. --- ## Create an assistant `POST https://www.getrevox.com/api/assistants` Create a voice agent: the prompt the LLM follows, how it opens the call, its voice (Cartesia, ElevenLabs and Gradium), the data to extract after each call and where to post the result. Once created, pass its ID as assistant_id to place calls or to create a campaign. ### Before you call - The language of the calls is the language of `voice` (`language` in [`GET /voices`](https://www.getrevox.com/docs/api/voices/get-voices.md)). Without `voice`, the assistant speaks English: send a voice in the language the person called will speak. - `first_sentence` is only used with `first_sentence_mode` `static`, spoken word for word. With the default mode, `generated`, the agent writes its own greeting from the prompt and `first_sentence` is dropped. - Write `{{variable}}` placeholders in `prompt` and `first_sentence`, then send their values in `prompt_variables` of each call, or of each campaign contact. - Set `webhook_url` to receive each call once it is over, with its outcome, transcript and extracted data. Without it, poll [`GET /call/{id}`](https://www.getrevox.com/docs/api/calls/get-call-by-id.md). - After your last change, run [`POST /assistants/{id}/setup-check`](https://www.getrevox.com/docs/api/assistants/check-an-assistants-setup.md) and fix what it reports before placing calls. ### Request The French voice makes every call French, even with a prompt written in English. Each call sends first_name and appointment_date in prompt_variables; the extracted values come back in structured_output of each attempt, and the call is posted to webhook_url once it is over. ```bash curl -X POST "https://www.getrevox.com/api/assistants" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Appointment reminders", "prompt": "You are Julie, the assistant of the Acme dental practice. You call {{first_name}} to remind them of their appointment on {{appointment_date}} and ask them to confirm it. If they cannot come, offer to call them back to set a new date and ask when suits them best. Keep the call short and friendly.", "first_sentence": "Bonjour {{first_name}}, ici Julie du cabinet dentaire Acme. Je vous appelle au sujet de votre rendez-vous.", "first_sentence_mode": "static", "voice": { "provider": "cartesia", "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6" }, "webhook_url": "https://example.com/webhooks/revox", "structured_output_config": [ { "name": "appointment_confirmed", "type": "boolean", "description": "True when the person confirmed they will come.", "required": true }, { "name": "preferred_callback_time", "type": "datetime", "description": "When the person wants to be called back to set a new date, if they asked to." } ] }' ``` ### Body JSON. - `prompt` (string, required): System prompt given to the LLM for the whole call: who the agent is, its goal and how to run the conversation. May contain {{variable}} placeholders, filled from the call's prompt_variables. - `name` (string, required): Display name of the assistant, shown in the dashboard and in call lists. - `post_call_prompt` (string | null, optional): Instructions the agent follows once the call has ended: who to email, when to text, what to post on Slack or Teams. Plain language, no template syntax. Empty or null means no post-call agent runs. - `first_sentence` (string, optional): The agent's opening line, spoken word for word. Only used, and only kept, with first_sentence_mode 'static': with 'generated' or 'none' it is dropped and reads back empty. May contain {{variable}} placeholders; one without a value is left out. - `first_sentence_mode` ("generated" | "static" | "none", optional): How the agent opens the call. Default at creation: 'generated'. - `"generated"`: The agent opens with a greeting it writes from the prompt. first_sentence is not used, and not kept. - `"static"`: The agent opens with first_sentence, word for word. - `"none"`: The agent says nothing first and waits for the other person to speak. - `end_of_call_sentence` (string, optional): Sentence the agent says, without being interruptible, when it decides to end the call. Null or empty: the agent says a short default goodbye, only if it has not said goodbye already. - `voice` (object, optional): The voice the agent speaks with ([`GET /voices`](https://www.getrevox.com/docs/api/voices/get-voices.md) lists them). Its language (see [`GET /voices`](https://www.getrevox.com/docs/api/voices/get-voices.md)) is the language of the calls, unless voice_languages picks another one for a call. Omitted at creation: Revox's default voice, Jacqueline from Cartesia (id 9626c31c-bec5-4cca-baa8-f8ba9e84c8bc), which speaks English. - `voice.provider` ("cartesia" | "elevenlabs" | "gradium", required): The provider of the voice. - `voice.id` (string, required): ID of the voice at its provider, as [`GET /voices`](https://www.getrevox.com/docs/api/voices/get-voices.md) lists it. At least 1 character. Example: `"4325f426-c4e0-418e-a0e5-97fcdfcdf8e6"`. - `voice.speed` (number, optional): The speed of the voice. Range depends on provider: Cartesia 0.6 to 1.5, ElevenLabs 0.7 to 1.2, Gradium 0.6 to 1.5. Default is 1.0. - `voice.volume` (number, optional): Volume of the voice (Cartesia only), 0.5 to 2.0. Default 1.0. Ignored for other providers. - `voice.model` ("sonic-3" | "sonic-3.5" | "sonic-3.6", optional): Cartesia TTS model (Cartesia only). Defaults to sonic-3.6 when omitted. Ignored for other providers. - `voice_languages` (array of object | null, optional): Extra languages for a multilingual assistant, each with its own voice (any provider). A call picks one with a `language` entry in its prompt_variables (a language code such as "es", or a name such as "Spanish"); otherwise the phone number's country picks one, and failing that the call runs in the language of `voice`, which cannot be listed here. A changed voice is applied to the calls in that language that have not completed yet; a language still used by such a call cannot be removed. - `voice_languages.language` (enum (8 values), required): The language contacts are called in with this voice. - `"en"`: English - `"fr"`: French - `"es"`: Spanish - `"de"`: German - `"it"`: Italian - `"pt"`: Portuguese - `"ru"`: Russian - `"zh"`: Mandarin Chinese - `voice_languages.voice` (object, required): The voice used for contacts whose language is this language. - `voice_languages.voice.provider` ("cartesia" | "elevenlabs" | "gradium", required): The provider of the voice. - `voice_languages.voice.id` (string, required): ID of the voice at its provider, as [`GET /voices`](https://www.getrevox.com/docs/api/voices/get-voices.md) lists it. At least 1 character. Example: `"4325f426-c4e0-418e-a0e5-97fcdfcdf8e6"`. - `voice_languages.voice.speed` (number, optional): The speed of the voice. Range depends on provider: Cartesia 0.6 to 1.5, ElevenLabs 0.7 to 1.2, Gradium 0.6 to 1.5. Default is 1.0. - `voice_languages.voice.volume` (number, optional): Volume of the voice (Cartesia only), 0.5 to 2.0. Default 1.0. Ignored for other providers. - `voice_languages.voice.model` ("sonic-3" | "sonic-3.5" | "sonic-3.6", optional): Cartesia TTS model (Cartesia only). Defaults to sonic-3.6 when omitted. Ignored for other providers. - `cartesia_dictionary_pronunciation_id` (string | null, optional): Optional Cartesia pronunciation dictionary ID to use for this assistant's calls. Set null to unlink it. At least 1 character. - `llm_model` (object, optional): The LLM that drives the conversation. Defaults to `recommended` (the model Revox currently recommends for voice agents) when omitted at creation. - One of 3, chosen by `llm_model.type`. - When `type` is `"recommended"`: The LLM Revox currently recommends for voice agents, chosen server-side and upgraded without any change on your side. No per-assistant configuration. Example: `{"type":"recommended"}`. - When `type` is `"gpt-4.1-priority"`: OpenAI gpt-4.1 on the priority tier, with gpt-4.1-mini answering a turn when gpt-4.1 is slow to respond. No per-assistant configuration. Example: `{"type":"gpt-4.1-priority"}`. - When `type` is `"realtime"`: A realtime speech-to-speech model: it listens to the call and answers with its own voice (realtime_voice_id), instead of the assistant's transcriber and voice. Example: `{"type":"realtime","provider":"openai","realtime_model_id":"gpt-realtime"}`. - `llm_model.provider` ("openai" | "google", required): Provider of the realtime model. - `llm_model.realtime_model_id` (string, required): ID of the realtime model: 'gpt-realtime' (provider 'openai'), 'gemini-3.1-flash-live-preview' (provider 'google'), 'gemini-2.5-flash-native-audio-preview-12-2025' (provider 'google'). Example: `"gpt-realtime"`. - `llm_model.realtime_voice_id` (string, optional): Output voice for the realtime provider (e.g. OpenAI: marin; Gemini: Puck). At least 1 character. Example: `"marin"`. - `webhook_url` (string, optional): URL that receives a POST with the call and this assistant once the call is over, when it reaches completed or errored (not when it is cancelled). See Webhooks for the payload. - `max_call_duration_secs` (number, optional): Longest a call may last, in seconds: the agent then says max_duration_end_message, if set, and hangs up. Default at creation: 300. Outbound calls are capped at 600. - `max_duration_end_message` (string | null, optional): Optional message the agent will say, without being interruptible, when the call reaches its max duration. Kept short so it fits inside the farewell buffer. If not set, the call ends silently. At most 150 characters. - `structured_output_config` (array of object, optional): The values to extract from each call (e.g. an email, a budget, a date). They land in structured_output of each call attempt, keyed by name. - `structured_output_config.name` (string, required): Name of the value (e.g. 'email', 'budget'). In an assistant's structured_output_config, its key in the call attempt's structured_output; in a custom tool's input_schema, the name of the parameter passed to the tool. At least 1 character. Example: `"budget"`. - `structured_output_config.type` (enum (6 values), required): Type of the extracted value. - `"string"`: Free text. - `"number"`: A JSON number. - `"boolean"`: true or false. - `"enum"`: One of enum_options. With fewer than 2 options, extracted as free text. - `"date"`: A date, as an ISO 8601 string (YYYY-MM-DD). - `"datetime"`: A date and time, as an ISO 8601 string. - `structured_output_config.description` (string, optional): What the value is, in plain words, for the LLM that fills it in (e.g. 'The budget the prospect mentions, in euros'). - `structured_output_config.required` (boolean, optional, default false): When false (the default), the value may be null or missing when the conversation did not provide it. - `structured_output_config.enum_options` (array of string, optional): The allowed values when type is 'enum'. With fewer than 2 options the field is extracted as a free string. - `structured_output_prompt` (string | null, optional): Custom prompt for structured data extraction. If not provided, a default prompt is used. Available variables: {{transcript}}, {{call_direction}}, {{user_phone_number}}, {{agent_phone_number}}. - `call_retry_config` (object, optional) - `call_retry_config.calling_windows` (array of object, required): Daily time windows in which calls may be placed, on the allowed_days. A call due outside every window waits for the next one to open. Request bodies need at least one window. - `call_retry_config.calling_windows.calling_window_start_time` (string, required): Start time of the calling window, in `timezone` (each callee's own timezone when it is null). Format: 'HH:mm' (24-hour) or 'h:mma' (12-hour, minutes required). Examples: '09:00', '10:00am'. Default: '10:00'. - `call_retry_config.calling_windows.calling_window_end_time` (string, required): End time of the calling window, in `timezone` (each callee's own timezone when it is null). Must be after the start time: a window cannot span midnight. Format: 'HH:mm' (24-hour) or 'h:mma' (12-hour, minutes required). Examples: '17:00', '6:00pm'. Default: '18:00'. - `call_retry_config.calling_windows.retry_delay_seconds` (integer, optional, default 7200): Delay between retry attempts in seconds. Values below the 15-minute minimum are raised to it: a shorter delay means calling someone again minutes after they declined. For one deliberate immediate second dial, use call_twice_in_a_row. Default: 7200 (2 hours). ≥ 0. - `call_retry_config.max_retry_attempts` (integer, optional, default 5): Maximum number of call attempts, first call included. Default: 5. Capped by the organization's plan: 5 on Starter, 8 on Business. A contact nobody picks up is billed once all its attempts were placed. > 0. - `call_retry_config.allowed_days` (array of enum (7 values), optional, default ["monday","tuesday","wednesday","thursday","friday"]): Days of the week when calls are allowed, in the same timezone as the calling windows. Default: Monday through Friday. Values: `"monday"`, `"tuesday"`, `"wednesday"`, `"thursday"`, `"friday"`, `"saturday"`, `"sunday"`. - `call_retry_config.excluded_dates` (array of string (date), optional): Calendar dates on which no call goes out, such as public holidays or days the office is closed, as 'YYYY-MM-DD' (e.g. ['2026-12-25', '2027-01-01']). Read in the same timezone as the calling windows: each callee's local date when timezone is null. A call or retry that would land on an excluded date waits for the next open window after it. Up to 366 dates; duplicates are removed and the list is sorted. A call placed with skip_calling_window ignores them for its first dial only. Default: none. At most 366 items. - `call_retry_config.call_twice_in_a_row` (boolean, optional, default false): Double call. If true and max_retry_attempts >= 2, when the first attempt reaches nobody (no answer, declined, voicemail, call screening nobody took), the second attempt is dialed within seconds instead of after retry_delay_seconds, from the same caller number. Two calls in a row from one number raise the pickup rate. Each call is an attempt: the double call counts as 2 when both calls happen, 1 when the first is picked up. Busy or unreachable phones are retried after the normal delay. Calling days and hours still apply. Only the first attempt is doubled; later ones follow retry_delay_seconds. A voicemail_message is left on the second dial only. Default: false. - `call_retry_config.timezone` (string | null, optional, deprecated): Deprecated: use the `timezone` field of the assistant, the campaign or [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md). Still accepted on writes and copied there, and returned with that value. Null no longer means each callee's own timezone: a call's timezone is never derived from its phone number. - `timezone` (string, optional): IANA timezone of this assistant's calls, e.g. 'Europe/Paris' or 'America/Phoenix'. Every call runs in exactly one timezone: its calling windows and allowed days are read in it, the agent tells the date and offers calendar slots in it, and callbacks and extracted datetimes are interpreted in it. A campaign's `timezone`, then [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md) `timezone`, override it for their calls. Default when creating: 'Europe/Paris'. Replaces the deprecated `call_retry_config.timezone`. - `background_sound` ("audio/office.ogg" | "audio/waves.m4a" | null, optional): Ambient background sound to play during the call. null/omitted disables it. - `background_sound_volume` (number, optional): Volume of the ambient background sound (0 = silent, 1 = max). 0 to 1. - `thinking_sound` (enum (7 values) | null, optional): Audio clip played while the agent prepares an answer. Null or omitted: none. Values: `"city-ambience.ogg"`, `"forest-ambience.ogg"`, `"office-ambience.ogg"`, `"crowded-room.ogg"`, `"keyboard-typing.ogg"`, `"keyboard-typing2.ogg"`, `"hold_music.ogg"`. - `thinking_sound_volume` (number, optional): Volume of the thinking sound (0 = silent, 1 = max). 0 to 1. - `thinking_sound_probability` (number, optional): Probability [0..1] that the thinking sound plays on any given turn; otherwise the agent is silent while thinking. 0 to 1. - `transfer_destinations` (array of object | null, optional): Where calls can be transferred to when users ask to speak to a human. With a single entry the assistant always transfers there; with several, it picks one at transfer time by applying the routing rules written in the assistant's own prompt (which refer to the destination labels). Empty or null disables transfer. At most 10 items. - `transfer_destinations.label` (string, required): Human-meaningful name for this destination (e.g. "Sales"). The assistant's prompt refers to these labels when describing who to transfer to. 1 to 60 characters. - `transfer_destinations.phone_number` (string, required): Destination phone number in E.164 format (e.g. +33612345678). - `human_transfer_mode` ("warm" | "cold" | null, optional): How calls are transferred to transfer_destinations. Default: 'warm'. Ignored without transfer destinations. - `"warm"`: The agent calls the destination first, briefs the person who answers on the call so far (see warm_transfer_summary_instructions), then puts the caller through. - `"cold"`: The call is passed on at once, without a briefing (a SIP REFER: the phone carrier must allow it). - `warm_transfer_summary_instructions` (string | null, optional): When using warm transfer: extra instructions for the supervisor handoff summary. If null or empty, the API uses the product default briefing when the call is loaded for the agent. - `warm_transfer_voice_speed` (number | null, optional): When using warm transfer: voice speed used only while the AI briefs the human colleague. Same range as voice.speed. Omit or null to brief at the assistant's voice speed. 0.6 to 1.5. - `ivr_navigation_enabled` (boolean, optional): Enable IVR navigation tools. When enabled, the assistant can send DTMF tones and skip turns to navigate phone menus. - `voicemail_message` (string | null, optional): If set, when voicemail is detected the agent will speak this message then hang up; if null, hang up immediately. Left on the first attempt only (second dial of a double call). Takes the same {{variables}} as the prompt (e.g. "Hi {{first_name}}, this is Julie from Acme, please call us back."). - `stt_context` (object | null, optional): Assistant-level speech-to-text context: structured `general` key/value pairs plus a list of domain `terms`. Prompt-derived context is merged in without replacing existing entries. - `stt_context.general` (array of object, optional, default []): Short key/value facts that frame the conversation for the speech-to-text engine (domain, topic, company), to improve recognition. Only the first 6 pairs are used. - `stt_context.general.key` (string, required): What the fact is about (e.g. 'domain', 'topic', 'company'). Unique within `general`: a repeated key is dropped. At least 1 character. - `stt_context.general.value` (string, required): The fact itself (e.g. 'Real estate rentals'). At least 1 character. - `stt_context.terms` (array of string, optional, default []): Words the speech-to-text engine should expect on the call: proper nouns, brand and product names, jargon, email domains. At most 100 terms of up to 5 words are used; URLs and digit-only terms are dropped, since callers never say them. Each item at least 1 character. - `first_sentence_delay_ms` (integer, optional): Delay in milliseconds before speaking the first sentence. Default: 400. ≥ 0. - `hubspot` (object | null, optional): HubSpot Meetings config. When set with at least one meeting link, the agent can read a rep's real availability and book the meeting natively in HubSpot during the call. Null when HubSpot is not connected. - `hubspot.connection_id` (string, required): The connection ID linking the organization's HubSpot account to Revox. - `hubspot.precall_lookup_enabled` (boolean, optional, default false): Resolve the caller against HubSpot contacts before answering an inbound call, filling the contact_* prompt variables (contact_name, contact_owner, contact_lead_status, contact_has_open_deal). Off by default: it costs API calls before the phone is picked up. - `hubspot.meeting_links` (array of object, optional, default []): Scheduling pages the agent can book on during a call: typically one per sales rep, plus a round-robin team page marked as the fallback. - `hubspot.meeting_links.slug` (string, required): HubSpot scheduling page slug, as returned by the meeting-links API (e.g. 'jane-doe'). At least 1 character. - `hubspot.meeting_links.label` (string, required): Name the agent recognises for this calendar (e.g. 'Jane Doe'). Listed in the prompt and matched against what the caller asks for. At least 1 character. - `hubspot.meeting_links.duration_ms` (integer, required): Meeting duration in milliseconds, chosen among the durations the scheduling page offers (e.g. 1800000 for 30 minutes). > 0. - `hubspot.meeting_links.is_fallback` (boolean, required): Marks the round-robin calendar the agent falls back to when the requested rep has no slot. At most one meeting link may set this. - `hubspot.meeting_links.booking_url` (string | null, optional, default null): Public URL of the scheduling page (e.g. https://meetings-eu1.hubspot.com/jane-doe). The agent books through the API and only texts this link to the caller when the booking fails and the call can receive an SMS. Null on calendars saved before this field existed. - `hubspot.post_call_sync` (object, optional): Sends call data back to HubSpot after the call. Off until set: connecting HubSpot to book meetings must not start writing to the CRM. Always present in responses; omit it on update to leave the current setting untouched. - `hubspot.post_call_sync.enabled` (boolean, optional, default false): Records calls in HubSpot after they end: the contact is created or updated from the phone number and the call is logged on its timeline. By default every call a person answered is recorded. When the post-call prompt talks about the CRM (in plain words or by mentioning the crm_push_call tool), the post-call agent decides instead which calls are recorded and what the logged call says. - `hubspot.post_call_sync.field_mapping` (array of object, optional, default []): Maps extracted call fields (structured_output / prompt variables) onto HubSpot contact properties. - `hubspot.post_call_sync.field_mapping.source` (string, required): Source key to read from the call: a structured_output field name, falling back to a prompt variable of the same name. At least 1 character. Example: `"email"`. - `hubspot.post_call_sync.field_mapping.hubspot_property` (string, required): Destination HubSpot contact property, by internal name (e.g. 'email', 'company', or a custom 'budget'). At least 1 character. Example: `"email"`. - `slack` (object | null, optional): Slack config. When set, the post-call agent can post to the listed channels after a call; whether it posts, and what it says, is decided by `post_call_prompt`. Null when Slack is not connected. - `slack.connection_id` (string, required): The connection ID linking the organization's Slack workspace to Revox. - `slack.channels` (array of object, required): The Slack channels the post-call agent may post to. It resolves the channel it was told to use against this list and cannot reach any other. - `slack.channels.id` (string, required): The Slack channel ID (e.g. 'C01234567'). - `slack.channels.name` (string | null, optional): Human-readable Slack channel name, cached for display in the dashboard and given to the LLM when the agent prompt routes by channel name. - `teams` (object | null, optional): Microsoft Teams config. When set with at least one channel, the post-call agent can post to those channels when the post-call instructions ask for it. Null when Teams is not connected. - `teams.connection_id` (string, required): The connection ID linking a Microsoft Teams account to Revox. Messages are posted as that account. - `teams.channels` (array of object, required): The Teams channels the post-call agent may post to. It resolves the channel it was told to use against this list and cannot reach any other. - `teams.channels.id` (string, required): The Microsoft Teams channel ID (e.g. '19:561fbdbb...@thread.tacv2'). - `teams.channels.team_id` (string, required): The ID of the team the channel belongs to. Needed to post. - `teams.channels.name` (string | null, optional): Human-readable channel name, cached for display in the dashboard and given to the LLM when the agent prompt routes by channel name. - `teams.channels.team_name` (string | null, optional): Human-readable team name. Channel names repeat across teams (every team has a 'General'), so the team name is what tells two of them apart. - `zoho` (object | null, optional): Zoho CRM config. When set, the post-call agent can upsert the prospect (keyed on phone) into the chosen module and attach a Note with the call summary. Null when Zoho is not connected. - `zoho.connection_id` (string, required): The connection ID linking the organization's Zoho CRM account to Revox. - `zoho.module` (string, required): Zoho module the prospect record is upserted into (e.g. 'Leads' or 'Contacts'). At least 1 character. - `zoho.log_call_activity` (boolean, required): When true, also log the call as a record in Zoho's Calls module (related to the upserted prospect via Who_Id). - `zoho.field_mapping` (array of object, required): Maps extracted call fields (structured_output / prompt variables) onto Zoho field API names on the upserted record. - `zoho.field_mapping.source` (string, required): Source key to read from the call: a structured_output field name, falling back to a prompt variable of the same name. At least 1 character. Example: `"email"`. - `zoho.field_mapping.zoho_field` (string, required): Destination Zoho field API name on the upserted record (e.g. 'Email', 'Company', or a custom 'Budget__c'). At least 1 character. Example: `"Email"`. - `zoho.template` (string | null, optional): Optional Note body template. Supports {{summary}}, {{outcome}}, {{phone}}, {{call_url}}, {{assistant_name}}, {{campaign_name}}, {{transcript}}, plus prompt_variables and structured_output keys. When null/empty a default note (outcome + summary + auto-listed extracted fields) is used. Example: `"{{outcome}}: {{summary}}\n{{call_url}}"`. - `custom_tools` (array of object | null, optional): Custom API tools the assistant can call during conversations. Each tool defines an HTTP endpoint with variable substitution. Null or empty when the assistant has none. - `custom_tools.name` (string, required): Unique tool name in lowercase_snake_case (e.g. check_inventory). At least 1 character, pattern ^[a-z][a-z0-9_]*$. - `custom_tools.description` (string, required): Human-readable description of what the tool does, used by the LLM to decide when to call it. At least 1 character. - `custom_tools.method` (enum (5 values), required): HTTP method to use when calling the API endpoint. Values: `"GET"`, `"POST"`, `"PUT"`, `"PATCH"`, `"DELETE"`. - `custom_tools.url` (string, required): Full URL of the API endpoint. Supports {{variable}} placeholders for dynamic values. At least 1 character. - `custom_tools.input_schema` (array of object, required): Schema defining the parameters the LLM should extract from the conversation to pass to this tool - `custom_tools.input_schema.name` (string, required): Name of the value (e.g. 'email', 'budget'). In an assistant's structured_output_config, its key in the call attempt's structured_output; in a custom tool's input_schema, the name of the parameter passed to the tool. At least 1 character. Example: `"budget"`. - `custom_tools.input_schema.type` (enum (6 values), required): Type of the extracted value. - `"string"`: Free text. - `"number"`: A JSON number. - `"boolean"`: true or false. - `"enum"`: One of enum_options. With fewer than 2 options, extracted as free text. - `"date"`: A date, as an ISO 8601 string (YYYY-MM-DD). - `"datetime"`: A date and time, as an ISO 8601 string. - `custom_tools.input_schema.description` (string, optional): What the value is, in plain words, for the LLM that fills it in (e.g. 'The budget the prospect mentions, in euros'). - `custom_tools.input_schema.required` (boolean, optional, default false): When false (the default), the value may be null or missing when the conversation did not provide it. - `custom_tools.input_schema.enum_options` (array of string, optional): The allowed values when type is 'enum'. With fewer than 2 options the field is extracted as a free string. - `custom_tools.headers` (array of object, optional, default []): HTTP headers to include in the request. Values support {{variable}} placeholders - `custom_tools.headers.key` (string, required): HTTP header name. At least 1 character. - `custom_tools.headers.value` (string, required): Header value. Supports {{variable}} placeholders. - `custom_tools.query_params` (array of object, optional, default []): Query string parameters appended to the URL. Values support {{variable}} placeholders - `custom_tools.query_params.key` (string, required): Query parameter name. At least 1 character. - `custom_tools.query_params.value` (string, required): Query parameter value. Supports {{variable}} placeholders. - `custom_tools.body_template` (string | null, optional, default null): JSON body template for the request. Use quoted {{variable}} placeholders (e.g. "{{name}}") for dynamic values - `from_phone_number` (string | null, optional): Caller ID of the calls placed with this assistant: a number of your organization ([`GET /phone-numbers`](https://www.getrevox.com/docs/api/phone-numbers/get-phone-numbers.md)), in E.164 format. A French mobile number (06, 07) cannot be the caller ID of an automated call. Null: a Revox number chosen for each destination. - `precall_lookup_url` (string | null, optional): Inbound calls only. URL fetched over HTTP GET right before the call is answered, with `{{phone}}` replaced by the caller's number in E.164 format (URL-encoded), to fill the `{{variable}}` placeholders the assistant declares. It answers either `{"prompt_variables": {...}}` or a flat JSON object whose top-level fields are the variables. The call is always answered: if the endpoint fails, takes more than 3 seconds, answers 404 or leaves a variable out, the missing variables are marked as not provided. Must be an http(s) URL containing `{{phone}}`. When null, no lookup is performed. At most 2000 characters. - `precall_lookup_headers` (array of object | null, optional): HTTP headers sent with the pre-call lookup request, e.g. an API key. Null or empty when the endpoint needs none. At most 10 items. - `precall_lookup_headers.key` (string, required): HTTP header name (e.g. 'Authorization'). At most 200 characters, pattern ^[A-Za-z0-9!#$%&'*+.^_`|~-]+$. - `precall_lookup_headers.value` (string, required): Header value, sent as is (no {{variable}} substitution), e.g. 'Bearer sk_123'. 1 to 4000 characters. - `stt_model` ("stt-rt-v4" | "stt-rt-v5", optional, deprecated): Speech-to-text model stored on the assistant. Ignored: every call is transcribed with the model Revox currently runs. - `calendly` (object | null, optional, deprecated): Deprecated: an assistant now books on any number of calendars, managed with the assistant calendars endpoints and listed in `calendars`. This field stands for the assistant's first ready calendar of this provider: setting it creates or updates that calendar, null removes it. The dashboard ignores it. - `cal` (object | null, optional, deprecated): Deprecated: an assistant now books on any number of calendars, managed with the assistant calendars endpoints and listed in `calendars`. This field stands for the assistant's first ready calendar of this provider: setting it creates or updates that calendar, null removes it. The dashboard ignores it. - `google_calendar` (object | null, optional, deprecated): Deprecated: an assistant now books on any number of calendars, managed with the assistant calendars endpoints and listed in `calendars`. This field stands for the assistant's first ready calendar of this provider: setting it creates or updates that calendar, null removes it. The dashboard ignores it. ### Response 200 - `assistant` ([Assistant](https://www.getrevox.com/docs/api/objects/assistant.md)) ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["prompt"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Get assistant by ID `GET https://www.getrevox.com/api/assistants/{id}` Retrieve a single assistant by its unique ID. Returns the full assistant configuration including prompt, voice settings, and first sentence mode. Useful for inspecting an assistant's current setup before updating it or placing a call. ### Request ```bash curl -X GET "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). ### Body No body: send the request without one. ### Response 200 A [Assistant](https://www.getrevox.com/docs/api/objects/assistant.md) object: see "Objects on this page" below. --- ## Get assistants `GET https://www.getrevox.com/api/assistants` Retrieve all assistants associated with your account. Each assistant in the response includes its full configuration: prompt, voice settings, and first sentence. Use this endpoint to list available assistants before placing calls. ### Request ```bash curl -X GET "https://www.getrevox.com/api/assistants" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Body No body: send the request without one. ### Response 200 - `assistants` (array of [Assistant](https://www.getrevox.com/docs/api/objects/assistant.md)): The organization's assistants. Steps of multi-step flows (type 'sub-assistant') are not listed. --- ## Check an assistant's setup `POST https://www.getrevox.com/api/assistants/{id}/setup-check` Check a saved assistant for the setup mistakes that break real calls: a persona whose gender doesn't match the voice, a prompt that transfers or books with no transfer destination or calendar connected, template text left in, the wrong language, wording that reads wrong once variables are filled. Call it after your last change to the assistant. Returns at most one issue per kind, each with the fix to apply when one exists; an empty list means nothing major was found. The result is stored: while the setup is unchanged it comes back instantly, a fresh check takes a few seconds. Multi-step assistants are not checked. ### Before you call - Run it after your last change to the assistant, then apply each issue's `fix` with [`PATCH /assistants/{id}`](https://www.getrevox.com/docs/api/assistants/update-an-assistant.md) and check again. ### Request Issue messages in English. ```bash curl -X POST "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/setup-check" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "locale": "en" }' ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). ### Body JSON. - `locale` ("fr" | "en", required): Language of the issue messages. - `dismiss` (integer, optional): Index of an issue to ignore: it is no longer returned until the setup changes. ### Response 200 - `issues` (array of [AssistantSetupIssue](https://www.getrevox.com/docs/api/objects/assistant-setup-issue.md)): The major problems found, at most one per kind. Empty when nothing major was found. ### Errors - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Update an assistant `PATCH https://www.getrevox.com/api/assistants/{id}` Update one or more fields of an assistant: only the fields you send change. Update the prompt, voice, first sentence, name or any other setting without touching the rest of the configuration. ### Before you call - Only the fields you send change. A list or object you send (`structured_output_config`, `call_retry_config`, `custom_tools`...) replaces the stored one: send it whole. - To change the language of the calls, change `voice` to a voice in that language. - Calls not completed yet take the change too, except those whose `prompt_variables` lack a variable the new prompt uses: they keep the previous prompt, and `unpatchedCallsNotice` counts them. ### Request Every other field keeps its value. A French voice keeps the calls in French. ```bash curl -X PATCH "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "voice": { "provider": "cartesia", "id": "93c98a2b-7d15-4f7b-8236-294b1e02b1c0" }, "llm_model": { "type": "gpt-4.1-priority" } }' ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). ### Body JSON. Same fields as the body of [Create an assistant](https://www.getrevox.com/docs/api/assistants/create-an-assistant.md), all optional: only the fields you send change. Fields: `prompt`, `post_call_prompt`, `first_sentence`, `first_sentence_mode`, `end_of_call_sentence`, `voice`, `voice_languages`, `cartesia_dictionary_pronunciation_id`, `llm_model`, `webhook_url`, `max_call_duration_secs`, `max_duration_end_message`, `structured_output_config`, `structured_output_prompt`, `call_retry_config`, `timezone`, `background_sound`, `background_sound_volume`, `thinking_sound`, `thinking_sound_volume`, `thinking_sound_probability`, `transfer_destinations`, `human_transfer_mode`, `warm_transfer_summary_instructions`, `warm_transfer_voice_speed`, `ivr_navigation_enabled`, `voicemail_message`, `stt_context`, `stt_model`, `first_sentence_delay_ms`, `calendly`, `cal`, `google_calendar`, `hubspot`, `slack`, `teams`, `zoho`, `custom_tools`, `from_phone_number`, `precall_lookup_url`, `precall_lookup_headers`, `name`. ### Response 200 - `assistant` ([Assistant](https://www.getrevox.com/docs/api/objects/assistant.md)) - `unpatchedCallsNotice` (object, may be absent): Present when the update added prompt variables that some calls not yet completed have no value for: those calls keep the previous prompt. Absent otherwise. - `unpatchedCallsNotice.count` (number): Calls left on the previous prompt. - `unpatchedCallsNotice.variables` (array of string): The new prompt variables those calls have no value for. ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["prompt"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Delete an assistant `DELETE https://www.getrevox.com/api/assistants/{id}` Permanently delete an assistant by its ID. Any future calls referencing this assistant ID will fail. Existing call records that used this assistant are not affected. ### Request ```bash curl -X DELETE "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). ### Body No body: send the request without one. ### Response 200 ```json { "success": true } ``` - `success` (boolean): True when the assistant was deleted. --- ## Clone an assistant `POST https://www.getrevox.com/api/assistants/{id}/clone` Create a copy of an assistant with its whole configuration and its calendars (on the same connected accounts), named after it with " (Copy)" appended. ### Request ```bash curl -X POST "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/clone" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{}' ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). ### Body JSON. An empty object: send `{}` or no body at all. ### Response 200 - `assistant` ([Assistant](https://www.getrevox.com/docs/api/objects/assistant.md)) ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["phone_number"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - `500` Server error: `{"error":"Server error"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Turn the public demo page on or off `POST https://www.getrevox.com/api/assistants/{id}/demo-page` The demo page lets anyone with its link call the assistant and see the calls it placed, with their transcripts and recordings. Off by default. `enabled: true` turns it on with a new link; calling it again regenerates the link and the previous one stops working at once. `enabled: false` turns it off. ### Request ```bash curl -X POST "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/demo-page" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "enabled": true }' ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). ### Body JSON. - `enabled` (boolean, required): true: turn the page on with a new link (regenerates it if already on). false: turn it off. ### Response 200 ```json { "demo_page_url": "https://example.com" } ``` - `demo_page_url` (string | null): The page's link, or null when it is off. ### Errors - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Get assistant statistics `GET https://www.getrevox.com/api/assistants/{id}/statistics` Report on the inbound calls the assistant received, whatever their status: the total, the weekly volume over the last 12 weeks and the weekly average since the assistant went into service, the weekday and hour they arrive, and how long the answered ones lasted. Weeks, weekdays and hours are computed in Europe/Paris time. has_activity is false until the first inbound call, and weekly_average stays null until one full week of service has passed. ### Request ```bash curl -X GET "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/statistics" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). ### Body No body: send the request without one. ### Response 200 ```json { "statistics": { "assistant": { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "name": "Appointment reminder", "timezone": "Europe/Paris", "has_activity": false }, "activity": { "calls_total": 3, "first_call_at": "2026-11-05T09:00:00Z", "in_service_since": "in service since", "weekly_average": 1, "weeks": [{ "week_start": "2026-11-02", "count": 3 }], "current_week_start": "2026-11-02" }, "weekdays": { "days": [1], "hours": [1], "busiest_day": { "index": 1, "count": 3 }, "busiest_hour": { "start": 1, "count": 3 } }, "durations": { "average_seconds": 98, "buckets": { "under_1": 1, "from_1_to_2": 1, "from_2_to_3": 1, "over_3": 1 }, "unanswered": 1 } } } ``` - `statistics` (object): Report on the inbound calls the assistant received, over its whole history. - `statistics.assistant` (object): The assistant the report is about, and how it was computed. - `statistics.assistant.id` (string): ID of the assistant. - `statistics.assistant.name` (string): Name of the assistant. - `statistics.assistant.timezone` (string): IANA timezone every week, weekday and hour of the report is computed in: the assistant's. - `statistics.assistant.has_activity` (boolean): False when the assistant has never received an inbound call: the rest of the report is then all zeros and nulls. - `statistics.activity` (object): Inbound call volume over time. - `statistics.activity.calls_total` (number): Inbound calls the assistant has received, all time. - `statistics.activity.first_call_at` (string | null): When the assistant received its first inbound call, as an ISO datetime. Null when it has never received a call. - `statistics.activity.in_service_since` (string | null): Monday (ISO date, YYYY-MM-DD, in the report's timezone) of the week the assistant went into service: the first week whose volume reaches a quarter of its busiest week, so setup and test calls before go-live are left out. Null when it has never received a call. - `statistics.activity.weekly_average` (number | null): Average number of inbound calls per week over the complete weeks since `in_service_since`, the current unfinished week excluded, rounded to one decimal. Null until one full week of service has passed. - `statistics.activity.weeks` (array of object): Exactly 12 weeks, oldest first, weeks without calls included; the last one is the current, unfinished week. - `statistics.activity.weeks.week_start` (string): Monday that starts the week, as an ISO date (YYYY-MM-DD) in the report's timezone. - `statistics.activity.weeks.count` (number): Inbound calls received that week. - `statistics.activity.current_week_start` (string): Monday (ISO date, YYYY-MM-DD, in the report's timezone) of the current, unfinished week: the last entry of `weeks`. - `statistics.weekdays` (object): When inbound calls arrive, by weekday and hour, in the report's timezone. - `statistics.weekdays.days` (array of number): Inbound calls received on each day of the week, all time: 7 counts, Monday first. - `statistics.weekdays.hours` (array of number): Inbound calls received in each hour of the day, all time: 24 counts, from 0:00-1:00 to 23:00-24:00. - `statistics.weekdays.busiest_day` (object | null): The weekday with the most inbound calls (the earliest one on a tie). Null when the assistant has never received a call. - `statistics.weekdays.busiest_day.index` (number): Day of the week, 0 = Monday to 6 = Sunday. - `statistics.weekdays.busiest_day.count` (number): Inbound calls received on that day. - `statistics.weekdays.busiest_hour` (object | null): The one-hour slot of the day with the most inbound calls (the earliest one on a tie). Null when the assistant has never received a call. - `statistics.weekdays.busiest_hour.start` (number): Hour (0 to 23) that opens the busiest one-hour slot, e.g. 14 for 14:00-15:00. - `statistics.weekdays.busiest_hour.count` (number): Inbound calls received in that slot. - `statistics.durations` (object): How long the answered inbound calls lasted. - `statistics.durations.average_seconds` (number | null): Average duration of answered calls, in seconds, rounded. Null when no call was answered. - `statistics.durations.buckets` (object): Answered calls counted by duration, measured from pick-up to hang-up. - `statistics.durations.buckets.under_1` (number): Answered calls shorter than 1 minute. - `statistics.durations.buckets.from_1_to_2` (number): Answered calls from 1 minute (included) to 2 minutes (excluded). - `statistics.durations.buckets.from_2_to_3` (number): Answered calls from 2 minutes (included) to 3 minutes (excluded). - `statistics.durations.buckets.over_3` (number): Answered calls of 3 minutes or more. - `statistics.durations.unanswered` (number): Inbound calls whose last attempt was not answered or has not ended, so it has no duration. ### Errors - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Add a calendar to an assistant `POST https://www.getrevox.com/api/assistants/{id}/calendars` Add a calendar on a provider, before any account is connected to it. Then create an invite link for the account owner to connect it: connecting gives it the handle the prompt mentions, named after the account (`google_calendar_jane_at_example.com`). ### Before you call - Next, create an invite link with [`POST /assistants/{id}/calendars/{calendarId}/invite`](https://www.getrevox.com/docs/api/assistants/create-an-invite-link-for-a-calendar.md) and give `invite.url` to the owner of the account. On that page they sign in to their provider and pick the calendar to book on; no Revox account is needed. - Poll [`GET /assistants/{id}/calendars`](https://www.getrevox.com/docs/api/assistants/list-an-assistants-calendars.md) until the calendar's `status` is `ready`. On `needs_setup`, list what it can book on with GET .../options and pick one with PUT .../selection. - Once `ready`, the agent can book on it. With several calendars, say in the prompt which one fits which meeting by its mention: `@` followed by its `handle` (e.g. `@google_calendar_jane_at_example.com`). ### Request Adds a calendar with no account yet: its status is not_connected. ```bash curl -X POST "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/calendars" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "provider": "google-calendar" }' ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). ### Body JSON. - `provider` ("google-calendar" | "calendly" | "cal-com-oauth", required): Calendar provider. - `"google-calendar"`: Google Calendar: books on a calendar of the account, with the opening hours and meeting length of its settings. - `"calendly"`: Calendly: books an event type of the account. - `"cal-com-oauth"`: Cal.com: books an event type of the account. ### Response 200 - `calendar` ([AssistantCalendar](https://www.getrevox.com/docs/api/objects/assistant-calendar.md)) ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["provider"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Create an invite link for a calendar `POST https://www.getrevox.com/api/assistants/{id}/calendars/{calendarId}/invite` A link for the owner of an account to connect it to the calendar, on the calendar's provider, without a Revox account: give them invite.url. A new link replaces the previous one, which stops working. Returns 400 when an account is already connected. ### Before you call - Give `invite.url` only to the owner of the account: anyone holding the link can connect an account to the calendar until it expires (`invite.expires_at`). - Then poll [`GET /assistants/{id}/calendars`](https://www.getrevox.com/docs/api/assistants/list-an-assistants-calendars.md) until the calendar's `status` is `ready`. ### Request ```bash curl -X POST "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/calendars/b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e/invite" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). - `calendarId` (string, required): ID of the calendar, from the assistant's `calendars` list or [`GET /assistants/{id}/calendars`](https://www.getrevox.com/docs/api/assistants/list-an-assistants-calendars.md). ### Body No body: send the request without one. ### Response 200 - `calendar` ([AssistantCalendar](https://www.getrevox.com/docs/api/objects/assistant-calendar.md)) ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["phone_number"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## List an assistant's calendars `GET https://www.getrevox.com/api/assistants/{id}/calendars` The calendars the assistant books meetings on during a call, in the order they were added. Each has a handle the prompt mentions, a status, and the account it is connected to. ### Request ```bash curl -X GET "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/calendars" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). ### Body No body: send the request without one. ### Response 200 - `calendars` (array of [AssistantCalendar](https://www.getrevox.com/docs/api/objects/assistant-calendar.md)): The assistant's calendars, oldest first. ### Errors - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## List what a calendar can book on `GET https://www.getrevox.com/api/assistants/{id}/calendars/{calendarId}/options` The calendars (Google) or event types (Calendly, Cal.com) of the account connected to the calendar, to pick the one it books on with PUT .../selection. Returns 400 when no account is connected. ### Before you call - Only an option with `bookable` true can be picked. A `notice` means the account's plan will stop bookings: tell the account owner. ### Request ```bash curl -X GET "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/calendars/b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e/options" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). - `calendarId` (string, required): ID of the calendar, from the assistant's `calendars` list or [`GET /assistants/{id}/calendars`](https://www.getrevox.com/docs/api/assistants/list-an-assistants-calendars.md). ### Body No body: send the request without one. ### Response 200 ```json { "options": [ { "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "name": "Appointment reminder", "detail": "30 min", "bookable": false } ], "selected_option_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "notice": "calendly_free_plan" } ``` - `options` (array of object): The calendars (Google) or event types (Calendly, Cal.com) of the connected account. - `options.id` (string): What to pass as option_id to PUT .../selection: a Google calendar ID, or a Calendly or Cal.com event type. - `options.name` (string): Name of the calendar or event type. - `options.detail` (string | null): What tells two similar options apart, e.g. '30 min' or a team name. Null when there is nothing to add. Example: `"30 min"`. - `options.bookable` (boolean): False for a Google calendar shared with the account read-only: listed so the user sees it, but meetings cannot be booked on it until its owner grants "Make changes to events". - `selected_option_id` (string | null): The option the calendar books on now. Null until one is picked. - `notice` ("calendly_free_plan" | "calendly_trial" | null): Something about the account that will stop bookings. Null when there is nothing to report. - `"calendly_free_plan"`: The Calendly account is on the free plan: Calendly only books through its API on a paid plan (Standard or above), so the agent will see the slots but cannot book them. - `"calendly_trial"`: The Calendly account is on a trial: Calendly only books through its API on a paid plan (Standard or above). Without one, the agent will see the slots but cannot book them. ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["phone_number"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - `500` Server error: `{"error":"Server error"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Change a calendar's settings `PATCH https://www.getrevox.com/api/assistants/{id}/calendars/{calendarId}` The settings of its provider: opening hours, meeting length and Meet link for Google Calendar, the event type for Calendly and Cal.com. ### Before you call - `settings` must match the calendar's provider: Google Calendar settings for a `google-calendar` calendar, an event type for Calendly and Cal.com. The calendar must be connected first. ### Request 30-minute meetings with a Meet link, Monday to Friday from 09:00 to 18:00, Paris time, on the account's main calendar. ```bash curl -X PATCH "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/calendars/b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "settings": { "calendar_id": "primary", "time_zone": "Europe/Paris", "duration_minutes": 30, "days": [1, 2, 3, 4, 5], "start_time": "09:00", "end_time": "18:00", "google_meet": true } }' ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). - `calendarId` (string, required): ID of the calendar, from the assistant's `calendars` list or [`GET /assistants/{id}/calendars`](https://www.getrevox.com/docs/api/assistants/list-an-assistants-calendars.md). ### Body JSON. - `settings` (object, required): Must match the calendar's provider. - Option `Google Calendar` - `settings.calendar_id` (string, required): ID of the Google calendar to book on: 'primary' for the account's main calendar, or an id from [`GET /assistants/{id}/calendars/{calendarId}/options`](https://www.getrevox.com/docs/api/assistants/list-what-a-calendar-can-book-on.md). Example: `"primary"`. - `settings.time_zone` (string, required): IANA timezone of start_time and end_time. Example: `"Europe/Paris"`. - `settings.duration_minutes` (integer, optional, default 30): Length of a booked meeting, in minutes. Default: 30. 5 to 480. - `settings.days` (array of integer, optional, default [1,2,3,4,5]): Open days, from 0 (Sunday) to 6 (Saturday). Default: Monday to Friday. Each item 0 to 6. - `settings.start_time` (string, optional, default "09:00"): Opening time of each open day, 'HH:mm' 24-hour, in time_zone: no meeting is booked before it. Default: '09:00'. Pattern ^\d{2}:\d{2}$. - `settings.end_time` (string, optional, default "18:00"): Closing time of each open day, 'HH:mm' 24-hour, in time_zone: a meeting must end by then. Default: '18:00'. Pattern ^\d{2}:\d{2}$. - `settings.google_meet` (boolean, optional, default true): Adds a Google Meet link to the meeting. Default: true. A calendar whose Google Workspace does not allow Meet gets the meeting without the link. - `settings.location` (string | null, optional, default null): Where the meeting takes place, written in the calendar event and the invitation. Can use the call's prompt variables, e.g. '{{site_address}}': a variable the call does not have is left out. Null (default): no location. At most 500 characters. - Option `Calendly` Example: `{"event_type_id":"https://api.calendly.com/event_types/0b6e1f3a-7c2d-4e8b-9a5f-3d2c1b0a9e8f"}`. - `settings.event_type_id` (string, required): The Calendly event type to book, by its URI, as [`GET /assistants/{id}/calendars/{calendarId}/options`](https://www.getrevox.com/docs/api/assistants/list-what-a-calendar-can-book-on.md) lists it. At least 1 character. Example: `"https://api.calendly.com/event_types/0b6e1f3a-7c2d-4e8b-9a5f-3d2c1b0a9e8f"`. - Option `Cal.com` Example: `{"event_type_id":"1234567"}`. - `settings.event_type_id` (string, required): ID of the Cal.com event type to book, as [`GET /assistants/{id}/calendars/{calendarId}/options`](https://www.getrevox.com/docs/api/assistants/list-what-a-calendar-can-book-on.md) lists it. At least 1 character. Example: `"1234567"`. ### Response 200 - `calendar` ([AssistantCalendar](https://www.getrevox.com/docs/api/objects/assistant-calendar.md)) ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["settings"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Connect an account to a calendar `PUT https://www.getrevox.com/api/assistants/{id}/calendars/{calendarId}/connection` Connect the calendar to an account your organization already uses on its provider. The calendar takes the handle of that account (`google_calendar_jane_at_example.com`, then `_2` for a second calendar on the same account); reconnecting the same account keeps the handle. Google's primary calendar, or the account's only event type, is picked right away; otherwise pick one with GET .../options and PUT .../selection. ### Before you call - `connection_id` must already belong to your organization: take `connection.connection_id` from another calendar of yours connected to the same account, on the same provider. To connect a new account, create an invite link ([`POST /assistants/{id}/calendars/{calendarId}/invite`](https://www.getrevox.com/docs/api/assistants/create-an-invite-link-for-a-calendar.md)) instead. - Google's primary calendar, or the account's only event type, is picked right away. Otherwise the calendar is `needs_setup`: pick what it books on with GET .../options and PUT .../selection. ### Request ```bash curl -X PUT "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/calendars/b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e/connection" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d" }' ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). - `calendarId` (string, required): ID of the calendar, from the assistant's `calendars` list or [`GET /assistants/{id}/calendars`](https://www.getrevox.com/docs/api/assistants/list-an-assistants-calendars.md). ### Body JSON. - `connection_id` (string, required): ID of a connection your organization already has to an account on the calendar's provider: the connection.connection_id of another calendar connected to that account. To connect a new account, create an invite link instead. ### Response 200 - `calendar` ([AssistantCalendar](https://www.getrevox.com/docs/api/objects/assistant-calendar.md)) ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["connection_id"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Remove a calendar from an assistant `DELETE https://www.getrevox.com/api/assistants/{id}/calendars/{calendarId}` The agent stops booking on it. The account connection is deleted too, unless another calendar still uses it. ### Request ```bash curl -X DELETE "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/calendars/b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). - `calendarId` (string, required): ID of the calendar, from the assistant's `calendars` list or [`GET /assistants/{id}/calendars`](https://www.getrevox.com/docs/api/assistants/list-an-assistants-calendars.md). ### Body No body: send the request without one. ### Response 200 ```json { "success": true } ``` - `success` (boolean): True when the calendar was removed. ### Errors - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Disconnect a calendar's account `DELETE https://www.getrevox.com/api/assistants/{id}/calendars/{calendarId}/connection` The calendar keeps its handle, which the agent then treats as not available, and waits for an account. Its invite link is revoked. ### Request ```bash curl -X DELETE "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/calendars/b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e/connection" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). - `calendarId` (string, required): ID of the calendar, from the assistant's `calendars` list or [`GET /assistants/{id}/calendars`](https://www.getrevox.com/docs/api/assistants/list-an-assistants-calendars.md). ### Body No body: send the request without one. ### Response 200 - `calendar` ([AssistantCalendar](https://www.getrevox.com/docs/api/objects/assistant-calendar.md)) ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["phone_number"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Revoke a calendar's invite link `DELETE https://www.getrevox.com/api/assistants/{id}/calendars/{calendarId}/invite` The calendar's invite link stops working right away, and its `invite` becomes null. An account a colleague already connected through the link stays connected. ### Request ```bash curl -X DELETE "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/calendars/b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e/invite" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). - `calendarId` (string, required): ID of the calendar, from the assistant's `calendars` list or [`GET /assistants/{id}/calendars`](https://www.getrevox.com/docs/api/assistants/list-an-assistants-calendars.md). ### Body No body: send the request without one. ### Response 200 - `calendar` ([AssistantCalendar](https://www.getrevox.com/docs/api/objects/assistant-calendar.md)) ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["phone_number"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Pick what a calendar books on `PUT https://www.getrevox.com/api/assistants/{id}/calendars/{calendarId}/selection` Set the calendar (Google) or event type (Calendly, Cal.com) of the connected account the calendar books on, with an id from GET .../options. A Google calendar shared read-only is refused with 400. The calendar is then ready to take bookings. ### Request ```bash curl -X PUT "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/calendars/b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e/selection" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "option_id": "sales-team@example.com" }' ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). - `calendarId` (string, required): ID of the calendar, from the assistant's `calendars` list or [`GET /assistants/{id}/calendars`](https://www.getrevox.com/docs/api/assistants/list-an-assistants-calendars.md). ### Body JSON. - `option_id` (string, required): The id of a bookable option from [`GET /assistants/{id}/calendars/{calendarId}/options`](https://www.getrevox.com/docs/api/assistants/list-what-a-calendar-can-book-on.md). ### Response 200 - `calendar` ([AssistantCalendar](https://www.getrevox.com/docs/api/objects/assistant-calendar.md)) ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["option_id"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## List an assistant's pronunciations `GET https://www.getrevox.com/api/assistants/{id}/pronunciations` The words the assistant's voice must say a specific way, with the text sent to the voice in their place. ### Request ```bash curl -X GET "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/pronunciations" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). ### Body No body: send the request without one. ### Response 200 ```json { "pronunciations": [ { "id": "d4c3b2a1-9e8f-4a7b-8c6d-5e4f3a2b1c0d", "assistant_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "term": "Swile", "sounds_like": "swaïle, une seule syllabe, à l'anglaise", "replacement": "replacement", "versions": ["version"], "voice": { "provider": "cartesia", "id": "8e1f2a3b-4c5d-4e6f-9a0b-1c2d3e4f5a6b" }, "voice_changed": false, "created_at": "2026-11-05T09:00:00Z", "updated_at": "2026-11-05T09:00:00Z" } ] } ``` - `pronunciations` (array of object) - `pronunciations.id` (string) - `pronunciations.assistant_id` (string) - `pronunciations.term` (string): The word or name as it is written in the prompt and as the assistant writes it, e.g. "Swile" or "Thibault Lhuillier". Matched whole-word and case-sensitively. 1 to 100 characters. Example: `"Swile"`. - `pronunciations.sounds_like` (string): How it must sound, as you would explain it to a colleague: a respelling in the call's language and any note on silent letters or English reading. 1 to 300 characters. Example: `"swaïle, une seule syllabe, à l'anglaise"`. - `pronunciations.replacement` (string | null): The text sent to the voice in place of `term` on calls. Null when the word as written was chosen. - `pronunciations.versions` (array of string): Every version that was offered when this one was chosen. - `pronunciations.voice` (object): The voice it was chosen on. The replacement applies only to calls with this voice: after a voice change, choose again. - `pronunciations.voice.provider` ("cartesia" | "elevenlabs" | "gradium"): The provider of the voice. - `pronunciations.voice.id` (string) - `pronunciations.voice_changed` (boolean): True when the assistant's voice is no longer the one it was chosen on, so it does not apply to calls until chosen again. - `pronunciations.created_at` (string): ISO 8601 timestamp. - `pronunciations.updated_at` (string): ISO 8601 timestamp. ### Errors - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Set how the voice says a word `PUT https://www.getrevox.com/api/assistants/{id}/pronunciations` Stores the version of a word the user chose by ear. On calls with the assistant's current voice, that text is sent to the voice in place of the word; the transcript keeps the word. ### Before you call - Send a version the user chose after listening to it ([`POST /assistants/{id}/pronunciations/suggest`](https://www.getrevox.com/docs/api/assistants/suggest-versions-of-a-word-to-choose-by-ear.md)): nothing checks the text, the voice reads it as is. - Setting a word that already exists replaces it. It applies to calls with the assistant's current voice only. - A word is one block: a term that holds another one, or is part of one ("Content" and "Content Square"), is refused with 400. Remove the other first. ### Request ```bash curl -X PUT "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/pronunciations" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "term": "Swile", "sounds_like": "swaïle, une seule syllabe, à l'\''anglaise", "text": "Swaïle", "versions": ["Swile", "Swaïle", "Souaïle"] }' ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). ### Body JSON. - `term` (string, required): The word or name as it is written in the prompt and as the assistant writes it, e.g. "Swile" or "Thibault Lhuillier". Matched whole-word and case-sensitively. 1 to 100 characters. Example: `"Swile"`. - `sounds_like` (string, required): How it must sound, as you would explain it to a colleague: a respelling in the call's language and any note on silent letters or English reading. 1 to 300 characters. Example: `"swaïle, une seule syllabe, à l'anglaise"`. - `text` (string, required): The version chosen, sent to the voice in place of the word on calls. The word itself means no replacement. 1 to 500 characters. - `versions` (array of string, optional, default []): Every version that was offered, kept to choose again later without a new recording. At most 10 items, each item 1 to 500 characters. ### Response 200 ```json { "pronunciation": { "id": "d4c3b2a1-9e8f-4a7b-8c6d-5e4f3a2b1c0d", "assistant_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "term": "Swile", "sounds_like": "swaïle, une seule syllabe, à l'anglaise", "replacement": "replacement", "versions": ["version"], "voice": { "provider": "cartesia", "id": "8e1f2a3b-4c5d-4e6f-9a0b-1c2d3e4f5a6b" }, "voice_changed": false, "created_at": "2026-11-05T09:00:00Z", "updated_at": "2026-11-05T09:00:00Z" } } ``` - `pronunciation` (object) - `pronunciation.id` (string) - `pronunciation.assistant_id` (string) - `pronunciation.term` (string): The word or name as it is written in the prompt and as the assistant writes it, e.g. "Swile" or "Thibault Lhuillier". Matched whole-word and case-sensitively. 1 to 100 characters. Example: `"Swile"`. - `pronunciation.sounds_like` (string): How it must sound, as you would explain it to a colleague: a respelling in the call's language and any note on silent letters or English reading. 1 to 300 characters. Example: `"swaïle, une seule syllabe, à l'anglaise"`. - `pronunciation.replacement` (string | null): The text sent to the voice in place of `term` on calls. Null when the word as written was chosen. - `pronunciation.versions` (array of string): Every version that was offered when this one was chosen. - `pronunciation.voice` (object): The voice it was chosen on. The replacement applies only to calls with this voice: after a voice change, choose again. - `pronunciation.voice.provider` ("cartesia" | "elevenlabs" | "gradium"): The provider of the voice. - `pronunciation.voice.id` (string) - `pronunciation.voice_changed` (boolean): True when the assistant's voice is no longer the one it was chosen on, so it does not apply to calls until chosen again. - `pronunciation.created_at` (string): ISO 8601 timestamp. - `pronunciation.updated_at` (string): ISO 8601 timestamp. ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["term"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Remove a pronunciation `DELETE https://www.getrevox.com/api/assistants/{id}/pronunciations/{pronunciationId}` The voice says the word as written again. ### Request ```bash curl -X DELETE "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/pronunciations/3c90c3cc-0d44-4b50-8888-8dd25736052a" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). - `pronunciationId` (string, required): ID of the pronunciation, from [`GET /assistants/{id}/pronunciations`](https://www.getrevox.com/docs/api/assistants/list-an-assistants-pronunciations.md). ### Body No body: send the request without one. ### Response 200 ```json { "success": true } ``` - `success` (boolean): True when the pronunciation was removed. ### Errors - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Suggest versions of a word to choose by ear `POST https://www.getrevox.com/api/assistants/{id}/pronunciations/suggest` Hears how the word must sound (a recording of someone saying it, or `sounds_like`), writes up to five ways to spell it for the assistant's voice, the word as written first, and returns each one said by that voice in `sentence`. ### Before you call - Nothing is saved: play the versions to the user, then send the one they keep to [`PUT /assistants/{id}/pronunciations`](https://www.getrevox.com/docs/api/assistants/set-how-the-voice-says-a-word.md). - Send a recording of the word (a few seconds, WAV, MP3, OGG, FLAC or AAC; a browser records WebM, convert it to WAV first), or `sounds_like` as text. - Takes about 5 to 10 seconds: one Gemini call, then every version synthesized at once. ### Request #### Example: From a recording audio_base64 is the recording (shortened here): someone saying the word the way the voice must say it. ```bash curl -X POST "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/pronunciations/suggest" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "term": "Swile", "sentence": "Je vous appelle de la part de Swile.", "audio_base64": "UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YQAAAAA=", "mime_type": "audio/wav" }' ``` #### Example: From a typed description ```json { "term": "Lefebvre", "sentence": "Vous avez rendez-vous avec Maître Lefebvre.", "sounds_like": "le-fèvre, le b est muet" } ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). ### Body JSON. - `term` (string, required): The word or name as it is written in the prompt and as the assistant writes it, e.g. "Swile" or "Thibault Lhuillier". Matched whole-word and case-sensitively. 1 to 100 characters. Example: `"Swile"`. - `sentence` (string, optional): A sentence holding the word, as the assistant says it (e.g. the prompt's sentence that mentions it), to hear each version in context. Defaults to the word alone. At most 300 characters. - `audio_base64` (string, optional): A recording of someone saying the word the way the voice must say it, base64-encoded without a data: prefix. A few seconds is enough. Send it with `mime_type`, or send `sounds_like` instead. 1 to 3000000 characters. - `mime_type` (enum (5 values), optional): Format of the recording. Values: `"audio/wav"`, `"audio/mpeg"`, `"audio/ogg"`, `"audio/flac"`, `"audio/aac"`. - `sounds_like` (string, optional): How it must sound, typed instead of a recording: a respelling in the call's language and any note on silent letters or English reading. 1 to 300 characters. Example: `"swaïle, une seule syllabe, à l'anglaise"`. ### Response 200 ```json { "sounds_like": "swaïle, une seule syllabe, à l'anglaise", "versions": [ { "text": "Hello, this is Julie from Acme.", "audio_base64": "audio base64" } ] } ``` - `sounds_like` (string): How the word must sound, from the recording or as sent. Send it back to POST /assistants/{id}/pronunciations. 1 to 300 characters. Example: `"swaïle, une seule syllabe, à l'anglaise"`. - `versions` (array of object): Up to 5 ways to write the word for the assistant's voice, each with its audio, to listen to and choose from. - `versions.text` (string): The text that would be sent to the voice in place of the word. The first version is the word as written. - `versions.audio_base64` (string): The assistant's voice saying `sentence` with this text, base64-encoded WAV. ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["term"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Hear the voice say a word or one of its versions `POST https://www.getrevox.com/api/assistants/{id}/pronunciations/say` Returns the assistant's voice saying `text` exactly as sent, without applying any of its pronunciations: the word as written is how callers hear it before one is set. ### Before you call - Nothing is saved: send the word as written to hear whether it needs a pronunciation, or a pronunciation's `replacement` to hear the one in use. ### Request ```bash curl -X POST "https://www.getrevox.com/api/assistants/3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34/pronunciations/say" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Swile" }' ``` ### Path parameters - `id` (string, required): ID of the assistant, as returned by [`GET /assistants`](https://www.getrevox.com/docs/api/assistants/get-assistants.md). ### Body JSON. - `text` (string, required): What the voice says: the word as written (how callers hear it with no pronunciation), or a version of it (`replacement` of a pronunciation, or a suggested version's `text`). 1 to 500 characters. Example: `"Swile"`. ### Response 200 ```json { "audio_base64": "audio base64" } ``` - `audio_base64` (string): The assistant's voice saying `text` exactly as sent, base64-encoded WAV. ### Errors - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Create a campaign `POST https://www.getrevox.com/api/campaigns` Create an outbound calling campaign. Every contact becomes a call in the `not_launched` status: nothing is dialed until [`POST /campaigns/{id}/launch-calls`](https://www.getrevox.com/docs/api/campaigns/launch-a-campaigns-calls.md) sends them. ### Before you call - Nothing is dialed at creation: every contact becomes a call in status `not_launched`. Send them with [`POST /campaigns/{id}/launch-calls`](https://www.getrevox.com/docs/api/campaigns/launch-a-campaigns-calls.md). - `name` must be unique in your organization. One contact on the do-not-call list fails the whole request with 400: screen the numbers first with [`POST /calls/screen-do-not-call`](https://www.getrevox.com/docs/api/calls/find-which-phone-numbers-are-on-the-do-not-call-list.md). - Send in each contact's `prompt_variables` every `{{variable}}` the assistant uses. Without `call_retry_config`, the campaign follows the default configuration, not the assistant's. ### Request Each contact's prompt_variables fill the assistant's {{first_name}} and {{company}}. The calls wait in not_launched until POST /campaigns/{id}/launch-calls. ```bash curl -X POST "https://www.getrevox.com/api/campaigns" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "November reminders", "assistant_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "contacts": [ { "to_phone_number": "+33612345678", "prompt_variables": { "first_name": "Marie", "company": "Acme" } }, { "to_phone_number": "+33698765432", "prompt_variables": { "first_name": "Jane", "company": "Globex" } }, { "to_phone_number": "+33645127893", "prompt_variables": { "first_name": "Lucas", "company": "Initech" } } ] }' ``` ### Body JSON. - `name` (string, required): Name of the campaign, unique within your organization. At least 1 character. - `assistant_id` (string (uuid), required): ID of the assistant that places the calls. It cannot be changed afterwards. - `contacts` (array of object, required): The contacts to call, at least one. A number listed twice is added once. At least 1 item. - `contacts.to_phone_number` (string, required): The contact's phone number, in E.164 format (e.g. +33612345678). Must be a valid number. - `contacts.prompt_variables` (object, optional): Values of the assistant's {{variables}} for this contact, keyed by variable name (e.g. {"first_name": "Marie"}). Default: {}. Keys: Variable name, as written between the braces: name for {{name}}. - `from_phone_number` (string, optional): Caller ID of the campaign's calls: a number of your organization, in E.164 format. A French mobile number (06, 07) cannot be the caller ID of an automated call. Omitted: the assistant's from_phone_number, or else a Revox number chosen for each destination. - `max_concurrent_calls` (number, optional): Maximum number of the campaign's calls in progress at the same time. Omitted: only your organization's limit applies. ≥ 1. - `call_retry_config` (object, optional): When and how often the campaign's calls are dialed. Omitted: the default configuration, not the assistant's. - `call_retry_config.calling_windows` (array of object, required): Daily time windows in which calls may be placed, on the allowed_days. A call due outside every window waits for the next one to open. Request bodies need at least one window. - `call_retry_config.calling_windows.calling_window_start_time` (string, required): Start time of the calling window, in `timezone` (each callee's own timezone when it is null). Format: 'HH:mm' (24-hour) or 'h:mma' (12-hour, minutes required). Examples: '09:00', '10:00am'. Default: '10:00'. - `call_retry_config.calling_windows.calling_window_end_time` (string, required): End time of the calling window, in `timezone` (each callee's own timezone when it is null). Must be after the start time: a window cannot span midnight. Format: 'HH:mm' (24-hour) or 'h:mma' (12-hour, minutes required). Examples: '17:00', '6:00pm'. Default: '18:00'. - `call_retry_config.calling_windows.retry_delay_seconds` (integer, optional, default 7200): Delay between retry attempts in seconds. Values below the 15-minute minimum are raised to it: a shorter delay means calling someone again minutes after they declined. For one deliberate immediate second dial, use call_twice_in_a_row. Default: 7200 (2 hours). ≥ 0. - `call_retry_config.max_retry_attempts` (integer, optional, default 5): Maximum number of call attempts, first call included. Default: 5. Capped by the organization's plan: 5 on Starter, 8 on Business. A contact nobody picks up is billed once all its attempts were placed. > 0. - `call_retry_config.allowed_days` (array of enum (7 values), optional, default ["monday","tuesday","wednesday","thursday","friday"]): Days of the week when calls are allowed, in the same timezone as the calling windows. Default: Monday through Friday. Values: `"monday"`, `"tuesday"`, `"wednesday"`, `"thursday"`, `"friday"`, `"saturday"`, `"sunday"`. - `call_retry_config.excluded_dates` (array of string (date), optional): Calendar dates on which no call goes out, such as public holidays or days the office is closed, as 'YYYY-MM-DD' (e.g. ['2026-12-25', '2027-01-01']). Read in the same timezone as the calling windows: each callee's local date when timezone is null. A call or retry that would land on an excluded date waits for the next open window after it. Up to 366 dates; duplicates are removed and the list is sorted. A call placed with skip_calling_window ignores them for its first dial only. Default: none. At most 366 items. - `call_retry_config.call_twice_in_a_row` (boolean, optional, default false): Double call. If true and max_retry_attempts >= 2, when the first attempt reaches nobody (no answer, declined, voicemail, call screening nobody took), the second attempt is dialed within seconds instead of after retry_delay_seconds, from the same caller number. Two calls in a row from one number raise the pickup rate. Each call is an attempt: the double call counts as 2 when both calls happen, 1 when the first is picked up. Busy or unreachable phones are retried after the normal delay. Calling days and hours still apply. Only the first attempt is doubled; later ones follow retry_delay_seconds. A voicemail_message is left on the second dial only. Default: false. - `call_retry_config.timezone` (string | null, optional, deprecated): Deprecated: use the `timezone` field of the assistant, the campaign or [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md). Still accepted on writes and copied there, and returned with that value. Null no longer means each callee's own timezone: a call's timezone is never derived from its phone number. - `timezone` (string | null, optional): IANA timezone of this campaign's calls, in place of its assistant's: calling windows, the agent's date and calendar slots, callbacks and extracted datetimes. Null: the assistant's timezone, followed live. [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md) `timezone` still overrides it for one call. Replaces the deprecated `call_retry_config.timezone`. ### Response 200 - `campaign` ([Campaign](https://www.getrevox.com/docs/api/objects/campaign.md)) ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["name"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `402` Not enough credits on the organization: `{"error":"Insufficient credits. Please buy credits to make calls.","code":"INSUFFICIENT_BALANCE"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Get campaign by ID `GET https://www.getrevox.com/api/campaigns/{id}` Retrieve the full details of a single campaign by its unique ID. Can be used to poll for campaign completion. ### Request ```bash curl -X GET "https://www.getrevox.com/api/campaigns/9b2d7e41-6c3f-4a8e-b5d0-2f7a1c9e4b63" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the campaign, as returned by [`GET /campaigns`](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md). ### Body No body: send the request without one. ### Response 200 - `campaign` ([Campaign](https://www.getrevox.com/docs/api/objects/campaign.md)) ### Errors - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## List campaigns `GET https://www.getrevox.com/api/campaigns` Retrieve all campaigns for your organization, including both active and completed ones. ### Request ```bash curl -X GET "https://www.getrevox.com/api/campaigns" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Body No body: send the request without one. ### Response 200 - `campaigns` (array of [Campaign](https://www.getrevox.com/docs/api/objects/campaign.md)): Every campaign of the organization. --- ## Update a campaign `PATCH https://www.getrevox.com/api/campaigns/{id}` Update a campaign's name, outbound number, retry configuration (calling hours, retry delay, max attempts) and concurrency cap. Changes are applied to the campaign's calls that have not completed yet. The assistant is fixed at creation; add contacts with [`POST /campaigns/{id}/rows`](https://www.getrevox.com/docs/api/campaigns/add-contacts-to-a-campaign.md), and choose when calls go out with [`POST /campaigns/{id}/launch-calls`](https://www.getrevox.com/docs/api/campaigns/launch-a-campaigns-calls.md). ### Request ```bash curl -X PATCH "https://www.getrevox.com/api/campaigns/9b2d7e41-6c3f-4a8e-b5d0-2f7a1c9e4b63" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Appointment reminder", "from_phone_number": "+33187654321" }' ``` ### Path parameters - `id` (string, required): ID of the campaign, as returned by [`GET /campaigns`](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md). ### Body JSON. - `name` (string, optional): Campaign display name. 1 to 255 characters. - `from_phone_number` (string | null, optional): The phone number to use for outbound calls. Editable after launch; applied to the campaign's calls that have not completed yet. - `max_concurrent_calls` (number | null, optional): Maximum concurrent calls. Editable after launch. ≥ 1. - `call_retry_config` (object | null, optional): Override retry configuration (calling hours, retry delay, max attempts). Editable after launch; applied to the campaign's calls that have not completed yet, whose next attempt is re-scheduled under the new configuration. Its max_retry_attempts is only the default for max_attempts in [`POST /campaigns/{id}/launch-calls`](https://www.getrevox.com/docs/api/campaigns/launch-a-campaigns-calls.md). - `call_retry_config.calling_windows` (array of object, required): Daily time windows in which calls may be placed, on the allowed_days. A call due outside every window waits for the next one to open. Request bodies need at least one window. - `call_retry_config.calling_windows.calling_window_start_time` (string, required): Start time of the calling window, in `timezone` (each callee's own timezone when it is null). Format: 'HH:mm' (24-hour) or 'h:mma' (12-hour, minutes required). Examples: '09:00', '10:00am'. Default: '10:00'. - `call_retry_config.calling_windows.calling_window_end_time` (string, required): End time of the calling window, in `timezone` (each callee's own timezone when it is null). Must be after the start time: a window cannot span midnight. Format: 'HH:mm' (24-hour) or 'h:mma' (12-hour, minutes required). Examples: '17:00', '6:00pm'. Default: '18:00'. - `call_retry_config.calling_windows.retry_delay_seconds` (integer, optional, default 7200): Delay between retry attempts in seconds. Values below the 15-minute minimum are raised to it: a shorter delay means calling someone again minutes after they declined. For one deliberate immediate second dial, use call_twice_in_a_row. Default: 7200 (2 hours). ≥ 0. - `call_retry_config.max_retry_attempts` (integer, optional, default 5): Maximum number of call attempts, first call included. Default: 5. Capped by the organization's plan: 5 on Starter, 8 on Business. A contact nobody picks up is billed once all its attempts were placed. > 0. - `call_retry_config.allowed_days` (array of enum (7 values), optional, default ["monday","tuesday","wednesday","thursday","friday"]): Days of the week when calls are allowed, in the same timezone as the calling windows. Default: Monday through Friday. Values: `"monday"`, `"tuesday"`, `"wednesday"`, `"thursday"`, `"friday"`, `"saturday"`, `"sunday"`. - `call_retry_config.excluded_dates` (array of string (date), optional): Calendar dates on which no call goes out, such as public holidays or days the office is closed, as 'YYYY-MM-DD' (e.g. ['2026-12-25', '2027-01-01']). Read in the same timezone as the calling windows: each callee's local date when timezone is null. A call or retry that would land on an excluded date waits for the next open window after it. Up to 366 dates; duplicates are removed and the list is sorted. A call placed with skip_calling_window ignores them for its first dial only. Default: none. At most 366 items. - `call_retry_config.call_twice_in_a_row` (boolean, optional, default false): Double call. If true and max_retry_attempts >= 2, when the first attempt reaches nobody (no answer, declined, voicemail, call screening nobody took), the second attempt is dialed within seconds instead of after retry_delay_seconds, from the same caller number. Two calls in a row from one number raise the pickup rate. Each call is an attempt: the double call counts as 2 when both calls happen, 1 when the first is picked up. Busy or unreachable phones are retried after the normal delay. Calling days and hours still apply. Only the first attempt is doubled; later ones follow retry_delay_seconds. A voicemail_message is left on the second dial only. Default: false. - `call_retry_config.timezone` (string | null, optional, deprecated): Deprecated: use the `timezone` field of the assistant, the campaign or [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md). Still accepted on writes and copied there, and returned with that value. Null no longer means each callee's own timezone: a call's timezone is never derived from its phone number. - `timezone` (string | null, optional): IANA timezone of this campaign's calls, in place of its assistant's: calling windows, the agent's date and calendar slots, callbacks and extracted datetimes. Null: the assistant's timezone, followed live. [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md) `timezone` still overrides it for one call. Replaces the deprecated `call_retry_config.timezone`. ### Response 200 - `campaign` ([Campaign](https://www.getrevox.com/docs/api/objects/campaign.md)) ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["name"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Delete a campaign `DELETE https://www.getrevox.com/api/campaigns/{id}` Permanently delete a campaign and all its associated rows. This action is irreversible. In-progress calls will not be affected, but no new calls will be placed. ### Request ```bash curl -X DELETE "https://www.getrevox.com/api/campaigns/9b2d7e41-6c3f-4a8e-b5d0-2f7a1c9e4b63" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the campaign, as returned by [`GET /campaigns`](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md). ### Body No body: send the request without one. ### Response 200 ```json { "success": true } ``` - `success` (boolean): True when the operation succeeded. --- ## Launch a campaign's calls `POST https://www.getrevox.com/api/campaigns/{id}/launch-calls` Send the campaign's calls matching a selection. In ai_first mode each call is dialed from the requested time, inside the calling windows, and follows the retry configuration from there. In speed_dial mode a live operator session dials them, and any call waiting on an AI retry is un-scheduled first so the same contact is never dialed twice. Calls the AI is already dialing are skipped. In ai_first mode, contacts already reached (a person answered, or they called in) are skipped too; other finished or cancelled calls are launched again. ### Before you call - Use `ai_first` from the API: `speed_dial` puts the user who launched it through to the contacts live, in the dashboard, and cannot be scheduled. - Calls the AI is already dialing are skipped. In ai_first mode, contacts already reached (a person answered, or they called in) are skipped too (skipped.already_reached); other finished or cancelled calls are launched again. Launching also resumes a cancelled campaign. - `scheduled_at` is UTC and ends in `Z`. Returns 402 when your credits do not cover the selection, and 400 when no call matches it. ### Request #### Example: Every call, now The smallest body: every call of the campaign, now. ```bash curl -X POST "https://www.getrevox.com/api/campaigns/9b2d7e41-6c3f-4a8e-b5d0-2f7a1c9e4b63/launch-calls" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "mode": "ai_first", "selection": { "filters": {} } }' ``` #### Example: Calls never launched, on Monday morning Only the calls still waiting in not_launched, from November 9 at 08:30 UTC. ```json { "mode": "ai_first", "scheduled_at": "2026-11-09T08:30:00Z", "selection": { "filters": { "statuses": ["not_launched"] } } } ``` ### Path parameters - `id` (string, required): ID of the campaign, as returned by [`GET /campaigns`](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md). ### Body JSON. - `mode` ("ai_first" | "speed_dial", required): How the calls are placed. - `"ai_first"`: The AI agent places the calls, at scheduled_at or as soon as each contact's calling window opens, then follows the campaign's retry configuration. - `"speed_dial"`: A live session in the dashboard: the user who launched it is put through to the first contact who answers. It cannot be scheduled, and only one runs per campaign. - `selection` (object, required): Which of the campaign's calls to launch. - `selection.filters` (object, required): Filters on the campaign's calls, as in [`POST /call/search`](https://www.getrevox.com/docs/api/calls/search-calls.md). Pass {} to select every call of the campaign. - `selection.filters.query` (string, optional): Free-text search. A call matches when it contains every word of the query (3 characters or more, in any order) in its phone numbers, contact identity, metadata or prompt variable values, or in the extracted data of its last attempt. A phone number typed with spaces or a leading 0 is matched on its digits. - `selection.filters.statuses` (array of enum (10 values), optional, default []): Keep calls in any of these statuses. A scheduled call of a paused campaign counts as 'paused'. - `"initializing"`: Being created, not scheduled yet. Newer calls start as scheduled instead. - `"queued_for_calling"`: Its turn came: the attempt is about to dial, within your concurrent call limit. - `"calling"`: An attempt is in progress: the phone is ringing or a conversation is going on. - `"post_processing"`: The phone conversation is over; the transcript, outcome and extracted data are being computed. It can no longer be paused or cancelled. - `"not_launched"`: Created but never sent: a campaign call waiting for [`POST /campaigns/{id}/launch-calls`](https://www.getrevox.com/docs/api/campaigns/launch-a-campaigns-calls.md). It is not dialed until then. - `"scheduled"`: Waiting to be dialed at scheduled_at (the first attempt, a retry or a requested callback). A call due outside its calling windows waits for the next one. - `"paused"`: No new attempt is made until it is resumed ([`POST /call/{id}/resume`](https://www.getrevox.com/docs/api/calls/resume-a-paused-call.md), or resuming its campaign). - `"completed"`: Final. Revox will not dial it again: a person or a phone menu answered, or the last attempt allowed by call_retry_config was made. outcome and last_call_attempt tell how it went. - `"cancelled"`: Final. Cancelled before it completed: by a user ([`POST /call/{id}/cancel`](https://www.getrevox.com/docs/api/calls/cancel-a-call.md), the dashboard, a campaign cancel), or because the prospect called back (see cancel_reason). - `"errored"`: Final. The call could not be placed and will not be retried: the number does not exist, the destination cannot be called, the organization ran out of credits, or an internal error stopped it. - `selection.filters.directions` (array of ("inbound" | "outbound"), optional, default []): Keep calls in any of these directions. - `"inbound"`: Someone called one of your numbers and an assistant answered. - `"outbound"`: Revox called the number: from [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md), a campaign or the dashboard. - `selection.filters.results` (array of enum (6 values), optional, default []): Keep calls whose last attempt has one of these results (who answered: human, voicemail, IVR...). 'none' matches calls whose last attempt has no result yet, or no attempt at all. - `"IVR"`: An automated phone menu answered (e.g. 'press 1 for sales'). - `"voicemail"`: A voicemail or an answering machine answered. - `"human"`: A person answered. - `"unknown"`: Silence, or audio that could not be classified. - `"screening-filter"`: A call screening assistant (Apple or Google) answered for the person and asked who is calling and why. - `"none"`: The last attempt has no result yet, or there is no attempt. - `selection.filters.outcomes` (array of enum (6 values), optional, default []): Keep calls with one of these business outcomes. 'none' matches calls without an outcome, 'do_not_call' calls whose number is on the do-not-call list (those match no other outcome value). - `"not_interested"`: The person declined, refused or showed no interest. - `"interested"`: The person engaged and is a lead to follow up: the strongest outcome the AI assigns. - `"completed"`: A person from your team talked to the prospect: they joined the call, the call was transferred to them, or they set this outcome by hand. Never assigned by the AI. - `"requested_callback_later"`: The person asked to be called back later. When they gave a time and attempts are left, the call is scheduled again for that time. - `"none"`: The call has no outcome. - `"do_not_call"`: The number is on the do-not-call list. Such a call matches no other outcome value. - `selection.filters.assignee_ids` (array of (string | "none"), optional, default []): Keep calls assigned to one of these team members (user IDs, see the call's assignee.id). 'none' matches unassigned calls. - `selection.filters.variables` (array of object, optional): Keep calls whose metadata (or, when the metadata has no such key, prompt variables) hold all these values. - `selection.filters.variables.key` (string, required): Name of the metadata entry or prompt variable. - `selection.filters.variables.value` (string, required): Value it must have, compared case-insensitively and ignoring surrounding spaces. - `selection.rows` (object, optional, default {"mode":"all_except","call_ids":[]}): Narrows the filtered calls down. Default: {"mode": "all_except", "call_ids": []}, every filtered call. - `selection.rows.mode` ("all_except" | "only", required): How call_ids narrow the filtered calls. - `"all_except"`: Every call the filters match, except call_ids. - `"only"`: Just the call_ids that the filters match. - `selection.rows.call_ids` (array of string, required): IDs of the campaign calls to exclude or to keep, per mode. - `scheduled_at` (string (date-time), optional): When to place the calls: ISO 8601 in UTC ending in Z, e.g. 2026-11-09T08:30:00Z; offsets such as +01:00 are rejected. Omitted: now. ai_first only: a speed dial session cannot be scheduled. - `max_attempts` (integer, optional): ai_first only. How many more attempts each launched call gets from now, replacing whatever it had left. Defaults to the campaign's max_retry_attempts. With the campaign's call_twice_in_a_row on, the double call counts as 2 of these attempts when both calls happen: with 1, there is no double call. > 0. ### Response 200 ```json { "launched": 1, "skipped": { "active": 1, "already_reached": 1, "attempts_exhausted": 0, "cancelled": 0 } } ``` - `launched` (number): Calls launched. - `skipped` (object): Calls of the selection that were not launched, by reason. - `skipped.active` (number): Calls left alone because the AI is already dialing them or analysing their last attempt. - `skipped.already_reached` (number): ai_first only: calls left alone because the contact was already reached (a person answered, or the contact called in). - `skipped.attempts_exhausted` (number): Not used anymore: always 0. - `skipped.cancelled` (number): Not used anymore: always 0. ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["mode"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `402` Not enough credits on the organization: `{"error":"Insufficient credits. Please buy credits to make calls.","code":"INSUFFICIENT_BALANCE"}` - `404` Not found in your organization: `{"error":"Not found"}` - `409` Conflicts with the resource's current state: `{"error":"Conflicts with the resource's current state"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Cancel a campaign `POST https://www.getrevox.com/api/campaigns/{id}/cancel` Cancel a running or scheduled campaign. Pending and queued calls will be aborted, while in-progress calls will be allowed to finish. Unlike deletion, the campaign and its rows are preserved for historical reference. ### Request ```bash curl -X POST "https://www.getrevox.com/api/campaigns/9b2d7e41-6c3f-4a8e-b5d0-2f7a1c9e4b63/cancel" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the campaign, as returned by [`GET /campaigns`](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md). ### Body No body: send the request without one. ### Response 200 ```json { "success": true } ``` - `success` (boolean): True when the operation succeeded. ### Errors - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Pause a running campaign `POST https://www.getrevox.com/api/campaigns/{id}/pause` Pause a running campaign so no further calls are placed. In-progress calls are allowed to finish; pending and scheduled calls are held until the campaign is resumed. Scheduled retry timers keep counting down, so a call resumed before its time fires on schedule, while one resumed after its time fires at the next available calling window. ### Request ```bash curl -X POST "https://www.getrevox.com/api/campaigns/9b2d7e41-6c3f-4a8e-b5d0-2f7a1c9e4b63/pause" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the campaign, as returned by [`GET /campaigns`](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md). ### Body No body: send the request without one. ### Response 200 ```json { "success": true } ``` - `success` (boolean): True when the operation succeeded. ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["phone_number"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Resume a paused campaign `POST https://www.getrevox.com/api/campaigns/{id}/resume` Resume a paused campaign. Held calls continue from where they left off; calls whose scheduled time passed during the pause are placed at the next available calling window. ### Request ```bash curl -X POST "https://www.getrevox.com/api/campaigns/9b2d7e41-6c3f-4a8e-b5d0-2f7a1c9e4b63/resume" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the campaign, as returned by [`GET /campaigns`](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md). ### Body No body: send the request without one. ### Response 200 ```json { "success": true } ``` - `success` (boolean): True when the operation succeeded. ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["phone_number"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Export campaign rows `GET https://www.getrevox.com/api/campaigns/{id}/export` Export all rows of a campaign as a CSV file for offline analysis or reporting. ### Request ```bash curl -X GET "https://www.getrevox.com/api/campaigns/9b2d7e41-6c3f-4a8e-b5d0-2f7a1c9e4b63/export" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the campaign, as returned by [`GET /campaigns`](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md). ### Body No body: send the request without one. ### Response 200 ```json { "csv": "id,to_phone_number,status,outcome\n6f9a3c1e,+33612345678,completed,interested", "filename": "calls-2026-11-05.csv" } ``` - `csv` (string): The CSV file content: one line per contact with phone_number, the assistant's prompt variables, the extracted data fields, the call status and the calls' metadata keys. - `filename` (string): Suggested file name, derived from the campaign name (e.g. 'spring-promo-results.csv'). ### Errors - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Get campaign statistics `GET https://www.getrevox.com/api/campaigns/{id}/statistics` Campaign report: a four-step funnel (contacts called, reached, real conversations, hot leads), the calling effort, inbound calls, the calls your team joined live, the outcome breakdown and the hot leads to follow up. Counts are distinct phone numbers unless stated otherwise, outcome figures use each contact's latest outcome, and percentages are null when their base is 0. ### Request ```bash curl -X GET "https://www.getrevox.com/api/campaigns/9b2d7e41-6c3f-4a8e-b5d0-2f7a1c9e4b63/statistics" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the campaign, as returned by [`GET /campaigns`](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md). ### Body No body: send the request without one. ### Response 200 ```json { "statistics": { "campaign": { "id": "8e1f2a3b-4c5d-4e6f-9a0b-1c2d3e4f5a6b", "name": "Appointment reminder", "status": "completed", "is_cancelled": false, "first_activity_at": "2026-11-05T09:00:00Z", "last_activity_at": "2026-11-05T09:00:00Z", "agent_name": "Julie", "max_attempts_per_contact": 1, "timezone": "Europe/Paris", "has_activity": false }, "funnel": { "called": { "count": 3, "imported_rows": 1 }, "reached": { "count": 3, "outbound": 1, "inbound": 1, "overlap": 1, "pct_of_called": 1 }, "real_exchanges": { "count": 3, "pct_of_reached": 1 }, "hot_leads": { "count": 3, "pct_of_reached": 1 } }, "effort": { "calls_total": 3, "outbound_attempts": 1, "inbound_calls": 1 }, "inbound": { "unique_callers": 1 }, "jump_in": { "joined_calls": 1, "median_time_to_join_seconds": 98, "median_conversation_seconds": 98 }, "outcome_breakdown": [ { "outcome": "interested", "label": "Intéressé", "count": 3 } ], "hot_lead_outcomes": ["hot lead outcome"], "data_extraction": null, "leads": { "interested": [ { "name": "Appointment reminder", "phone": "+33612345678", "email": "jane@example.com", "direction": "outbound", "summary": "Marie confirmed tomorrow's appointment and asked for the address by SMS.", "last_activity_at": "2026-11-05T09:00:00Z", "call_id": "8d2f6b1a-4c9e-4f37-b215-6a0e9c3d7f12", "attempt_id": "5a7c9e1b-3d5f-4a2c-8e6b-0f1a2b3c4d5e" } ], "callback_requested": [ { "name": "Appointment reminder", "phone": "+33612345678", "email": "jane@example.com", "direction": "outbound", "summary": "Marie confirmed tomorrow's appointment and asked for the address by SMS.", "last_activity_at": "2026-11-05T09:00:00Z", "call_id": "8d2f6b1a-4c9e-4f37-b215-6a0e9c3d7f12", "attempt_id": "5a7c9e1b-3d5f-4a2c-8e6b-0f1a2b3c4d5e" } ] } } } ``` - `statistics` (object): Campaign report. Counts are over distinct contacts (phone numbers) unless stated otherwise, and outcome-based figures use each contact's latest outcome. - `statistics.campaign` (object): The campaign the report is about. - `statistics.campaign.id` (string): ID of the campaign. - `statistics.campaign.name` (string): Name of the campaign. - `statistics.campaign.status` ("running" | "paused" | "completed"): Where the campaign stands. A cancelled campaign is flagged by is_cancelled, not by its status. - `"running"`: Active: its launched calls are placed. A campaign is running from its creation on, before any call is launched too. - `"paused"`: No new call is placed until the campaign is resumed ([`POST /campaigns/{id}/resume`](https://www.getrevox.com/docs/api/campaigns/resume-a-paused-campaign.md)). - `"completed"`: Every contact is done. Launching calls again sets it back to running. - `statistics.campaign.is_cancelled` (boolean): True when the campaign was cancelled: its pending calls were aborted. Launching calls again clears it. - `statistics.campaign.first_activity_at` (string (date-time) | null): When the first call of the campaign went out or came in (ISO 8601). Null when no call has yet. - `statistics.campaign.last_activity_at` (string (date-time) | null): When the latest call of the campaign went out or came in (ISO 8601). Null when no call has yet. - `statistics.campaign.agent_name` (string | null): Name of the campaign's assistant. Null when it was deleted. - `statistics.campaign.max_attempts_per_contact` (number | null): Maximum call attempts per contact, from the campaign's retry configuration (or the default one). - `statistics.campaign.timezone` (string): IANA timezone the report is computed in: the campaign's, else its assistant's. - `statistics.campaign.has_activity` (boolean): False while no call of the campaign has gone out or come in: the rest of the report is then all zeros. - `statistics.funnel` (object): Four-step funnel, counted in distinct contacts (phone numbers). Each step is a subset of the previous one. - `statistics.funnel.called` (object): Step 1: the contacts called. - `statistics.funnel.called.count` (number): Contacts with at least one outbound attempt that actually went out. - `statistics.funnel.called.imported_rows` (number): Contacts added to the campaign (rows created by inbound calls excluded). - `statistics.funnel.reached` (object): Step 2: the contacts actually reached. - `statistics.funnel.reached.count` (number): Contacts a person spoke with: an outbound attempt answered by a person, or an inbound call from them. - `statistics.funnel.reached.outbound` (number): Of them, contacts reached on an outbound attempt answered by a person. - `statistics.funnel.reached.inbound` (number): Of them, contacts reached because they called in. - `statistics.funnel.reached.overlap` (number): Contacts counted in both outbound and inbound, so that count = outbound + inbound - overlap. - `statistics.funnel.reached.pct_of_called` (number | null): count as a percentage of called.count, rounded to a whole number (0 to 100). Null when called.count is 0. - `statistics.funnel.real_exchanges` (object): Step 3: the reached contacts who had a real conversation. - `statistics.funnel.real_exchanges.count` (number): Reached contacts with at least one call that got a business outcome. - `statistics.funnel.real_exchanges.pct_of_reached` (number | null): count as a percentage of reached.count, rounded to a whole number (0 to 100). Null when reached.count is 0. - `statistics.funnel.hot_leads` (object): Step 4: the hot leads. - `statistics.funnel.hot_leads.count` (number): Contacts whose latest outcome is one of hot_lead_outcomes. - `statistics.funnel.hot_leads.pct_of_reached` (number | null): count as a percentage of reached.count, rounded to a whole number (0 to 100). Null when reached.count is 0. - `statistics.effort` (object): Calling effort, counted in calls rather than contacts. - `statistics.effort.calls_total` (number): outbound_attempts + inbound_calls. - `statistics.effort.outbound_attempts` (number): Outbound call attempts that actually went out. - `statistics.effort.inbound_calls` (number): Inbound calls from the campaign's contacts. - `statistics.inbound` (object): Inbound calls from the campaign's contacts. - `statistics.inbound.unique_callers` (number): Distinct contacts of the campaign who called in (same as funnel.reached.inbound). - `statistics.jump_in` (object): Calls a person from your team joined live. - `statistics.jump_in.joined_calls` (number): Call attempts a person from your team joined (took over from the AI). - `statistics.jump_in.median_time_to_join_seconds` (number | null): Median time, in seconds, the prospect talked with the AI before the person joined. Null when no joined attempt has the timing. - `statistics.jump_in.median_conversation_seconds` (number | null): Median time, in seconds, the conversation lasted after the person joined. Null when no joined attempt has the timing. - `statistics.outcome_breakdown` (array of object): The contacts of funnel.real_exchanges split by their latest outcome, most frequent first. - `statistics.outcome_breakdown.outcome` (string): The business outcome (e.g. 'interested', 'not_interested'). Example: `"interested"`. - `statistics.outcome_breakdown.label` (string): Display label of the outcome, in French (e.g. 'Pas intéressé' for not_interested; 'Autre' for an outcome without a label). Use outcome in code. Example: `"Intéressé"`. - `statistics.outcome_breakdown.count` (number): Contacts whose latest outcome is this one. - `statistics.hot_lead_outcomes` (array of string): The outcomes that make a contact a hot lead. - `statistics.data_extraction` (object | null): Summary of the data the assistant extracts from calls. Currently always null: not computed yet. - `statistics.data_extraction.intro` (string): Introductory sentence of the block. - `statistics.data_extraction.fields` (array of string): The extracted fields, in readable words. - `statistics.leads` (object): The hot leads to follow up, split by outcome. The two lists sum to funnel.hot_leads.count. - `statistics.leads.interested` (array of object): Hot leads whose latest outcome is 'interested', most recent first. - `statistics.leads.interested.name` (string): The contact's name, from the data imported with the contact; their phone number when no name is known. - `statistics.leads.interested.phone` (string): The contact's phone number, formatted for display: national format for a number of your organization's country, international otherwise. - `statistics.leads.interested.email` (string | null): The contact's email address. Null when unknown. - `statistics.leads.interested.direction` ("inbound" | "outbound"): Direction of the call that gave the contact's latest outcome. - `statistics.leads.interested.summary` (string | null): The outcome summary of that call (its outcome_summary). Null when it has none. - `statistics.leads.interested.last_activity_at` (string (date-time)): When that call took place (ISO 8601). - `statistics.leads.interested.call_id` (string): ID of that call (see [`GET /call/{id}`](https://www.getrevox.com/docs/api/calls/get-call-by-id.md)). - `statistics.leads.interested.attempt_id` (string | null): ID of the answered attempt of that call that holds the conversation. Null when none is found. - `statistics.leads.callback_requested` (array of object): Hot leads whose latest outcome is 'requested_callback_later', most recent first. - `statistics.leads.callback_requested.name` (string): The contact's name, from the data imported with the contact; their phone number when no name is known. - `statistics.leads.callback_requested.phone` (string): The contact's phone number, formatted for display: national format for a number of your organization's country, international otherwise. - `statistics.leads.callback_requested.email` (string | null): The contact's email address. Null when unknown. - `statistics.leads.callback_requested.direction` ("inbound" | "outbound"): Direction of the call that gave the contact's latest outcome. - `statistics.leads.callback_requested.summary` (string | null): The outcome summary of that call (its outcome_summary). Null when it has none. - `statistics.leads.callback_requested.last_activity_at` (string (date-time)): When that call took place (ISO 8601). - `statistics.leads.callback_requested.call_id` (string): ID of that call (see [`GET /call/{id}`](https://www.getrevox.com/docs/api/calls/get-call-by-id.md)). - `statistics.leads.callback_requested.attempt_id` (string | null): ID of the answered attempt of that call that holds the conversation. Null when none is found. ### Errors - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Add contacts to a campaign `POST https://www.getrevox.com/api/campaigns/{id}/rows` Append contacts to an existing campaign. Each new contact becomes a call in the `not_launched` status: nothing is dialed until [`POST /campaigns/{id}/launch-calls`](https://www.getrevox.com/docs/api/campaigns/launch-a-campaigns-calls.md) sends it. Contacts whose phone number is already in the campaign are skipped. ### Before you call - Added contacts are not dialed until [`POST /campaigns/{id}/launch-calls`](https://www.getrevox.com/docs/api/campaigns/launch-a-campaigns-calls.md) sends them. ### Request ```bash curl -X POST "https://www.getrevox.com/api/campaigns/9b2d7e41-6c3f-4a8e-b5d0-2f7a1c9e4b63/rows" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "contacts": [ { "to_phone_number": "+33687654321", "prompt_variables": { "first_name": "Camille", "company": "Acme" } } ] }' ``` ### Path parameters - `id` (string, required): ID of the campaign, as returned by [`GET /campaigns`](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md). ### Body JSON. - `contacts` (array of object, required): The contacts to add. A number already in the campaign, or repeated in the list, is skipped. At least 1 item. - `contacts.to_phone_number` (string, required): The contact's phone number, in E.164 format (e.g. +33612345678). Must be a valid number. - `contacts.prompt_variables` (object, optional): Values of the assistant's {{variables}} for this contact, keyed by variable name (e.g. {"first_name": "Marie"}). Default: {}. Keys: Variable name, as written between the braces: name for {{name}}. ### Response 200 - `campaign` ([Campaign](https://www.getrevox.com/docs/api/objects/campaign.md)) - `added` (number): Contacts actually added, duplicates and undialable numbers excluded. ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["contacts"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Get campaign rows `GET https://www.getrevox.com/api/campaigns/{id}/rows` Retrieve all contact rows for a campaign. ### Request ```bash curl -X GET "https://www.getrevox.com/api/campaigns/9b2d7e41-6c3f-4a8e-b5d0-2f7a1c9e4b63/rows" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the campaign, as returned by [`GET /campaigns`](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md). ### Body No body: send the request without one. ### Response 200 - `rows` (array of object): Every contact of the campaign, in row_index order. - `rows.id` (string): Unique ID of the campaign row (one per contact). - `rows.row_index` (number): Position of the contact in the campaign, in the order contacts were added, starting at 0. - `rows.phone_number` (string): The contact's phone number, in E.164 format. - `rows.input_data` (object): The contact's prompt variables, as given when the contact was added. - `rows.call` ([Call](https://www.getrevox.com/docs/api/objects/call.md), may be absent): The contact's call. Absent when it was deleted. ### Errors - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Get voice by ID `GET https://www.getrevox.com/api/voices/{id}` Retrieve details for a single voice by its unique ID and provider. ### Request ```bash curl -X GET "https://www.getrevox.com/api/voices/4325f426-c4e0-418e-a0e5-97fcdfcdf8e6?provider=cartesia" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): The voice ID to get. ### Query parameters - `provider` ("cartesia" | "elevenlabs" | "gradium", required): Provider of the voice, as listed by [`GET /voices`](https://www.getrevox.com/docs/api/voices/get-voices.md). ### Body No body: send the request without one. ### Response 200 ```json { "voice": { "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6", "name": "Camille", "description": "Books a slot in the agenda.", "language": "en" } } ``` - `voice` (object): The voice. - `voice.id` (string): ID of the voice at its provider: voice.id of an assistant. At least 1 character. Example: `"4325f426-c4e0-418e-a0e5-97fcdfcdf8e6"`. - `voice.name` (string): The name of the voice. Example: `"Camille"`. - `voice.description` (string, may be absent): The description of the voice. - `voice.language` (enum (8 values)): The voice's language, which is the language of the calls made with it. - `"en"`: English - `"fr"`: French - `"es"`: Spanish - `"de"`: German - `"it"`: Italian - `"pt"`: Portuguese - `"ru"`: Russian - `"zh"`: Mandarin Chinese ### Errors - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Get voices `GET https://www.getrevox.com/api/voices` Retrieve all voices available for AI calls: the preset voices from Cartesia, ElevenLabs and Gradium, and your organization's cloned voices. ### Request ```bash curl -X GET "https://www.getrevox.com/api/voices" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Body No body: send the request without one. ### Response 200 - `voices` (array of [Voice](https://www.getrevox.com/docs/api/objects/voice.md)): Every voice an assistant can use: Revox's preset voices and your organization's cloned voices. --- ## Delete a voice `DELETE https://www.getrevox.com/api/voices/{id}` Delete a cloned voice. Only cloned voices can be deleted. Returns 409 if the voice is in use by an assistant. ### Request ```bash curl -X DELETE "https://www.getrevox.com/api/voices/4325f426-c4e0-418e-a0e5-97fcdfcdf8e6" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): The cloned voice ID to delete. ### Body No body: send the request without one. ### Response 200 ```json { "success": true } ``` - `success` (boolean): True when the voice was deleted. ### Errors - `403` The resource belongs to another organization: `{"error":"Unauthorized, you are not the owner of this resource"}` - `404` Not found in your organization: `{"error":"Not found"}` - `409` Conflicts with the resource's current state: `{"error":"Conflicts with the resource's current state","assistantIds":["assistantId"]}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Generate voice preview `POST https://www.getrevox.com/api/voices/preview` Generate a short audio sample of a voice. Returns the audio file itself, not JSON: audio/mpeg, or audio/wav for Gradium voices. ### Before you call - The response is the audio file itself, not JSON: `audio/mpeg`, or `audio/wav` for a Gradium voice. Save the body as is. ### Request ```bash curl -X POST "https://www.getrevox.com/api/voices/preview" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "voiceId": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6", "provider": "cartesia", "text": "Bonjour, ici Camille du cabinet Acme. Je vous appelle pour confirmer votre rendez-vous de jeudi." }' \ --output response.mp3 ``` ### Body JSON. - `voiceId` (string, required): The voice ID to generate a preview for. - `provider` ("cartesia" | "elevenlabs" | "gradium", required): The provider to use for the preview. - `text` (string, optional): Custom text for the preview. If omitted, a short default is used. At most 2000 characters. - `assistantPrompt` (string, optional): Prompt of the assistant the voice is for. When `text` is omitted, the preview is a few lines that assistant would say on a call. At most 100000 characters. - `speed` (number, optional): Speed for preview. Cartesia 0.6 to 1.5, ElevenLabs 0.7 to 1.2. Default 1.0. - `volume` (number, optional): Volume for Cartesia preview (0.5 to 2.0). Ignored for other providers. - `model` ("sonic-3" | "sonic-3.5" | "sonic-3.6", optional): Cartesia model for the preview. Defaults to sonic-3.6. Ignored for other providers. ### Response 200 The body is the binary file itself (`audio/mpeg`). ### Errors - `400` Invalid request: a field or parameter failed validation: `{"error":"Invalid request: a field or parameter failed validation"}` - `500` Server error: `{"error":"Server error"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Clone a voice `POST https://www.getrevox.com/api/voices/clone` Clone a voice from an audio recording. Send audio as a base64-encoded string. The cloned voice will be available in [`GET /voices`](https://www.getrevox.com/docs/api/voices/get-voices.md). ### Request audio is the recording in base64 (shortened here). Use the returned cartesiaVoiceId as voice.id, with provider cartesia. ```bash curl -X POST "https://www.getrevox.com/api/voices/clone" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "audio": "UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YQAAAAA=", "contentType": "audio/wav", "name": "Marie", "language": "fr" }' ``` ### Body JSON. - `audio` (string, required): Base64-encoded audio data (max ~7.5MB decoded). At most 10000000 characters. - `contentType` (enum (6 values), required): MIME type of the audio. Values: `"audio/webm"`, `"audio/wav"`, `"audio/mpeg"`, `"audio/ogg"`, `"audio/mp4"`, `"video/webm"`. - `name` (string, required): Name for the cloned voice. At least 1 character. - `language` (enum (8 values), required): Language of the voice - `"en"`: English - `"fr"`: French - `"es"`: Spanish - `"de"`: German - `"it"`: Italian - `"pt"`: Portuguese - `"ru"`: Russian - `"zh"`: Mandarin Chinese ### Response 201 ```json { "id": "6f9a3c1e-2b7d-4e58-9a10-3d2c4b5e6f70", "cartesiaVoiceId": "a0e99841-438c-4a64-b679-ae501e7d6091", "name": "Appointment reminder", "language": "en", "createdAt": "2026-11-05T09:00:00Z" } ``` - `id` (string): Revox's internal ID of the cloned voice record. The other endpoints use cartesiaVoiceId instead. - `cartesiaVoiceId` (string): ID of the voice at Cartesia, which hosts cloned voices: the voice's id in [`GET /voices`](https://www.getrevox.com/docs/api/voices/get-voices.md) and the {id} of [`DELETE /voices/{id}`](https://www.getrevox.com/docs/api/voices/delete-a-voice.md). Give the voice to an assistant with voice.provider 'cartesia' and this value as voice.id. - `name` (string): Name of the cloned voice. - `language` (string): Language of the voice. - `createdAt` (string): When the voice was cloned (ISO 8601). ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["audio"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `401` Missing or invalid API key: `{"error":"Unauthorized, invalid API key"}` - `502` An upstream provider failed: `{"error":"An upstream provider failed"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Get phone numbers `GET https://www.getrevox.com/api/phone-numbers` List the phone numbers of your organization: the numbers calls can be placed from (from_phone_number) and received on, with the assistant that answers each one's inbound calls and its spam reputation. ### Request ```bash curl -X GET "https://www.getrevox.com/api/phone-numbers" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Body No body: send the request without one. ### Response 200 - `phone_numbers` (array of [PhoneNumber](https://www.getrevox.com/docs/api/objects/phone-number.md)): Every phone number of the organization. --- ## Update a phone number `PATCH https://www.getrevox.com/api/phone-numbers/{id}` Rename a phone number, or choose which assistant answers its inbound calls. Only the fields you send are changed. ### Request Every call to this number is now answered by the assistant. ```bash curl -X PATCH "https://www.getrevox.com/api/phone-numbers/6f9a3c1e-2b7d-4e58-9a10-3d2c4b5e6f70" \ -H "Authorization: Bearer $REVOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "inbound_assistant_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34" }' ``` ### Path parameters - `id` (string, required): ID of the phone number record, as returned by [`GET /phone-numbers`](https://www.getrevox.com/docs/api/phone-numbers/get-phone-numbers.md) (not the phone number itself). ### Body JSON. - `label` (string | null, optional): Free-text name for the number (e.g. 'Paris office'). Null clears it; omit to leave it unchanged. - `inbound_assistant_id` (string | null, optional): ID of the assistant that answers inbound calls to this number; it must belong to your organization. Null stops routing inbound calls to an assistant; omit to leave it unchanged. ### Response 200 - `phone_number` ([PhoneNumber](https://www.getrevox.com/docs/api/objects/phone-number.md)) ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["label"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Delete a phone number `DELETE https://www.getrevox.com/api/phone-numbers/{id}` Remove a phone number from your organization: no call can be placed from it or received on it through Revox anymore. A number bought through Revox is also released, so it stops being billed and cannot be recovered. Returns 400 when the release fails; try again later. ### Request ```bash curl -X DELETE "https://www.getrevox.com/api/phone-numbers/6f9a3c1e-2b7d-4e58-9a10-3d2c4b5e6f70" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Path parameters - `id` (string, required): ID of the phone number record, as returned by [`GET /phone-numbers`](https://www.getrevox.com/docs/api/phone-numbers/get-phone-numbers.md) (not the phone number itself). ### Body No body: send the request without one. ### Response 200 ```json { "success": true } ``` - `success` (boolean): True when the number was deleted. ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["phone_number"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `404` Not found in your organization: `{"error":"Not found"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Get the current user `GET https://www.getrevox.com/api/users/me` Get the user the API key or session belongs to, with their organization ID. ### Request ```bash curl -X GET "https://www.getrevox.com/api/users/me" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Body No body: send the request without one. ### Response 200 - `user` ([User](https://www.getrevox.com/docs/api/objects/user.md)) ### Errors - `401` Missing or invalid API key: `{"error":"Unauthorized, invalid API key"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## Get credit and call usage `GET https://www.getrevox.com/api/usage` Credits used, calls placed, calls answered and time on the line over a period, point by point and per assistant and campaign, compared with the period just before. Also returns the balance now and the date it runs out at the recent pace. ### Before you call - Without parameters it returns the current month so far, in Europe/Paris, by day. - 1 credit = 1 worked contact = €0.50 excl. VAT: a contact is charged once, however many times it is called. `credits_by_kind` says what the credits paid for. - `balance` is the balance now, whatever the period: `depletion_date` is when it runs out at the pace of the last 14 days. ### Request ```bash curl -X GET "https://www.getrevox.com/api/usage" \ -H "Authorization: Bearer $REVOX_API_KEY" ``` ### Query parameters - `from` (string (date-time), optional): Start of the period, ISO 8601 (e.g. 2026-11-01T00:00:00+01:00). Default: the start of the current month in `timezone`. - `to` (string (date-time), optional): End of the period, excluded, ISO 8601. Default: now. - `granularity` ("hour" | "day" | "week" | "month", optional): Size of each point of `series`. Default: hour up to 2 days, day up to 92 days, week up to a year, month beyond. At most 400 points. - `timezone` (string, optional): IANA timezone the points and the default period are cut in. Default: Europe/Paris. ### Body No body: send the request without one. ### Response 200 A [Usage](https://www.getrevox.com/docs/api/objects/usage.md) object: see "Objects on this page" below. ### Errors - `400` Invalid request: a field or parameter failed validation: `{"message":"Request validation failed","bodyErrors":{"issues":[{"path":["phone_number"],"message":"Invalid input: expected string, received undefined","code":"invalid_type"}]}}` - `401` Missing or invalid API key: `{"error":"Unauthorized, invalid API key"}` - Every status is explained under Errors in https://www.getrevox.com/docs/api.md#errors. --- ## The Assistant object The voice agent that places and answers calls: its prompt, voice and LLM, how it opens and ends a call, the data it extracts, and the tools and calendars it uses. ```json { "id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "prompt": "You are Julie from Acme. You call {{first_name}} to confirm tomorrow's appointment.", "post_call_prompt": "Send the appointment address by SMS if asked.", "first_sentence": "Hello {{first_name}}, this is Julie from Acme.", "first_sentence_mode": "generated", "end_of_call_sentence": "Thank you, have a good day.", "voice": { "provider": "cartesia", "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6", "speed": 1, "volume": 1, "model": "sonic-3" }, "voice_languages": [ { "language": "en", "voice": { "provider": "cartesia", "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6", "speed": 1, "volume": 1, "model": "sonic-3" } } ], "cartesia_dictionary_pronunciation_id": "6f9a3c1e-2b7d-4e58-9a10-3d2c4b5e6f70", "llm_model": { "type": "recommended" }, "webhook_url": "https://example.com/revox-webhook", "max_call_duration_secs": 600, "max_duration_end_message": "Thank you, have a good day.", "structured_output_config": [ { "name": "budget", "type": "string", "description": "Books a slot in the agenda.", "required": false, "enum_options": ["enum option"] } ], "structured_output_prompt": "Send the appointment address by SMS if asked.", "call_retry_config": { "calling_windows": [ { "calling_window_start_time": "09:00", "calling_window_end_time": "18:00", "retry_delay_seconds": 7200 } ], "max_retry_attempts": 1, "allowed_days": [ "monday", "tuesday", "wednesday", "thursday", "friday" ], "excluded_dates": ["2026-11-05"], "call_twice_in_a_row": false }, "timezone": "Europe/Paris", "background_sound": "audio/office.ogg", "background_sound_volume": 1, "thinking_sound": "city-ambience.ogg", "thinking_sound_volume": 1, "thinking_sound_probability": 0, "transfer_destinations": [ { "label": "Main line", "phone_number": "+33612345678" } ], "human_transfer_mode": "warm", "warm_transfer_summary_instructions": "Send the appointment address by SMS if asked.", "warm_transfer_voice_speed": 1, "ivr_navigation_enabled": true, "voicemail_message": "Thank you, have a good day.", "stt_context": { "general": [{ "key": "crm_id", "value": "lead_8812" }], "terms": ["term"] }, "stt_model": "stt-rt-v4", "first_sentence_delay_ms": 400, "calendars": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "assistant_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "handle": "google_calendar_jane_at_example.com", "provider": "google-calendar", "status": "ready", "connection": { "provider": "google-calendar", "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "settings": { "calendar_id": "primary", "time_zone": "Europe/Paris", "duration_minutes": 30, "days": [1, 2, 3, 4, 5], "start_time": "09:00", "end_time": "18:00", "google_meet": false, "location": "{{site_address}}" } }, "account_label": "Main line", "connected_via_invite": false, "invite": { "url": "https://example.com", "status": "completed", "created_at": "2026-11-05T09:00:00Z", "expires_at": "2026-11-05T09:00:00Z" }, "created_at": "2026-11-05T09:00:00Z" } ], "calendly": null, "cal": null, "google_calendar": null, "hubspot": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "precall_lookup_enabled": true, "meeting_links": [ { "slug": "jane-martin", "label": "Main line", "duration_ms": 1800000, "is_fallback": false, "booking_url": "https://example.com" } ], "post_call_sync": { "enabled": true, "field_mapping": [ { "source": "email", "hubspot_property": "email" } ] } }, "slack": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "channels": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "name": "Appointment reminder" } ] }, "teams": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "channels": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "name": "Appointment reminder", "team_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "team_name": "Sales" } ] }, "zoho": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "module": "Leads", "log_call_activity": false, "field_mapping": [ { "source": "email", "zoho_field": "Email" } ], "template": "{{outcome}}: {{summary}}\n{{call_url}}" }, "custom_tools": [ { "name": "appointment_reminder", "description": "Books a slot in the agenda.", "method": "GET", "url": "https://example.com", "headers": [{ "key": "crm_id", "value": "lead_8812" }], "query_params": [ { "key": "crm_id", "value": "lead_8812" } ], "body_template": "{\"email\": \"{{email}}\", \"name\": \"{{first_name}}\"}", "input_schema": [ { "name": "budget", "type": "string", "description": "Books a slot in the agenda.", "required": false, "enum_options": ["enum option"] } ] } ], "from_phone_number": "+33187654321", "demo_page_url": "https://example.com", "precall_lookup_url": "https://example.com", "precall_lookup_headers": [ { "key": "crm_id", "value": "lead_8812" } ], "organization_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "name": "Appointment reminders", "is_inbound_receptionist": false, "created_by": { "id": "5a7c9e1b-3d5f-4a2c-8e6b-0f1a2b3c4d5e", "email": "jane@example.com", "first_name": "Marie", "last_name": "Martin" }, "created_at": "2026-11-05T09:00:00Z", "updated_at": "2026-11-05T09:02:41Z" } ``` ### Fields - `id` (string): Unique ID of the assistant (UUID). Pass it as assistant_id to place a call or create a campaign with this assistant. Example: `"3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34"`. - `prompt` (string): System prompt given to the LLM for the whole call: who the agent is, its goal and how to run the conversation. May contain {{variable}} placeholders, filled from the call's prompt_variables. - `post_call_prompt` (string | null): Instructions the agent follows once the call has ended: who to email, when to text, what to post on Slack or Teams. Plain language, no template syntax. Empty or null means no post-call agent runs. - `first_sentence` (string | null): The agent's opening line, spoken word for word. Only used, and only kept, with first_sentence_mode 'static': with 'generated' or 'none' it is dropped and reads back empty. May contain {{variable}} placeholders; one without a value is left out. - `first_sentence_mode` ("generated" | "static" | "none"): How the agent opens the call. Default at creation: 'generated'. - `"generated"`: The agent opens with a greeting it writes from the prompt. first_sentence is not used, and not kept. - `"static"`: The agent opens with first_sentence, word for word. - `"none"`: The agent says nothing first and waits for the other person to speak. - `end_of_call_sentence` (string | null): Sentence the agent says, without being interruptible, when it decides to end the call. Null or empty: the agent says a short default goodbye, only if it has not said goodbye already. - `voice` (object | null): The voice the agent speaks with: provider, voice ID and speed. Its language (see [`GET /voices`](https://www.getrevox.com/docs/api/voices/get-voices.md)) is the language of the calls, unless voice_languages picks another one for a call. Always set on a saved assistant. - `voice.provider` ("cartesia" | "elevenlabs" | "gradium"): The provider of the voice. - `voice.id` (string): ID of the voice at its provider, as [`GET /voices`](https://www.getrevox.com/docs/api/voices/get-voices.md) lists it. At least 1 character. Example: `"4325f426-c4e0-418e-a0e5-97fcdfcdf8e6"`. - `voice.speed` (number, may be absent): The speed of the voice. Range depends on provider: Cartesia 0.6 to 1.5, ElevenLabs 0.7 to 1.2, Gradium 0.6 to 1.5. Default is 1.0. - `voice.volume` (number, may be absent): Volume of the voice (Cartesia only), 0.5 to 2.0. Default 1.0. Ignored for other providers. - `voice.model` ("sonic-3" | "sonic-3.5" | "sonic-3.6", may be absent): Cartesia TTS model (Cartesia only). Defaults to sonic-3.6 when omitted. Ignored for other providers. - `voice_languages` (array of object | null): Extra languages for a multilingual assistant, each with its own voice. Null for a single-language assistant. - `voice_languages.language` (enum (8 values)): The language contacts are called in with this voice. - `"en"`: English - `"fr"`: French - `"es"`: Spanish - `"de"`: German - `"it"`: Italian - `"pt"`: Portuguese - `"ru"`: Russian - `"zh"`: Mandarin Chinese - `voice_languages.voice` (object): The voice used for contacts whose language is this language. - `voice_languages.voice.provider` ("cartesia" | "elevenlabs" | "gradium"): The provider of the voice. - `voice_languages.voice.id` (string): ID of the voice at its provider, as [`GET /voices`](https://www.getrevox.com/docs/api/voices/get-voices.md) lists it. At least 1 character. Example: `"4325f426-c4e0-418e-a0e5-97fcdfcdf8e6"`. - `voice_languages.voice.speed` (number, may be absent): The speed of the voice. Range depends on provider: Cartesia 0.6 to 1.5, ElevenLabs 0.7 to 1.2, Gradium 0.6 to 1.5. Default is 1.0. - `voice_languages.voice.volume` (number, may be absent): Volume of the voice (Cartesia only), 0.5 to 2.0. Default 1.0. Ignored for other providers. - `voice_languages.voice.model` ("sonic-3" | "sonic-3.5" | "sonic-3.6", may be absent): Cartesia TTS model (Cartesia only). Defaults to sonic-3.6 when omitted. Ignored for other providers. - `cartesia_dictionary_pronunciation_id` (string | null): Optional Cartesia pronunciation dictionary ID linked to this assistant. - `llm_model` (object): The LLM that drives the conversation. Defaults to `recommended` (the model Revox currently recommends for voice agents) when omitted at creation. - One of 3, chosen by `llm_model.type`. - When `type` is `"recommended"`: The LLM Revox currently recommends for voice agents, chosen server-side and upgraded without any change on your side. No per-assistant configuration. Example: `{"type":"recommended"}`. - When `type` is `"gpt-4.1-priority"`: OpenAI gpt-4.1 on the priority tier, with gpt-4.1-mini answering a turn when gpt-4.1 is slow to respond. No per-assistant configuration. Example: `{"type":"gpt-4.1-priority"}`. - When `type` is `"realtime"`: A realtime speech-to-speech model: it listens to the call and answers with its own voice (realtime_voice_id), instead of the assistant's transcriber and voice. Example: `{"type":"realtime","provider":"openai","realtime_model_id":"gpt-realtime","realtime_voice_id":"marin"}`. - `llm_model.provider` ("openai" | "google"): Provider of the realtime model. - `llm_model.realtime_model_id` (string): ID of the realtime model: 'gpt-realtime' (provider 'openai'), 'gemini-3.1-flash-live-preview' (provider 'google'), 'gemini-2.5-flash-native-audio-preview-12-2025' (provider 'google'). Example: `"gpt-realtime"`. - `llm_model.realtime_voice_id` (string, may be absent): Output voice for the realtime provider (e.g. OpenAI: marin; Gemini: Puck). At least 1 character. Example: `"marin"`. - `webhook_url` (string | null): URL that receives a POST with the call and this assistant once the call is over, when it reaches completed or errored (not when it is cancelled). See Webhooks for the payload. - `max_call_duration_secs` (number): Longest a call may last, in seconds: the agent then says max_duration_end_message, if set, and hangs up. Default at creation: 300. Outbound calls are capped at 600. - `max_duration_end_message` (string | null): Optional message the agent will say, without being interruptible, when the call reaches its max duration. Kept short so it fits inside the farewell buffer. If null, the call ends silently. At most 150 characters. - `structured_output_config` (array of [StructuredOutputField](https://www.getrevox.com/docs/api/objects/structured-output-field.md) | null): The values to extract from each call (e.g. an email, a budget, a date). They land in structured_output of each call attempt, keyed by name. - `structured_output_prompt` (string | null): Custom prompt for structured data extraction. If not provided, a default prompt is used. Available variables: {{transcript}}, {{call_direction}}, {{user_phone_number}}, {{agent_phone_number}}. - `call_retry_config` ([CallRetryConfig](https://www.getrevox.com/docs/api/objects/call-retry-config.md) | null): When and how often the assistant's calls are dialed. Null: the defaults. - `timezone` (string): IANA timezone of this assistant's calls, e.g. 'Europe/Paris' or 'America/Phoenix'. Every call runs in exactly one timezone: its calling windows and allowed days are read in it, the agent tells the date and offers calendar slots in it, and callbacks and extracted datetimes are interpreted in it. A campaign's `timezone`, then [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md) `timezone`, override it for their calls. Default when creating: 'Europe/Paris'. Replaces the deprecated `call_retry_config.timezone`. - `background_sound` ("audio/office.ogg" | "audio/waves.m4a" | null): Ambient background sound to play during the call. null disables it. - `background_sound_volume` (number): Volume of the ambient background sound (0 = silent, 1 = max). 0 to 1. - `thinking_sound` (enum (7 values) | null): Audio clip played while the agent prepares an answer. Null or omitted: none. Values: `"city-ambience.ogg"`, `"forest-ambience.ogg"`, `"office-ambience.ogg"`, `"crowded-room.ogg"`, `"keyboard-typing.ogg"`, `"keyboard-typing2.ogg"`, `"hold_music.ogg"`. - `thinking_sound_volume` (number): Volume of the thinking sound (0 = silent, 1 = max). 0 to 1. - `thinking_sound_probability` (number): Probability [0..1] that the thinking sound plays on any given turn; otherwise the agent is silent while thinking. 0 to 1. - `transfer_destinations` (array of object | null): Where calls can be transferred to when users ask to speak to a human. Null or empty when transfer is not configured. - `transfer_destinations.label` (string): Human-meaningful name for this destination (e.g. "Sales"). The assistant's prompt refers to these labels when describing who to transfer to. 1 to 60 characters. - `transfer_destinations.phone_number` (string): Destination phone number in E.164 format (e.g. +33612345678). - `human_transfer_mode` ("warm" | "cold" | null): Warm or cold transfer when transfer_destinations is non-empty; null when transfer is not configured. - `"warm"`: The agent calls the destination first, briefs the person who answers on the call so far (see warm_transfer_summary_instructions), then puts the caller through. - `"cold"`: The call is passed on at once, without a briefing (a SIP REFER: the phone carrier must allow it). - `warm_transfer_summary_instructions` (string | null): Warm transfer only: instructions for the supervisor handoff summary; null when not configured or cold transfer. - `warm_transfer_voice_speed` (number | null): Warm transfer only: voice speed of the briefing to the human colleague; null when it follows voice.speed, not configured, or cold transfer. 0.6 to 1.5. - `ivr_navigation_enabled` (boolean): Enable IVR navigation tools. When enabled, the assistant can send DTMF tones and skip turns to navigate phone menus. - `voicemail_message` (string | null): If set, when voicemail is detected the agent will speak this message then hang up; if null, hang up immediately. - `stt_context` (object | null): Assistant-level speech-to-text context: structured `general` key/value pairs plus a list of domain `terms`. Prompt-derived context is merged in without replacing existing entries. - `stt_context.general` (array of object, default []): Short key/value facts that frame the conversation for the speech-to-text engine (domain, topic, company), to improve recognition. Only the first 6 pairs are used. - `stt_context.general.key` (string): What the fact is about (e.g. 'domain', 'topic', 'company'). Unique within `general`: a repeated key is dropped. At least 1 character. - `stt_context.general.value` (string): The fact itself (e.g. 'Real estate rentals'). At least 1 character. - `stt_context.terms` (array of string, default []): Words the speech-to-text engine should expect on the call: proper nouns, brand and product names, jargon, email domains. At most 100 terms of up to 5 words are used; URLs and digit-only terms are dropped, since callers never say them. Each item at least 1 character. - `first_sentence_delay_ms` (integer): Delay in milliseconds before speaking the first sentence. Default: 400. - `calendars` (array of [AssistantCalendar](https://www.getrevox.com/docs/api/objects/assistant-calendar.md)): The calendars the agent books meetings on during a call, each named by the handle the prompt mentions. Only the `ready` ones are offered to the agent. - `hubspot` (object | null): HubSpot Meetings config. When set with at least one meeting link, the agent can read a rep's real availability and book the meeting natively in HubSpot during the call. Null when HubSpot is not connected. - `hubspot.connection_id` (string): The connection ID linking the organization's HubSpot account to Revox. - `hubspot.precall_lookup_enabled` (boolean, default false): Resolve the caller against HubSpot contacts before answering an inbound call, filling the contact_* prompt variables (contact_name, contact_owner, contact_lead_status, contact_has_open_deal). Off by default: it costs API calls before the phone is picked up. - `hubspot.meeting_links` (array of object, default []): Scheduling pages the agent can book on during a call: typically one per sales rep, plus a round-robin team page marked as the fallback. - `hubspot.meeting_links.slug` (string): HubSpot scheduling page slug, as returned by the meeting-links API (e.g. 'jane-doe'). At least 1 character. - `hubspot.meeting_links.label` (string): Name the agent recognises for this calendar (e.g. 'Jane Doe'). Listed in the prompt and matched against what the caller asks for. At least 1 character. - `hubspot.meeting_links.duration_ms` (integer): Meeting duration in milliseconds, chosen among the durations the scheduling page offers (e.g. 1800000 for 30 minutes). > 0. - `hubspot.meeting_links.is_fallback` (boolean): Marks the round-robin calendar the agent falls back to when the requested rep has no slot. At most one meeting link may set this. - `hubspot.meeting_links.booking_url` (string | null, default null): Public URL of the scheduling page (e.g. https://meetings-eu1.hubspot.com/jane-doe). The agent books through the API and only texts this link to the caller when the booking fails and the call can receive an SMS. Null on calendars saved before this field existed. - `hubspot.post_call_sync` (object, may be absent): Sends call data back to HubSpot after the call. Off until set: connecting HubSpot to book meetings must not start writing to the CRM. Always present in responses; omit it on update to leave the current setting untouched. - `hubspot.post_call_sync.enabled` (boolean, default false): Records calls in HubSpot after they end: the contact is created or updated from the phone number and the call is logged on its timeline. By default every call a person answered is recorded. When the post-call prompt talks about the CRM (in plain words or by mentioning the crm_push_call tool), the post-call agent decides instead which calls are recorded and what the logged call says. - `hubspot.post_call_sync.field_mapping` (array of object, default []): Maps extracted call fields (structured_output / prompt variables) onto HubSpot contact properties. - `hubspot.post_call_sync.field_mapping.source` (string): Source key to read from the call: a structured_output field name, falling back to a prompt variable of the same name. At least 1 character. Example: `"email"`. - `hubspot.post_call_sync.field_mapping.hubspot_property` (string): Destination HubSpot contact property, by internal name (e.g. 'email', 'company', or a custom 'budget'). At least 1 character. Example: `"email"`. - `slack` (object | null): Slack config. When set, the post-call agent can post to the listed channels after a call; whether it posts, and what it says, is decided by `post_call_prompt`. Null when Slack is not connected. - `slack.connection_id` (string): The connection ID linking the organization's Slack workspace to Revox. - `slack.channels` (array of object): The Slack channels the post-call agent may post to. It resolves the channel it was told to use against this list and cannot reach any other. - `slack.channels.id` (string): The Slack channel ID (e.g. 'C01234567'). - `slack.channels.name` (string | null, may be absent): Human-readable Slack channel name, cached for display in the dashboard and given to the LLM when the agent prompt routes by channel name. - `teams` (object | null): Microsoft Teams config. When set with at least one channel, the post-call agent can post to those channels when the post-call instructions ask for it. Null when Teams is not connected. - `teams.connection_id` (string): The connection ID linking a Microsoft Teams account to Revox. Messages are posted as that account. - `teams.channels` (array of object): The Teams channels the post-call agent may post to. It resolves the channel it was told to use against this list and cannot reach any other. - `teams.channels.id` (string): The Microsoft Teams channel ID (e.g. '19:561fbdbb...@thread.tacv2'). - `teams.channels.name` (string | null, may be absent): Human-readable channel name, cached for display in the dashboard and given to the LLM when the agent prompt routes by channel name. - `teams.channels.team_id` (string): The ID of the team the channel belongs to. Needed to post. - `teams.channels.team_name` (string | null, may be absent): Human-readable team name. Channel names repeat across teams (every team has a 'General'), so the team name is what tells two of them apart. - `zoho` (object | null): Zoho CRM config. When set, the post-call agent can upsert the prospect (keyed on phone) into the chosen module and attach a Note with the call summary. Null when Zoho is not connected. - `zoho.connection_id` (string): The connection ID linking the organization's Zoho CRM account to Revox. - `zoho.module` (string): Zoho module the prospect record is upserted into (e.g. 'Leads' or 'Contacts'). At least 1 character. - `zoho.log_call_activity` (boolean): When true, also log the call as a record in Zoho's Calls module (related to the upserted prospect via Who_Id). - `zoho.field_mapping` (array of object): Maps extracted call fields (structured_output / prompt variables) onto Zoho field API names on the upserted record. - `zoho.field_mapping.source` (string): Source key to read from the call: a structured_output field name, falling back to a prompt variable of the same name. At least 1 character. Example: `"email"`. - `zoho.field_mapping.zoho_field` (string): Destination Zoho field API name on the upserted record (e.g. 'Email', 'Company', or a custom 'Budget__c'). At least 1 character. Example: `"Email"`. - `zoho.template` (string | null, may be absent): Optional Note body template. Supports {{summary}}, {{outcome}}, {{phone}}, {{call_url}}, {{assistant_name}}, {{campaign_name}}, {{transcript}}, plus prompt_variables and structured_output keys. When null/empty a default note (outcome + summary + auto-listed extracted fields) is used. Example: `"{{outcome}}: {{summary}}\n{{call_url}}"`. - `custom_tools` (array of object | null): Custom API tools the assistant can call during conversations. Each tool defines an HTTP endpoint with variable substitution. Null or empty when the assistant has none. - `custom_tools.name` (string): Unique tool name in lowercase_snake_case (e.g. check_inventory). At least 1 character, pattern ^[a-z][a-z0-9_]*$. - `custom_tools.description` (string): Human-readable description of what the tool does, used by the LLM to decide when to call it. At least 1 character. - `custom_tools.method` (enum (5 values)): HTTP method to use when calling the API endpoint. Values: `"GET"`, `"POST"`, `"PUT"`, `"PATCH"`, `"DELETE"`. - `custom_tools.url` (string): Full URL of the API endpoint. Supports {{variable}} placeholders for dynamic values. At least 1 character. - `custom_tools.headers` (array of object, default []): HTTP headers to include in the request. Values support {{variable}} placeholders - `custom_tools.headers.key` (string): HTTP header name. At least 1 character. - `custom_tools.headers.value` (string): Header value. Supports {{variable}} placeholders. - `custom_tools.query_params` (array of object, default []): Query string parameters appended to the URL. Values support {{variable}} placeholders - `custom_tools.query_params.key` (string): Query parameter name. At least 1 character. - `custom_tools.query_params.value` (string): Query parameter value. Supports {{variable}} placeholders. - `custom_tools.body_template` (string | null, default null): JSON body template for the request. Use quoted {{variable}} placeholders (e.g. "{{name}}") for dynamic values - `custom_tools.input_schema` (array of [StructuredOutputField](https://www.getrevox.com/docs/api/objects/structured-output-field.md)): Schema defining the parameters the LLM should extract from the conversation to pass to this tool - `from_phone_number` (string | null): Caller ID of the calls placed with this assistant: a number of your organization ([`GET /phone-numbers`](https://www.getrevox.com/docs/api/phone-numbers/get-phone-numbers.md)), in E.164 format. A French mobile number (06, 07) cannot be the caller ID of an automated call. Null: a Revox number chosen for each destination. - `demo_page_url` (string | null): Public demo page of the assistant: anyone with this link can call the assistant and see the calls it placed, their transcripts and recordings. Null when the page is off. Turn it on, regenerate it or turn it off with [`POST /assistants/{id}/demo-page`](https://www.getrevox.com/docs/api/assistants/turn-the-public-demo-page-on-or-off.md). - `precall_lookup_url` (string | null): URL fetched before an inbound call is answered to resolve the assistant's prompt variables. Null when no lookup is configured. - `precall_lookup_headers` (array of object | null): HTTP headers sent with the pre-call lookup request. Null when none are configured. - `precall_lookup_headers.key` (string): HTTP header name (e.g. 'Authorization'). At most 200 characters, pattern ^[A-Za-z0-9!#$%&'*+.^_`|~-]+$. - `precall_lookup_headers.value` (string): Header value, sent as is (no {{variable}} substitution), e.g. 'Bearer sk_123'. 1 to 4000 characters. - `organization_id` (string): ID of the organization that owns the assistant. - `name` (string): Display name of the assistant, shown in the dashboard and in call lists. Example: `"Appointment reminders"`. - `is_inbound_receptionist` (boolean, may be absent): True when at least one of the organization's phone numbers sends its inbound calls to this assistant (see [`PATCH /phone-numbers/{id}`](https://www.getrevox.com/docs/api/phone-numbers/update-a-phone-number.md), inbound_assistant_id). Not computed by every endpoint: absent or false does not prove that no number routes to it. - `created_by` (object | null, may be absent): The user who created the assistant. Null for assistants created by Revox itself, for assistants created before this was tracked, and when that user was deleted. - `created_by.id` (string): User ID of the creator. - `created_by.email` (string): The user's email address. - `created_by.first_name` (string | null): The user's first name. Null when not set on their account. - `created_by.last_name` (string | null): The user's last name. Null when not set on their account. - `created_at` (string (date-time)): When the assistant was created (ISO 8601). - `updated_at` (string (date-time)): When the assistant was last modified (ISO 8601). - `stt_model` ("stt-rt-v4" | "stt-rt-v5", deprecated): Speech-to-text model stored on the assistant. Ignored: every call is transcribed with the model Revox currently runs. - `calendly` (object | null, deprecated): Deprecated: an assistant now books on any number of calendars, managed with the assistant calendars endpoints and listed in `calendars`. This field stands for the assistant's first ready calendar of this provider: setting it creates or updates that calendar, null removes it. The dashboard ignores it. - `cal` (object | null, deprecated): Deprecated: an assistant now books on any number of calendars, managed with the assistant calendars endpoints and listed in `calendars`. This field stands for the assistant's first ready calendar of this provider: setting it creates or updates that calendar, null removes it. The dashboard ignores it. - `google_calendar` (object | null, deprecated): Deprecated: an assistant now books on any number of calendars, managed with the assistant calendars endpoints and listed in `calendars`. This field stands for the assistant's first ready calendar of this provider: setting it creates or updates that calendar, null removes it. The dashboard ignores it. ### Returned by - [Place a call](https://www.getrevox.com/docs/api/calls/place-a-call.md): `POST /call` - [Get call by ID](https://www.getrevox.com/docs/api/calls/get-call-by-id.md): `GET /call/{id}` - [Search calls](https://www.getrevox.com/docs/api/calls/search-calls.md): `POST /call/search` - [Create an assistant](https://www.getrevox.com/docs/api/assistants/create-an-assistant.md): `POST /assistants` - [Get assistant by ID](https://www.getrevox.com/docs/api/assistants/get-assistant-by-id.md): `GET /assistants/{id}` - [Get assistants](https://www.getrevox.com/docs/api/assistants/get-assistants.md): `GET /assistants` - [Update an assistant](https://www.getrevox.com/docs/api/assistants/update-an-assistant.md): `PATCH /assistants/{id}` - [Clone an assistant](https://www.getrevox.com/docs/api/assistants/clone-an-assistant.md): `POST /assistants/{id}/clone` - [Create a campaign](https://www.getrevox.com/docs/api/campaigns/create-a-campaign.md): `POST /campaigns` - [Get campaign by ID](https://www.getrevox.com/docs/api/campaigns/get-campaign-by-id.md): `GET /campaigns/{id}` - [List campaigns](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md): `GET /campaigns` - [Update a campaign](https://www.getrevox.com/docs/api/campaigns/update-a-campaign.md): `PATCH /campaigns/{id}` - [Add contacts to a campaign](https://www.getrevox.com/docs/api/campaigns/add-contacts-to-a-campaign.md): `POST /campaigns/{id}/rows` - [Get campaign rows](https://www.getrevox.com/docs/api/campaigns/get-campaign-rows.md): `GET /campaigns/{id}/rows` - [Get phone numbers](https://www.getrevox.com/docs/api/phone-numbers/get-phone-numbers.md): `GET /phone-numbers` - [Update a phone number](https://www.getrevox.com/docs/api/phone-numbers/update-a-phone-number.md): `PATCH /phone-numbers/{id}` --- ## The AssistantCalendar object A calendar an assistant books meetings on during calls: one provider, one connected account, and the calendar or event type of that account it books on. ```json { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "assistant_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "handle": "google_calendar_jane_at_example.com", "provider": "google-calendar", "status": "ready", "connection": { "provider": "google-calendar", "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "settings": { "calendar_id": "primary", "time_zone": "Europe/Paris", "duration_minutes": 30, "days": [1, 2, 3, 4, 5], "start_time": "09:00", "end_time": "18:00", "google_meet": false, "location": "{{site_address}}" } }, "account_label": "Main line", "connected_via_invite": false, "invite": { "url": "https://example.com", "status": "completed", "created_at": "2026-11-05T09:00:00Z", "expires_at": "2026-11-05T09:00:00Z" }, "created_at": "2026-11-05T09:00:00Z" } ``` ### Fields - `id` (string): Unique ID of the calendar: the {calendarId} of the calendar endpoints. - `assistant_id` (string): ID of the assistant that books on this calendar. - `handle` (string | null): How the prompt names this calendar, as @handle: the provider, then the connected account (e.g. google_calendar_jane_at_example.com). Null until an account is connected, unique within the assistant, kept when it is disconnected. At most 255 characters. Example: `"google_calendar_jane_at_example.com"`. - `provider` ("google-calendar" | "calendly" | "cal-com-oauth"): Calendar provider. - `"google-calendar"`: Google Calendar: books on a calendar of the account, with the opening hours and meeting length of its settings. - `"calendly"`: Calendly: books an event type of the account. - `"cal-com-oauth"`: Cal.com: books an event type of the account. - `status` ("not_connected" | "needs_setup" | "ready"): Whether the calendar takes bookings. - `"not_connected"`: No account is connected yet: send the invite link to the account owner, or connect an account of your organization. - `"needs_setup"`: An account is connected, but the calendar (Google) or event type (Calendly, Cal.com) to book on is not picked: list them with GET .../options and pick one with PUT .../selection. - `"ready"`: Takes bookings: the agent can book on it during calls. - `connection` (object | null): The connected account, on the calendar's provider. Null until one is connected. - One of 3, chosen by `connection.provider`: The calendar's provider, which tells which shape `settings` has. - `connection.connection_id` (string): ID of the connection to the account. Pass it to [`PUT /assistants/{id}/calendars/{calendarId}/connection`](https://www.getrevox.com/docs/api/assistants/connect-an-account-to-a-calendar.md) to connect another calendar to the same account. - When `provider` is `"google-calendar"` - `connection.settings` (object | null): What the calendar books on. Null until the calendar (Google) or event type (Calendly, Cal.com) is picked: until then the calendar takes no booking. - `connection.settings.calendar_id` (string): ID of the Google calendar to book on: 'primary' for the account's main calendar, or an id from [`GET /assistants/{id}/calendars/{calendarId}/options`](https://www.getrevox.com/docs/api/assistants/list-what-a-calendar-can-book-on.md). Example: `"primary"`. - `connection.settings.time_zone` (string): IANA timezone of start_time and end_time. Example: `"Europe/Paris"`. - `connection.settings.duration_minutes` (integer, default 30): Length of a booked meeting, in minutes. Default: 30. 5 to 480. - `connection.settings.days` (array of integer, default [1,2,3,4,5]): Open days, from 0 (Sunday) to 6 (Saturday). Default: Monday to Friday. Each item 0 to 6. - `connection.settings.start_time` (string, default "09:00"): Opening time of each open day, 'HH:mm' 24-hour, in time_zone: no meeting is booked before it. Default: '09:00'. Pattern ^\d{2}:\d{2}$. - `connection.settings.end_time` (string, default "18:00"): Closing time of each open day, 'HH:mm' 24-hour, in time_zone: a meeting must end by then. Default: '18:00'. Pattern ^\d{2}:\d{2}$. - `connection.settings.google_meet` (boolean, default true): Adds a Google Meet link to the meeting. Default: true. A calendar whose Google Workspace does not allow Meet gets the meeting without the link. - `connection.settings.location` (string | null, default null): Where the meeting takes place, written in the calendar event and the invitation. Can use the call's prompt variables, e.g. '{{site_address}}': a variable the call does not have is left out. Null (default): no location. At most 500 characters. - When `provider` is `"calendly"` - `connection.settings` (object | null): What the calendar books on. Null until the calendar (Google) or event type (Calendly, Cal.com) is picked: until then the calendar takes no booking. - `connection.settings.event_type_id` (string): The Calendly event type to book, by its URI, as [`GET /assistants/{id}/calendars/{calendarId}/options`](https://www.getrevox.com/docs/api/assistants/list-what-a-calendar-can-book-on.md) lists it. At least 1 character. Example: `"https://api.calendly.com/event_types/0b6e1f3a-7c2d-4e8b-9a5f-3d2c1b0a9e8f"`. - When `provider` is `"cal-com-oauth"` Example: `{"provider":"cal-com-oauth","connection_id":"9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d","settings":{"event_type_id":"1234567"}}`. - `connection.settings` (object | null): What the calendar books on. Null until the calendar (Google) or event type (Calendly, Cal.com) is picked: until then the calendar takes no booking. - `connection.settings.event_type_id` (string): ID of the Cal.com event type to book, as [`GET /assistants/{id}/calendars/{calendarId}/options`](https://www.getrevox.com/docs/api/assistants/list-what-a-calendar-can-book-on.md) lists it. At least 1 character. Example: `"1234567"`. - `account_label` (string | null): The connected account, usually its email. Null when not connected, or when the provider did not say. - `connected_via_invite` (boolean): True when the account was connected by a colleague from the invite link. - `invite` (object | null): The invite link a colleague can use to connect their own account to this calendar ([`POST /assistants/{id}/calendars/{calendarId}/invite`](https://www.getrevox.com/docs/api/assistants/create-an-invite-link-for-a-calendar.md)). Null when no link was created, once it was revoked, and once an account was connected from the dashboard or the API instead. - `invite.url` (string | null): Page where a colleague without a Revox account connects their own calendar to this one. Anyone holding the link can, until it expires. Only given by the calendar endpoints, null on a calendar listed in an assistant. - `invite.status` ("pending" | "completed" | "expired"): Where the invite link stands. - `"pending"`: The link works and waits for the account owner. - `"completed"`: The owner connected their account and picked the calendar to book on. - `"expired"`: The link no longer works. - `invite.created_at` (string (date-time)): When the link was created (ISO 8601). - `invite.expires_at` (string (date-time)): When the link stops working (ISO 8601): 14 days after its creation, shortened to at most 60 minutes after the colleague connects their account, the time to pick their calendar. - `created_at` (string (date-time)): When the calendar was added to the assistant (ISO 8601). ### Returned by - [Place a call](https://www.getrevox.com/docs/api/calls/place-a-call.md): `POST /call` - [Get call by ID](https://www.getrevox.com/docs/api/calls/get-call-by-id.md): `GET /call/{id}` - [Search calls](https://www.getrevox.com/docs/api/calls/search-calls.md): `POST /call/search` - [Create an assistant](https://www.getrevox.com/docs/api/assistants/create-an-assistant.md): `POST /assistants` - [Get assistant by ID](https://www.getrevox.com/docs/api/assistants/get-assistant-by-id.md): `GET /assistants/{id}` - [Get assistants](https://www.getrevox.com/docs/api/assistants/get-assistants.md): `GET /assistants` - [Update an assistant](https://www.getrevox.com/docs/api/assistants/update-an-assistant.md): `PATCH /assistants/{id}` - [Clone an assistant](https://www.getrevox.com/docs/api/assistants/clone-an-assistant.md): `POST /assistants/{id}/clone` - [Add a calendar to an assistant](https://www.getrevox.com/docs/api/assistants/add-a-calendar-to-an-assistant.md): `POST /assistants/{id}/calendars` - [Create an invite link for a calendar](https://www.getrevox.com/docs/api/assistants/create-an-invite-link-for-a-calendar.md): `POST /assistants/{id}/calendars/{calendarId}/invite` - [List an assistant's calendars](https://www.getrevox.com/docs/api/assistants/list-an-assistants-calendars.md): `GET /assistants/{id}/calendars` - [Change a calendar's settings](https://www.getrevox.com/docs/api/assistants/change-a-calendars-settings.md): `PATCH /assistants/{id}/calendars/{calendarId}` - [Connect an account to a calendar](https://www.getrevox.com/docs/api/assistants/connect-an-account-to-a-calendar.md): `PUT /assistants/{id}/calendars/{calendarId}/connection` - [Disconnect a calendar's account](https://www.getrevox.com/docs/api/assistants/disconnect-a-calendars-account.md): `DELETE /assistants/{id}/calendars/{calendarId}/connection` - [Revoke a calendar's invite link](https://www.getrevox.com/docs/api/assistants/revoke-a-calendars-invite-link.md): `DELETE /assistants/{id}/calendars/{calendarId}/invite` - [Pick what a calendar books on](https://www.getrevox.com/docs/api/assistants/pick-what-a-calendar-books-on.md): `PUT /assistants/{id}/calendars/{calendarId}/selection` - [Create a campaign](https://www.getrevox.com/docs/api/campaigns/create-a-campaign.md): `POST /campaigns` - [Get campaign by ID](https://www.getrevox.com/docs/api/campaigns/get-campaign-by-id.md): `GET /campaigns/{id}` - [List campaigns](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md): `GET /campaigns` - [Update a campaign](https://www.getrevox.com/docs/api/campaigns/update-a-campaign.md): `PATCH /campaigns/{id}` - [Add contacts to a campaign](https://www.getrevox.com/docs/api/campaigns/add-contacts-to-a-campaign.md): `POST /campaigns/{id}/rows` - [Get campaign rows](https://www.getrevox.com/docs/api/campaigns/get-campaign-rows.md): `GET /campaigns/{id}/rows` - [Get phone numbers](https://www.getrevox.com/docs/api/phone-numbers/get-phone-numbers.md): `GET /phone-numbers` - [Update a phone number](https://www.getrevox.com/docs/api/phone-numbers/update-a-phone-number.md): `PATCH /phone-numbers/{id}` --- ## The AssistantSetupIssue object A setup mistake found by [`POST /assistants/{id}/setup-check`](https://www.getrevox.com/docs/api/assistants/check-an-assistants-setup.md), with the edit that fixes it when one is known. ```json { "message": "Hello, this is Julie from Acme.", "fix": { "type": "text", "field": "prompt", "find": "{{firstname}}", "replace": "{{first_name}}" } } ``` ### Fields - `message` (string): What is wrong, in the requested locale. - `fix` (object | null): The edit that fixes the issue, or null when none is known. - One of 2, chosen by `fix.type`. - When `type` is `"text"`: A text fix: replace `find` with `replace` in the assistant field `field`, then save the assistant with [`PATCH /assistants/{id}`](https://www.getrevox.com/docs/api/assistants/update-an-assistant.md). Example: `{"type":"text","field":"prompt","find":"{{firstname}}","replace":"{{first_name}}"}`. - `fix.field` (enum (4 values)): The assistant field to edit. Values: `"prompt"`, `"first_sentence"`, `"voicemail_message"`, `"end_of_call_sentence"`. - `fix.find` (string): Text that occurs exactly once in that field. Example: `"{{firstname}}"`. - `fix.replace` (string): Its replacement. Example: `"{{first_name}}"`. - When `type` is `"voice"`: A voice fix: set the assistant's `voice` to `voice` with [`PATCH /assistants/{id}`](https://www.getrevox.com/docs/api/assistants/update-an-assistant.md). - `fix.voice` (object): The voice to switch the assistant to. - `fix.voice.provider` ("cartesia" | "elevenlabs" | "gradium"): The provider of the voice. - `fix.voice.id` (string): ID of the voice at its provider, as [`GET /voices`](https://www.getrevox.com/docs/api/voices/get-voices.md) lists it. At least 1 character. Example: `"4325f426-c4e0-418e-a0e5-97fcdfcdf8e6"`. - `fix.voice.speed` (number, may be absent): The speed of the voice. Range depends on provider: Cartesia 0.6 to 1.5, ElevenLabs 0.7 to 1.2, Gradium 0.6 to 1.5. Default is 1.0. - `fix.voice.volume` (number, may be absent): Volume of the voice (Cartesia only), 0.5 to 2.0. Default 1.0. Ignored for other providers. - `fix.voice.model` ("sonic-3" | "sonic-3.5" | "sonic-3.6", may be absent): Cartesia TTS model (Cartesia only). Defaults to sonic-3.6 when omitted. Ignored for other providers. - `fix.name` (string): That voice's name. ### Returned by - [Check an assistant's setup](https://www.getrevox.com/docs/api/assistants/check-an-assistants-setup.md): `POST /assistants/{id}/setup-check` --- ## The Call object One order to call one phone number with an assistant. Revox dials it inside the calling windows and calls back when nobody answers: each dial is an attempt, and a call can take several days of attempts. ```json { "id": "8d2f6b1a-4c9e-4f37-b215-6a0e9c3d7f12", "organization_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "from_phone_number": "+33199001234", "to_phone_number": "+33612345678", "direction": "outbound", "channel": "phone", "status": "completed", "is_completed": true, "is_cancelled": false, "cancel_reason": null, "retries_stopped": false, "callback_from": null, "calls_count": 1, "last_call_attempt": { "id": "c41f9a2e-7d3b-4e85-a6f0-1b2c3d4e5f60", "phone_number": "+33612345678", "status": "completed", "dial_error": null, "result": "human", "recording_url": "https://recordings.example.com/7c9e6679-7425-40de-944b-e07fc1f90ae7.wav", "started_at": "2026-11-09T08:30:02Z", "answered_at": "2026-11-09T08:30:09Z", "ended_at": "2026-11-09T08:31:47Z", "transcript": [ { "role": "assistant", "content": "Bonjour Marie, ici Julie du cabinet Acme. Je vous appelle pour confirmer votre rendez-vous de jeudi à 10 heures." }, { "role": "user", "content": "Oui, c'est bien noté, merci." } ], "post_call_transcript": [ { "role": "assistant", "content": "Bonjour Marie, ici Julie du cabinet Acme. Je vous appelle pour confirmer votre rendez-vous de jeudi à 10 heures." }, { "role": "user", "content": "Oui, c'est bien noté, merci." } ], "structured_output": { "appointment_confirmed": true, "preferred_callback_time": null }, "assistants_used": [ "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "b7e2d4c9-1a3f-4e6b-8d5c-2f9a0c7e1b43" ], "assistant_names": { "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34": "Reception", "b7e2d4c9-1a3f-4e6b-8d5c-2f9a0c7e1b43": "Appointment booking" }, "ended_by": "agent", "end_reason": "tool_end_call", "transferred_to": null, "handled_by_human": false, "handled_by_ai": true, "handled_by_user": null, "sms_log": [ { "id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "type": "in_call", "to_phone_number": "+33612345678", "message_body": "Votre rendez-vous du jeudi 12 novembre à 10h au cabinet dentaire Acme est confirmé.", "provider": "twilio", "provider_message_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "provider_status": "delivered", "provider_error_code": null, "created_at": "2026-11-05T09:00:00Z" } ], "actions": [ { "id": "d4c3b2a1-9e8f-4a7b-8c6d-5e4f3a2b1c0d", "phase": "in_call", "tool_name": "send_sms", "arguments": { "message": "Votre rendez-vous du jeudi 12 novembre à 10h au cabinet dentaire Acme est confirmé." }, "status": "succeeded", "error": null, "created_at": "2026-11-05T09:00:00Z" } ], "email_log": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "from_address": "Appointment reminders ", "to_emails": ["jane@example.com"], "subject": "Your appointment tomorrow", "resend_message_id": "d4c3b2a1-9e8f-4a7b-8c6d-5e4f3a2b1c0d", "calendar_invite_at": "2026-11-05T09:00:00Z", "created_at": "2026-11-05T09:00:00Z" } ] }, "call_retry_config": { "calling_windows": [ { "calling_window_start_time": "09:00", "calling_window_end_time": "18:00", "retry_delay_seconds": 7200 } ], "max_retry_attempts": 1, "allowed_days": [ "monday", "tuesday", "wednesday", "thursday", "friday" ], "excluded_dates": ["2026-11-05"], "call_twice_in_a_row": false }, "llm_model": { "type": "recommended" }, "call_attempts": [ { "id": "c41f9a2e-7d3b-4e85-a6f0-1b2c3d4e5f60", "phone_number": "+33612345678", "status": "completed", "dial_error": null, "result": "human", "recording_url": "https://recordings.example.com/7c9e6679-7425-40de-944b-e07fc1f90ae7.wav", "started_at": "2026-11-09T08:30:02Z", "answered_at": "2026-11-09T08:30:09Z", "ended_at": "2026-11-09T08:31:47Z", "transcript": [ { "role": "assistant", "content": "Bonjour Marie, ici Julie du cabinet Acme. Je vous appelle pour confirmer votre rendez-vous de jeudi à 10 heures." }, { "role": "user", "content": "Oui, c'est bien noté, merci." } ], "post_call_transcript": [ { "role": "assistant", "content": "Bonjour Marie, ici Julie du cabinet Acme. Je vous appelle pour confirmer votre rendez-vous de jeudi à 10 heures." }, { "role": "user", "content": "Oui, c'est bien noté, merci." } ], "structured_output": { "appointment_confirmed": true, "preferred_callback_time": null }, "assistants_used": [ "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "b7e2d4c9-1a3f-4e6b-8d5c-2f9a0c7e1b43" ], "assistant_names": { "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34": "Reception", "b7e2d4c9-1a3f-4e6b-8d5c-2f9a0c7e1b43": "Appointment booking" }, "ended_by": "agent", "end_reason": "tool_end_call", "transferred_to": null, "handled_by_human": false, "handled_by_ai": true, "handled_by_user": null, "sms_log": [ { "id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "type": "in_call", "to_phone_number": "+33612345678", "message_body": "Votre rendez-vous du jeudi 12 novembre à 10h au cabinet dentaire Acme est confirmé.", "provider": "twilio", "provider_message_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "provider_status": "delivered", "provider_error_code": null, "created_at": "2026-11-05T09:00:00Z" } ], "actions": [ { "id": "d4c3b2a1-9e8f-4a7b-8c6d-5e4f3a2b1c0d", "phase": "in_call", "tool_name": "send_sms", "arguments": { "message": "Votre rendez-vous du jeudi 12 novembre à 10h au cabinet dentaire Acme est confirmé." }, "status": "succeeded", "error": null, "created_at": "2026-11-05T09:00:00Z" } ], "email_log": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "from_address": "Appointment reminders ", "to_emails": ["jane@example.com"], "subject": "Your appointment tomorrow", "resend_message_id": "d4c3b2a1-9e8f-4a7b-8c6d-5e4f3a2b1c0d", "calendar_invite_at": "2026-11-05T09:00:00Z", "created_at": "2026-11-05T09:00:00Z" } ] } ], "assistant": { "id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "prompt": "You are Julie from Acme. You call {{first_name}} to confirm tomorrow's appointment.", "post_call_prompt": "Send the appointment address by SMS if asked.", "first_sentence": "Hello {{first_name}}, this is Julie from Acme.", "first_sentence_mode": "generated", "end_of_call_sentence": "Thank you, have a good day.", "voice": { "provider": "cartesia", "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6", "speed": 1, "volume": 1, "model": "sonic-3" }, "voice_languages": [ { "language": "en", "voice": { "provider": "cartesia", "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6", "speed": 1, "volume": 1, "model": "sonic-3" } } ], "cartesia_dictionary_pronunciation_id": "6f9a3c1e-2b7d-4e58-9a10-3d2c4b5e6f70", "llm_model": { "type": "recommended" }, "webhook_url": "https://example.com/revox-webhook", "max_call_duration_secs": 600, "max_duration_end_message": "Thank you, have a good day.", "structured_output_config": [ { "name": "budget", "type": "string", "description": "Books a slot in the agenda.", "required": false, "enum_options": ["enum option"] } ], "structured_output_prompt": "Send the appointment address by SMS if asked.", "call_retry_config": { "calling_windows": [ { "calling_window_start_time": "09:00", "calling_window_end_time": "18:00", "retry_delay_seconds": 7200 } ], "max_retry_attempts": 1, "allowed_days": [ "monday", "tuesday", "wednesday", "thursday", "friday" ], "excluded_dates": ["2026-11-05"], "call_twice_in_a_row": false }, "timezone": "Europe/Paris", "background_sound": "audio/office.ogg", "background_sound_volume": 1, "thinking_sound": "city-ambience.ogg", "thinking_sound_volume": 1, "thinking_sound_probability": 0, "transfer_destinations": [ { "label": "Main line", "phone_number": "+33612345678" } ], "human_transfer_mode": "warm", "warm_transfer_summary_instructions": "Send the appointment address by SMS if asked.", "warm_transfer_voice_speed": 1, "ivr_navigation_enabled": true, "voicemail_message": "Thank you, have a good day.", "stt_context": { "general": [{ "key": "crm_id", "value": "lead_8812" }], "terms": ["term"] }, "stt_model": "stt-rt-v4", "first_sentence_delay_ms": 400, "calendars": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "assistant_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "handle": "google_calendar_jane_at_example.com", "provider": "google-calendar", "status": "ready", "connection": { "provider": "google-calendar", "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "settings": { "calendar_id": "primary", "time_zone": "Europe/Paris", "duration_minutes": 30, "days": [1, 2, 3, 4, 5], "start_time": "09:00", "end_time": "18:00", "google_meet": false, "location": "{{site_address}}" } }, "account_label": "Main line", "connected_via_invite": false, "invite": { "url": "https://example.com", "status": "completed", "created_at": "2026-11-05T09:00:00Z", "expires_at": "2026-11-05T09:00:00Z" }, "created_at": "2026-11-05T09:00:00Z" } ], "calendly": null, "cal": null, "google_calendar": null, "hubspot": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "precall_lookup_enabled": true, "meeting_links": [ { "slug": "jane-martin", "label": "Main line", "duration_ms": 1800000, "is_fallback": false, "booking_url": "https://example.com" } ], "post_call_sync": { "enabled": true, "field_mapping": [ { "source": "email", "hubspot_property": "email" } ] } }, "slack": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "channels": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "name": "Appointment reminder" } ] }, "teams": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "channels": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "name": "Appointment reminder", "team_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "team_name": "Sales" } ] }, "zoho": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "module": "Leads", "log_call_activity": false, "field_mapping": [ { "source": "email", "zoho_field": "Email" } ], "template": "{{outcome}}: {{summary}}\n{{call_url}}" }, "custom_tools": [ { "name": "appointment_reminder", "description": "Books a slot in the agenda.", "method": "GET", "url": "https://example.com", "headers": [{ "key": "crm_id", "value": "lead_8812" }], "query_params": [ { "key": "crm_id", "value": "lead_8812" } ], "body_template": "{\"email\": \"{{email}}\", \"name\": \"{{first_name}}\"}", "input_schema": [ { "name": "budget", "type": "string", "description": "Books a slot in the agenda.", "required": false, "enum_options": ["enum option"] } ] } ], "from_phone_number": "+33187654321", "demo_page_url": "https://example.com", "precall_lookup_url": "https://example.com", "precall_lookup_headers": [ { "key": "crm_id", "value": "lead_8812" } ], "organization_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "name": "Appointment reminders", "is_inbound_receptionist": false, "created_by": { "id": "5a7c9e1b-3d5f-4a2c-8e6b-0f1a2b3c4d5e", "email": "jane@example.com", "first_name": "Marie", "last_name": "Martin" }, "created_at": "2026-11-05T09:00:00Z", "updated_at": "2026-11-05T09:02:41Z" }, "prompt_version": { "id": "6f9a3c1e-2b7d-4e58-9a10-3d2c4b5e6f70", "number": 1, "latest_number": 1 }, "campaign": { "id": "8e1f2a3b-4c5d-4e6f-9a0b-1c2d3e4f5a6b", "name": "Appointment reminder", "status": "completed" }, "scheduled_at": "2026-11-09T08:30:00Z", "created_at": "2026-11-06T16:12:45Z", "updated_at": "2026-11-09T08:32:20Z", "metadata": { "crm_id": "lead_48213" }, "prompt_variables": { "first_name": "Marie", "company": "Acme" }, "transfer_destinations": [ { "label": "Main line", "phone_number": "+33612345678" } ], "contact": { "first_name": "Marie", "last_name": "Martin", "email": "jane@example.com", "company": "Acme", "job_title": "Office manager" }, "first_sentence_delay_ms": 400, "outcome": "interested", "outcome_summary": "Marie confirmed her appointment on Thursday at 10:00 and asked for the address by text message.", "do_not_call": false, "assignee": { "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "email": "jane@example.com", "first_name": "Marie", "last_name": "Martin" } } ``` ### Fields - `id` (string): The ID of the call. Example: `"8d2f6b1a-4c9e-4f37-b215-6a0e9c3d7f12"`. - `organization_id` (string): The ID of the organization that owns the call. - `from_phone_number` (string): The phone number that made the call (the caller ID of an outbound call), in E.164 format. Example: `"+33199001234"`. - `to_phone_number` (string): The phone number that received the call (the person called, for an outbound call), in E.164 format. Example: `"+33612345678"`. - `direction` ("inbound" | "outbound"): Whether Revox placed the call or received it. - `"inbound"`: Someone called one of your numbers and an assistant answered. - `"outbound"`: Revox called the number: from [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md), a campaign or the dashboard. - `channel` ("phone" | "web"): Where the call takes place. - `"phone"`: A phone call. - `"web"`: A test call taken in the browser, from the dashboard: its phone number is a placeholder, never dialed. - `status` (enum (10 values)): Where the call stands. Final statuses, after which nothing changes: completed, cancelled, errored. - `"initializing"`: Being created, not scheduled yet. Newer calls start as scheduled instead. - `"queued_for_calling"`: Its turn came: the attempt is about to dial, within your concurrent call limit. - `"calling"`: An attempt is in progress: the phone is ringing or a conversation is going on. - `"post_processing"`: The phone conversation is over; the transcript, outcome and extracted data are being computed. It can no longer be paused or cancelled. - `"not_launched"`: Created but never sent: a campaign call waiting for [`POST /campaigns/{id}/launch-calls`](https://www.getrevox.com/docs/api/campaigns/launch-a-campaigns-calls.md). It is not dialed until then. - `"scheduled"`: Waiting to be dialed at scheduled_at (the first attempt, a retry or a requested callback). A call due outside its calling windows waits for the next one. - `"paused"`: No new attempt is made until it is resumed ([`POST /call/{id}/resume`](https://www.getrevox.com/docs/api/calls/resume-a-paused-call.md), or resuming its campaign). - `"completed"`: Final. Revox will not dial it again: a person or a phone menu answered, or the last attempt allowed by call_retry_config was made. outcome and last_call_attempt tell how it went. - `"cancelled"`: Final. Cancelled before it completed: by a user ([`POST /call/{id}/cancel`](https://www.getrevox.com/docs/api/calls/cancel-a-call.md), the dashboard, a campaign cancel), or because the prospect called back (see cancel_reason). - `"errored"`: Final. The call could not be placed and will not be retried: the number does not exist, the destination cannot be called, the organization ran out of credits, or an internal error stopped it. - `cancel_reason` ("prospect_called_back" | null, may be absent): Why the call was cancelled, when it can be told. Null for a cancel by a user or a campaign, and for calls that are not cancelled. - `"prospect_called_back"`: The prospect called back before the next retry: the pending retry was cancelled, and their call is recorded as a separate inbound call. - `retries_stopped` (boolean, default false): Whether no further attempt will be made for this call: it was cancelled, or its future attempts were stopped while an attempt was already in progress (that attempt still finishes). Unlike `is_cancelled`, this is true as soon as retries are stopped, before the call reaches a terminal status. - `callback_from` (object | null, may be absent): For an inbound call only: the outbound call this one answers, when the prospect rang us back after we called them. Null for every other call. A callback is matched on the caller's number against outbound calls dialed within the last 2 days on a shared Revox number, or within the last 30 days on a number dedicated to your organization (only your own calls are matched there), counted from the last attempt. A matched callback carries the outbound call's `metadata` over, cancels its pending retries, and is answered by the outbound call's assistant when the prospect dials back the number we called from (or when the number they dial has no inbound assistant), otherwise by that number's inbound assistant. Its end-of-call webhook goes to the `webhook_url` of the assistant that answers. - `callback_from.call_id` (string): ID of the outbound call the prospect is calling back. - `callback_from.created_at` (string (date-time)): When that outbound call was created (ISO 8601). - `calls_count` (number): The number of call attempts made. Example: `1`. - `last_call_attempt` ([CallAttempt](https://www.getrevox.com/docs/api/objects/call-attempt.md) | null): The most recent attempt, the same as the first entry of call_attempts. Null until a first attempt is made. - `call_retry_config` ([CallRetryConfig](https://www.getrevox.com/docs/api/objects/call-retry-config.md) | null): Retry configuration this call follows: calling windows, allowed days, delay between attempts and maximum attempts. Copied when the call is created from the assistant's, or the campaign's for a campaign call, with the per-call overrides of [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md) (timezone, call_twice_in_a_row) applied. - `llm_model` (object): The LLM that drives this call, copied from the assistant when the call is created. - One of 4, chosen by `llm_model.type`. - When `type` is `"recommended"`: The LLM Revox currently recommends for voice agents, chosen server-side and upgraded without any change on your side. No per-assistant configuration. Example: `{"type":"recommended"}`. - When `type` is `"gpt-4.1-priority"`: OpenAI gpt-4.1 on the priority tier, with gpt-4.1-mini answering a turn when gpt-4.1 is slow to respond. No per-assistant configuration. Example: `{"type":"gpt-4.1-priority"}`. - When `type` is `"realtime"`: A realtime speech-to-speech model: it listens to the call and answers with its own voice (realtime_voice_id), instead of the assistant's transcriber and voice. Example: `{"type":"realtime","provider":"openai","realtime_model_id":"gpt-realtime","realtime_voice_id":"marin"}`. - `llm_model.provider` ("openai" | "google"): Provider of the realtime model. - `llm_model.realtime_model_id` (string): ID of the realtime model: 'gpt-realtime' (provider 'openai'), 'gemini-3.1-flash-live-preview' (provider 'google'), 'gemini-2.5-flash-native-audio-preview-12-2025' (provider 'google'). Example: `"gpt-realtime"`. - `llm_model.realtime_voice_id` (string, may be absent): Output voice for the realtime provider (e.g. OpenAI: marin; Gemini: Puck). At least 1 character. Example: `"marin"`. - When `type` is `"dedicated-instance"` or `"fireworks"` or `"openrouter"` or `"custom"` or `"gemma-4-31b-racing"` (Legacy) (deprecated): A model type that is no longer offered, kept on calls made while it was. Example: `{"type":"dedicated-instance"}`. - `call_attempts` (array of [CallAttempt](https://www.getrevox.com/docs/api/objects/call-attempt.md)): All call attempts for this call order, ordered by most recent first. - `assistant` ([Assistant](https://www.getrevox.com/docs/api/objects/assistant.md) | null): The assistant the call was placed with, as it is configured now (not a snapshot taken at call time). Null for a call made with an inline `assistant` configuration, and when the assistant was deleted. - `prompt_version` (object | null, may be absent): The assistant prompt version the call's prompt was compiled from. Null for calls created before versions were tracked, and for calls made with an inline assistant. - `prompt_version.id` (string): The ID of the assistant prompt version. - `prompt_version.number` (integer): The version's number in the assistant's prompt history (v1 is the oldest). - `prompt_version.latest_number` (integer): The number of the assistant's current prompt version. Higher than `number` when the call was left on an older version, e.g. because it lacks a variable the newer prompt uses. - `campaign` (object | null): The campaign this call belongs to. Null for a call outside any campaign. - `campaign.id` (string): ID of the campaign. - `campaign.name` (string): Name of the campaign. - `campaign.status` ("running" | "paused" | "completed"): Where the campaign stands. A cancelled campaign is flagged by is_cancelled, not by its status. - `"running"`: Active: its launched calls are placed. A campaign is running from its creation on, before any call is launched too. - `"paused"`: No new call is placed until the campaign is resumed ([`POST /campaigns/{id}/resume`](https://www.getrevox.com/docs/api/campaigns/resume-a-paused-campaign.md)). - `"completed"`: Every contact is done. Launching calls again sets it back to running. - `scheduled_at` (string (date-time) | null): When the call's next attempt is due (ISO 8601): the requested start for a new call, then the time of the next retry. Null when no time is set, e.g. for a campaign call not launched yet. Example: `"2026-11-09T08:30:00Z"`. - `created_at` (string (date-time)): When the call was created. Example: `"2026-11-06T16:12:45Z"`. - `updated_at` (string (date-time)): When the call last changed: a status change, a new attempt or an analysis result. [`POST /call/search`](https://www.getrevox.com/docs/api/calls/search-calls.md) sorts on it by default. Example: `"2026-11-09T08:32:20Z"`. - `metadata` (object | null): Your own key/value pairs stored with the call (e.g. your CRM ID), as sent in [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md). On an inbound callback (`callback_from` set), the metadata of the outbound call it answers, copied over whichever assistant answers; null on other inbound calls. The query and variables filters of [`POST /call/search`](https://www.getrevox.com/docs/api/calls/search-calls.md) match them. Keys: A key of your choice. - `prompt_variables` (object | null): The values of the assistant's {{variables}} for this call, keyed by variable name. Keys: Variable name, as written between the braces: name for {{name}}. - `transfer_destinations` (array of object | null): Where this call can be transferred, if anywhere. - `transfer_destinations.label` (string): Human-meaningful name for this destination (e.g. "Sales"). The assistant's prompt refers to these labels when describing who to transfer to. 1 to 60 characters. - `transfer_destinations.phone_number` (string): Destination phone number in E.164 format (e.g. +33612345678). - `contact` (object): Who the prospect is, read from the call's prompt variables and, after the call, from the transcript. - `contact.first_name` (string | null): The prospect's first name. Null when unknown. - `contact.last_name` (string | null): The prospect's last name. Null when unknown. - `contact.email` (string | null): The prospect's email address. Null when unknown. - `contact.company` (string | null): The prospect's company. Null when unknown. - `contact.job_title` (string | null): The prospect's job title. Null when unknown. - `first_sentence_delay_ms` (integer): Delay in milliseconds before speaking the first sentence. Default: 400. - `outcome` (enum (4 values) | null, may be absent): How the call went for your business, set after the conversation. Null until computed, and when nobody talked. - `"not_interested"`: The person declined, refused or showed no interest. - `"interested"`: The person engaged and is a lead to follow up: the strongest outcome the AI assigns. - `"completed"`: A person from your team talked to the prospect: they joined the call, the call was transferred to them, or they set this outcome by hand. Never assigned by the AI. - `"requested_callback_later"`: The person asked to be called back later. When they gave a time and attempts are left, the call is scheduled again for that time. - `outcome_summary` (string | null, may be absent): Why the call got its outcome, in a few sentences written from the transcript. Null when there is no outcome. Example: `"Marie confirmed her appointment on Thursday at 10:00 and asked for the address by text message."`. - `do_not_call` (boolean, may be absent): True when the prospect's phone number is on the do-not-call list: it can no longer be called. - `assignee` (object | null): The team member assigned to follow up on this call. Null when unassigned. - `assignee.id` (string): User ID of the team member, the value assignee_ids takes in [`POST /call/search`](https://www.getrevox.com/docs/api/calls/search-calls.md). - `assignee.email` (string): The user's email address. - `assignee.first_name` (string | null): The user's first name. Null when not set on their account. - `assignee.last_name` (string | null): The user's last name. Null when not set on their account. - `is_completed` (boolean, deprecated, default false): Deprecated: read status. True when status is 'completed', false for every other status, cancelled and errored included. - `is_cancelled` (boolean, deprecated, default false): Deprecated: read status. True when status is 'cancelled'. ### Returned by - [Place a call](https://www.getrevox.com/docs/api/calls/place-a-call.md): `POST /call` - [Get call by ID](https://www.getrevox.com/docs/api/calls/get-call-by-id.md): `GET /call/{id}` - [Search calls](https://www.getrevox.com/docs/api/calls/search-calls.md): `POST /call/search` - [Get campaign rows](https://www.getrevox.com/docs/api/campaigns/get-campaign-rows.md): `GET /campaigns/{id}/rows` --- ## The CallAttempt object One dial of a call's phone number, with what answered, the transcript, the recording and the extracted data. A call makes one or more attempts. ```json { "id": "c41f9a2e-7d3b-4e85-a6f0-1b2c3d4e5f60", "phone_number": "+33612345678", "status": "completed", "dial_error": null, "result": "human", "recording_url": "https://recordings.example.com/7c9e6679-7425-40de-944b-e07fc1f90ae7.wav", "started_at": "2026-11-09T08:30:02Z", "answered_at": "2026-11-09T08:30:09Z", "ended_at": "2026-11-09T08:31:47Z", "transcript": [ { "role": "assistant", "content": "Bonjour Marie, ici Julie du cabinet Acme. Je vous appelle pour confirmer votre rendez-vous de jeudi à 10 heures." }, { "role": "user", "content": "Oui, c'est bien noté, merci." } ], "post_call_transcript": [ { "role": "assistant", "content": "Bonjour Marie, ici Julie du cabinet Acme. Je vous appelle pour confirmer votre rendez-vous de jeudi à 10 heures." }, { "role": "user", "content": "Oui, c'est bien noté, merci." } ], "structured_output": { "appointment_confirmed": true, "preferred_callback_time": null }, "assistants_used": [ "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "b7e2d4c9-1a3f-4e6b-8d5c-2f9a0c7e1b43" ], "assistant_names": { "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34": "Reception", "b7e2d4c9-1a3f-4e6b-8d5c-2f9a0c7e1b43": "Appointment booking" }, "ended_by": "agent", "end_reason": "tool_end_call", "transferred_to": null, "handled_by_human": false, "handled_by_ai": true, "handled_by_user": null, "sms_log": [ { "id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "type": "in_call", "to_phone_number": "+33612345678", "message_body": "Votre rendez-vous du jeudi 12 novembre à 10h au cabinet dentaire Acme est confirmé.", "provider": "twilio", "provider_message_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "provider_status": "delivered", "provider_error_code": null, "created_at": "2026-11-05T09:00:00Z" } ], "actions": [ { "id": "d4c3b2a1-9e8f-4a7b-8c6d-5e4f3a2b1c0d", "phase": "in_call", "tool_name": "send_sms", "arguments": { "message": "Votre rendez-vous du jeudi 12 novembre à 10h au cabinet dentaire Acme est confirmé." }, "status": "succeeded", "error": null, "created_at": "2026-11-05T09:00:00Z" } ], "email_log": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "from_address": "Appointment reminders ", "to_emails": ["jane@example.com"], "subject": "Your appointment tomorrow", "resend_message_id": "d4c3b2a1-9e8f-4a7b-8c6d-5e4f3a2b1c0d", "calendar_invite_at": "2026-11-05T09:00:00Z", "created_at": "2026-11-05T09:00:00Z" } ] } ``` ### Fields - `id` (string): The ID of the call attempt. Example: `"c41f9a2e-7d3b-4e85-a6f0-1b2c3d4e5f60"`. - `phone_number` (string): The phone number that was called, in E.164 format. Example: `"+33612345678"`. - `status` (enum (5 values)): Where the attempt stands. - `"queued"`: Created: the phone is not ringing yet. - `"ringing"`: Dialed: the phone is ringing. - `"ongoing"`: Answered: the conversation is in progress. - `"completed"`: Final. The line connected and the attempt ended: see result, ended_by and end_reason. - `"error"`: Final. The attempt could not connect: see dial_error. - `dial_error` (enum (10 values) | null): Why the call could not be connected, from the carrier's SIP response (e.g. busy, no_answer, number_non_attributed for a number that does not exist). Null when the call connected or no SIP error was reported. - `"number_non_attributed"`: The number does not exist or is not assigned (SIP 404). The call ends as errored, without retry. - `"too_many_calls"`: The carrier refused the call: too many calls (SIP 429). - `"busy"`: The line was busy (SIP 486). - `"temporarily_unavailable"`: The phone could not be reached, e.g. switched off or out of coverage (SIP 480). - `"no_answer"`: Nobody answered before the ringing timed out. - `"rejected"`: The call was declined, by the person or by an anti-spam filter of their carrier (SIP 603). - `"blocked"`: The carrier blocked the call ('Network Blocked'). - `"no_international_permission"`: The destination cannot be called from the caller number (SIP 403). The call ends as errored. - `"precondition_failed"`: The carrier refused the call setup (SIP 412). - `"non_classified_error"`: Another error, not classified. - `result` (enum (5 values) | null): What answered the call. Null until the call was analysed, and when nobody answered. - `"IVR"`: An automated phone menu answered (e.g. 'press 1 for sales'). - `"voicemail"`: A voicemail or an answering machine answered. - `"human"`: A person answered. - `"unknown"`: Silence, or audio that could not be classified. - `"screening-filter"`: A call screening assistant (Apple or Google) answered for the person and asked who is calling and why. - `recording_url` (string | null): URL of the audio recording of the attempt (a WAV file). Null until the recording is ready, and when there is none. Example: `"https://recordings.example.com/7c9e6679-7425-40de-944b-e07fc1f90ae7.wav"`. - `started_at` (string (date-time) | null): When the attempt was dialed. Null until it is. Example: `"2026-11-09T08:30:02Z"`. - `answered_at` (string (date-time) | null): When the call was picked up. Null when it was not. Example: `"2026-11-09T08:30:09Z"`. - `ended_at` (string (date-time) | null): When the attempt ended. Null until it does. Example: `"2026-11-09T08:31:47Z"`. - `transcript` (array of object | null, may be absent): The live transcript of the call, built as the conversation goes. Null or empty when nobody talked. - `transcript.role` ("user" | "assistant" | "human_agent" | "tool"): Who the entry is from. - `"user"`: The person on the phone. - `"assistant"`: The AI agent. - `"human_agent"`: A person from your team who took over the call or was briefed in a warm transfer. Post-call transcript only. - `"tool"`: A tool the agent ran. - `transcript.content` (string): What was said. For a 'tool' entry, a readable summary of the tool name, arguments and output. - `transcript.tool_name` (string, may be absent): 'tool' entries only: name of the tool the agent ran. - `transcript.tool_arguments` (object | string, may be absent): 'tool' entries only: the arguments the tool was called with, as an object or a JSON string. - `transcript.tool_output` (string, may be absent): 'tool' entries only: what the tool returned to the agent. - `transcript.tool_is_error` (boolean, may be absent): 'tool' entries only: true when the tool failed. - `post_call_transcript` (array of object | null, may be absent): A more accurate transcript, made from the recording after the call. Null until it is ready, and when there is no recording. - `post_call_transcript.role` ("user" | "assistant" | "human_agent" | "tool"): Who the entry is from. - `"user"`: The person on the phone. - `"assistant"`: The AI agent. - `"human_agent"`: A person from your team who took over the call or was briefed in a warm transfer. Post-call transcript only. - `"tool"`: A tool the agent ran. - `post_call_transcript.content` (string): What was said. For a 'tool' entry, a readable summary of the tool name, arguments and output. - `post_call_transcript.tool_name` (string, may be absent): 'tool' entries only: name of the tool the agent ran. - `post_call_transcript.tool_arguments` (object | string, may be absent): 'tool' entries only: the arguments the tool was called with, as an object or a JSON string. - `post_call_transcript.tool_output` (string, may be absent): 'tool' entries only: what the tool returned to the agent. - `post_call_transcript.tool_is_error` (boolean, may be absent): 'tool' entries only: true when the tool failed. - `structured_output` (object | null, may be absent): The data extracted from this attempt's conversation, one entry per field of the assistant's structured_output_config. Null until extracted, and when the assistant extracts nothing. Keys: Name of a field of the assistant's structured_output_config. - `assistants_used` (array of string | null, may be absent): IDs of the assistants the attempt went through, in order: several for a multi-step flow. - `assistant_names` (object, may be absent): Names of the assistants in `assistants_used`, keyed by ID. Only set when the attempt went through several assistants (a multi-step call). Keys: ID of an assistant of assistants_used. - `ended_by` ("agent" | "user" | "system" | null, may be absent): Who ended the call. Null when the call was never picked up. - `"agent"`: The AI agent hung up (see end_reason). - `"user"`: The other party hung up, or the line dropped on their side. - `"system"`: Revox ended the call, e.g. at a time limit. - `end_reason` (enum (17 values) | null, may be absent): Why the call ended, along with ended_by. Null when not reported. - `"client_initiated"`: The other party hung up. - `"connection_timeout"`: The phone connection timed out. - `"human_takeover"`: A person from your team had taken over the call, and the call ended. - `"ivr_no_navigate"`: A phone menu answered and the agent hung up: it was not set to navigate menus (ivr_navigation_enabled). - `"max_duration"`: The call reached the assistant's max_call_duration_secs: the agent said max_duration_end_message, if set, and hung up. - `"participant_removed"`: The phone line was removed from the call by the server. - `"sip_trunk_failure"`: The phone carrier's line failed during the call. - `"tool_end_call"`: The agent decided the conversation was over and hung up. - `"transfer"`: The call was transferred to one of transfer_destinations. - `"user_inactive"`: The agent hung up because the other party stopped responding. - `"user_rejected"`: The other party declined the call. - `"user_unavailable"`: The other party could not be reached. - `"voicemail"`: A voicemail answered: the agent hung up, after leaving voicemail_message when one is set. - `"speed_dial_abandoned"`: Speed dial session: another contact answered first, so this answered call was hung up. - `"speed_dial_operator_missed"`: Speed dial session: a person answered, but the operator did not join in time. - `"speed_dial_timeout"`: Speed dial session: the call hit its time limit before an operator was connected. - `"speed_dial_hangup"`: Speed dial session: the person hung up before being put through to the operator. - `transferred_to` (string | null, may be absent): The number the call was transferred to, in E.164 format (e.g. +33123456789). Recorded by the agent from the destination it actually dialled, so it is the destination itself and not a name read off the transcript. Null when the call was not transferred, and on transfers placed before this was tracked. Example: `null`. - `handled_by_human` (boolean): Whether a person from your team took part in this attempt: they joined the call live from the dashboard, or the call was transferred to them. - `handled_by_ai` (boolean): Whether the AI agent conducted the conversation on this attempt. False for attempts that were never answered, and for speed dial calls, where the agent only listens for a person before handing over. - `handled_by_user` (object | null): The person from your team who took over this attempt live from the dashboard. Null when nobody did, and for takeovers recorded before this was tracked. - `handled_by_user.id` (string): User ID of the team member, the value assignee_ids takes in [`POST /call/search`](https://www.getrevox.com/docs/api/calls/search-calls.md). - `handled_by_user.email` (string): The user's email address. - `handled_by_user.first_name` (string | null): The user's first name. Null when not set on their account. - `handled_by_user.last_name` (string | null): The user's last name. Null when not set on their account. - `sms_log` (array of object | null, may be absent): Every SMS sent in connection with the call (by the agent during the call, after a voicemail, after the call), oldest first. - `sms_log.id` (string): Unique ID of this SMS record. - `sms_log.type` ("in_call" | "voicemail" | "after_call"): Why the SMS was sent. - `"in_call"`: Sent by the agent during the call. - `"voicemail"`: Sent after the call reached voicemail. - `"after_call"`: Sent after an answered call completed. - `sms_log.to_phone_number` (string): Recipient phone number, in E.164 format. - `sms_log.message_body` (string): Text of the SMS as sent. Example: `"Votre rendez-vous du jeudi 12 novembre à 10h au cabinet dentaire Acme est confirmé."`. - `sms_log.provider` ("twilio" | "vonage"): Messaging provider the SMS went through, chosen by the recipient's country. - `sms_log.provider_message_id` (string | null): The provider's ID for the message (a Twilio SM… SID or a Vonage UUID). Null when the provider returned none. - `sms_log.provider_status` (string | null): Delivery status in the provider's own vocabulary (Twilio queued/sent/delivered/failed/undelivered), so only interpretable alongside `provider`. Null when the provider has not reported one, which is always the case for Vonage. Example: `"delivered"`. - `sms_log.provider_error_code` (string | null): The provider's numeric reason for a terminal failure (e.g. Twilio 30034). Null unless the message failed. Example: `null`. - `sms_log.created_at` (string (date-time)): When the SMS was sent. - `actions` (array of object | null, may be absent): Tools the agent ran for this attempt, in call and after it, ordered oldest first. This is the decision trail; what was delivered is in `sms_log` and `email_log`. - `actions.id` (string): Unique ID of this action record. - `actions.phase` ("in_call" | "post_call"): When the tool ran. - `"in_call"`: During the conversation. - `"post_call"`: By the post-call agent, once the call had ended. - `actions.tool_name` (string): Name of the tool the agent ran (e.g. 'send_sms'). Example: `"send_sms"`. - `actions.arguments` (object): The arguments the agent called the tool with. - `actions.status` ("succeeded" | "failed"): Whether the tool run succeeded or failed. - `actions.error` (string | null): Why the tool failed. Null when it succeeded. - `actions.created_at` (string (date-time)): When the tool ran. - `email_log` (array of object | null, may be absent): Notification emails sent in connection with the call, ordered oldest first (from/to addresses, subject, sent time). - `email_log.id` (string): Unique ID of this email record. - `email_log.from_address` (string): Sender address of the email. Example: `"Appointment reminders "`. - `email_log.to_emails` (array of string): Recipient email addresses. - `email_log.subject` (string): Subject line of the email. - `email_log.resend_message_id` (string | null): ID of the email at the email provider that sent it. Null when the provider returned none. - `email_log.calendar_invite_at` (string (date-time) | null): Start of the callback or meeting the attached calendar invitation (`invite.ics`) was for. Null when the email carried no invitation. - `email_log.created_at` (string (date-time)): When the email was sent. ### Returned by - [Place a call](https://www.getrevox.com/docs/api/calls/place-a-call.md): `POST /call` - [Get call by ID](https://www.getrevox.com/docs/api/calls/get-call-by-id.md): `GET /call/{id}` - [Search calls](https://www.getrevox.com/docs/api/calls/search-calls.md): `POST /call/search` - [Get campaign rows](https://www.getrevox.com/docs/api/campaigns/get-campaign-rows.md): `GET /campaigns/{id}/rows` --- ## The CallRetryConfig object When and how often a call is dialed: the calling windows and allowed days, the delay between two attempts and the maximum number of attempts. Omitted in a request: the default of each field. ```json { "calling_windows": [ { "calling_window_start_time": "09:00", "calling_window_end_time": "18:00", "retry_delay_seconds": 7200 } ], "max_retry_attempts": 1, "allowed_days": [ "monday", "tuesday", "wednesday", "thursday", "friday" ], "excluded_dates": ["2026-11-05"], "call_twice_in_a_row": false } ``` ### Fields - `calling_windows` (array of object): Daily time windows in which calls may be placed, on the allowed_days. A call due outside every window waits for the next one to open. Request bodies need at least one window. - `calling_windows.calling_window_start_time` (string): Start time of the calling window, in `timezone` (each callee's own timezone when it is null). Format: 'HH:mm' (24-hour) or 'h:mma' (12-hour, minutes required). Examples: '09:00', '10:00am'. Default: '10:00'. - `calling_windows.calling_window_end_time` (string): End time of the calling window, in `timezone` (each callee's own timezone when it is null). Must be after the start time: a window cannot span midnight. Format: 'HH:mm' (24-hour) or 'h:mma' (12-hour, minutes required). Examples: '17:00', '6:00pm'. Default: '18:00'. - `calling_windows.retry_delay_seconds` (integer, default 7200): Delay between retry attempts in seconds. Values below the 15-minute minimum are raised to it: a shorter delay means calling someone again minutes after they declined. For one deliberate immediate second dial, use call_twice_in_a_row. Default: 7200 (2 hours). ≥ 0. - `max_retry_attempts` (integer, default 5): Maximum number of call attempts, first call included. Default: 5. Capped by the organization's plan: 5 on Starter, 8 on Business. A contact nobody picks up is billed once all its attempts were placed. > 0. - `allowed_days` (array of enum (7 values), default ["monday","tuesday","wednesday","thursday","friday"]): Days of the week when calls are allowed, in the same timezone as the calling windows. Default: Monday through Friday. Values: `"monday"`, `"tuesday"`, `"wednesday"`, `"thursday"`, `"friday"`, `"saturday"`, `"sunday"`. - `excluded_dates` (array of string (date), may be absent): Calendar dates on which no call goes out, such as public holidays or days the office is closed, as 'YYYY-MM-DD' (e.g. ['2026-12-25', '2027-01-01']). Read in the same timezone as the calling windows: each callee's local date when timezone is null. A call or retry that would land on an excluded date waits for the next open window after it. Up to 366 dates; duplicates are removed and the list is sorted. A call placed with skip_calling_window ignores them for its first dial only. Default: none. At most 366 items. - `call_twice_in_a_row` (boolean, default false): Double call. If true and max_retry_attempts >= 2, when the first attempt reaches nobody (no answer, declined, voicemail, call screening nobody took), the second attempt is dialed within seconds instead of after retry_delay_seconds, from the same caller number. Two calls in a row from one number raise the pickup rate. Each call is an attempt: the double call counts as 2 when both calls happen, 1 when the first is picked up. Busy or unreachable phones are retried after the normal delay. Calling days and hours still apply. Only the first attempt is doubled; later ones follow retry_delay_seconds. A voicemail_message is left on the second dial only. Default: false. - `timezone` (string | null, may be absent, deprecated): Deprecated: use the `timezone` field of the assistant, the campaign or [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md). Still accepted on writes and copied there, and returned with that value. Null no longer means each callee's own timezone: a call's timezone is never derived from its phone number. ### Returned by - [Place a call](https://www.getrevox.com/docs/api/calls/place-a-call.md): `POST /call` - [Get call by ID](https://www.getrevox.com/docs/api/calls/get-call-by-id.md): `GET /call/{id}` - [Search calls](https://www.getrevox.com/docs/api/calls/search-calls.md): `POST /call/search` - [Create an assistant](https://www.getrevox.com/docs/api/assistants/create-an-assistant.md): `POST /assistants` - [Get assistant by ID](https://www.getrevox.com/docs/api/assistants/get-assistant-by-id.md): `GET /assistants/{id}` - [Get assistants](https://www.getrevox.com/docs/api/assistants/get-assistants.md): `GET /assistants` - [Update an assistant](https://www.getrevox.com/docs/api/assistants/update-an-assistant.md): `PATCH /assistants/{id}` - [Clone an assistant](https://www.getrevox.com/docs/api/assistants/clone-an-assistant.md): `POST /assistants/{id}/clone` - [Create a campaign](https://www.getrevox.com/docs/api/campaigns/create-a-campaign.md): `POST /campaigns` - [Get campaign by ID](https://www.getrevox.com/docs/api/campaigns/get-campaign-by-id.md): `GET /campaigns/{id}` - [List campaigns](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md): `GET /campaigns` - [Update a campaign](https://www.getrevox.com/docs/api/campaigns/update-a-campaign.md): `PATCH /campaigns/{id}` - [Add contacts to a campaign](https://www.getrevox.com/docs/api/campaigns/add-contacts-to-a-campaign.md): `POST /campaigns/{id}/rows` - [Get campaign rows](https://www.getrevox.com/docs/api/campaigns/get-campaign-rows.md): `GET /campaigns/{id}/rows` - [Get phone numbers](https://www.getrevox.com/docs/api/phone-numbers/get-phone-numbers.md): `GET /phone-numbers` - [Update a phone number](https://www.getrevox.com/docs/api/phone-numbers/update-a-phone-number.md): `PATCH /phone-numbers/{id}` --- ## The CallRetryConfigInput object When and how often a call is dialed: the calling windows and allowed days, the delay between two attempts and the maximum number of attempts. Omitted in a request: the default of each field. ```json { "calling_windows": [ { "calling_window_start_time": "09:00", "calling_window_end_time": "18:00", "retry_delay_seconds": 7200 } ], "max_retry_attempts": 1, "allowed_days": [ "monday", "tuesday", "wednesday", "thursday", "friday" ], "excluded_dates": ["2026-11-05"], "call_twice_in_a_row": false } ``` ### Fields - `calling_windows` (array of object, required): Daily time windows in which calls may be placed, on the allowed_days. A call due outside every window waits for the next one to open. Request bodies need at least one window. - `calling_windows.calling_window_start_time` (string, required): Start time of the calling window, in `timezone` (each callee's own timezone when it is null). Format: 'HH:mm' (24-hour) or 'h:mma' (12-hour, minutes required). Examples: '09:00', '10:00am'. Default: '10:00'. - `calling_windows.calling_window_end_time` (string, required): End time of the calling window, in `timezone` (each callee's own timezone when it is null). Must be after the start time: a window cannot span midnight. Format: 'HH:mm' (24-hour) or 'h:mma' (12-hour, minutes required). Examples: '17:00', '6:00pm'. Default: '18:00'. - `calling_windows.retry_delay_seconds` (integer, optional, default 7200): Delay between retry attempts in seconds. Values below the 15-minute minimum are raised to it: a shorter delay means calling someone again minutes after they declined. For one deliberate immediate second dial, use call_twice_in_a_row. Default: 7200 (2 hours). ≥ 0. - `max_retry_attempts` (integer, optional, default 5): Maximum number of call attempts, first call included. Default: 5. Capped by the organization's plan: 5 on Starter, 8 on Business. A contact nobody picks up is billed once all its attempts were placed. > 0. - `allowed_days` (array of enum (7 values), optional, default ["monday","tuesday","wednesday","thursday","friday"]): Days of the week when calls are allowed, in the same timezone as the calling windows. Default: Monday through Friday. Values: `"monday"`, `"tuesday"`, `"wednesday"`, `"thursday"`, `"friday"`, `"saturday"`, `"sunday"`. - `excluded_dates` (array of string (date), optional): Calendar dates on which no call goes out, such as public holidays or days the office is closed, as 'YYYY-MM-DD' (e.g. ['2026-12-25', '2027-01-01']). Read in the same timezone as the calling windows: each callee's local date when timezone is null. A call or retry that would land on an excluded date waits for the next open window after it. Up to 366 dates; duplicates are removed and the list is sorted. A call placed with skip_calling_window ignores them for its first dial only. Default: none. At most 366 items. - `call_twice_in_a_row` (boolean, optional, default false): Double call. If true and max_retry_attempts >= 2, when the first attempt reaches nobody (no answer, declined, voicemail, call screening nobody took), the second attempt is dialed within seconds instead of after retry_delay_seconds, from the same caller number. Two calls in a row from one number raise the pickup rate. Each call is an attempt: the double call counts as 2 when both calls happen, 1 when the first is picked up. Busy or unreachable phones are retried after the normal delay. Calling days and hours still apply. Only the first attempt is doubled; later ones follow retry_delay_seconds. A voicemail_message is left on the second dial only. Default: false. - `timezone` (string | null, optional, deprecated): Deprecated: use the `timezone` field of the assistant, the campaign or [`POST /call`](https://www.getrevox.com/docs/api/calls/place-a-call.md). Still accepted on writes and copied there, and returned with that value. Null no longer means each callee's own timezone: a call's timezone is never derived from its phone number. --- ## The CallRetryConfigOverride object Retry settings for this call only, over the assistant's call_retry_config (or the campaign's, when the call names a campaign). Precedence, lowest to highest: assistant, campaign, this object, then the top-level timezone and call_twice_in_a_row fields. Use it for a public holiday or a one-off batch instead of pausing a campaign. ```json { "max_retry_attempts": 1, "excluded_dates": ["2026-11-05"] } ``` ### Fields - `max_retry_attempts` (integer, may be absent): Maximum number of call attempts for this call, first call included (1 = a single call, no retry), in place of the assistant's or campaign's max_retry_attempts. Still capped by the organization's plan: 5 on Starter, 8 on Business. Omitted: the assistant's or campaign's value. > 0. - `excluded_dates` (array of string (date), may be absent): Calendar dates on which this call must not be placed, such as public holidays, as 'YYYY-MM-DD' (e.g. ['2026-12-25']). Added to the assistant's or campaign's own excluded_dates, never replacing them. Read in the call's timezone (the timezone field, else the assistant's, else the callee's from their number). A first dial or retry that would land on one of these dates waits for the next open window after it. Up to 366 dates. At most 366 items. --- ## The Campaign object A list of contacts called by one assistant, with its calling windows, retries and concurrency cap, and where its contacts stand. ```json { "id": "9b2d7e41-6c3f-4a8e-b5d0-2f7a1c9e4b63", "organization_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "name": "November reminders", "assistant_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "assistant": { "id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "prompt": "You are Julie from Acme. You call {{first_name}} to confirm tomorrow's appointment.", "post_call_prompt": "Send the appointment address by SMS if asked.", "first_sentence": "Hello {{first_name}}, this is Julie from Acme.", "first_sentence_mode": "generated", "end_of_call_sentence": "Thank you, have a good day.", "voice": { "provider": "cartesia", "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6", "speed": 1, "volume": 1, "model": "sonic-3" }, "voice_languages": [ { "language": "en", "voice": { "provider": "cartesia", "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6", "speed": 1, "volume": 1, "model": "sonic-3" } } ], "cartesia_dictionary_pronunciation_id": "6f9a3c1e-2b7d-4e58-9a10-3d2c4b5e6f70", "llm_model": { "type": "recommended" }, "webhook_url": "https://example.com/revox-webhook", "max_call_duration_secs": 600, "max_duration_end_message": "Thank you, have a good day.", "structured_output_config": [ { "name": "budget", "type": "string", "description": "Books a slot in the agenda.", "required": false, "enum_options": ["enum option"] } ], "structured_output_prompt": "Send the appointment address by SMS if asked.", "call_retry_config": { "calling_windows": [ { "calling_window_start_time": "09:00", "calling_window_end_time": "18:00", "retry_delay_seconds": 7200 } ], "max_retry_attempts": 1, "allowed_days": [ "monday", "tuesday", "wednesday", "thursday", "friday" ], "excluded_dates": ["2026-11-05"], "call_twice_in_a_row": false }, "timezone": "Europe/Paris", "background_sound": "audio/office.ogg", "background_sound_volume": 1, "thinking_sound": "city-ambience.ogg", "thinking_sound_volume": 1, "thinking_sound_probability": 0, "transfer_destinations": [ { "label": "Main line", "phone_number": "+33612345678" } ], "human_transfer_mode": "warm", "warm_transfer_summary_instructions": "Send the appointment address by SMS if asked.", "warm_transfer_voice_speed": 1, "ivr_navigation_enabled": true, "voicemail_message": "Thank you, have a good day.", "stt_context": { "general": [{ "key": "crm_id", "value": "lead_8812" }], "terms": ["term"] }, "stt_model": "stt-rt-v4", "first_sentence_delay_ms": 400, "calendars": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "assistant_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "handle": "google_calendar_jane_at_example.com", "provider": "google-calendar", "status": "ready", "connection": { "provider": "google-calendar", "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "settings": { "calendar_id": "primary", "time_zone": "Europe/Paris", "duration_minutes": 30, "days": [1, 2, 3, 4, 5], "start_time": "09:00", "end_time": "18:00", "google_meet": false, "location": "{{site_address}}" } }, "account_label": "Main line", "connected_via_invite": false, "invite": { "url": "https://example.com", "status": "completed", "created_at": "2026-11-05T09:00:00Z", "expires_at": "2026-11-05T09:00:00Z" }, "created_at": "2026-11-05T09:00:00Z" } ], "calendly": null, "cal": null, "google_calendar": null, "hubspot": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "precall_lookup_enabled": true, "meeting_links": [ { "slug": "jane-martin", "label": "Main line", "duration_ms": 1800000, "is_fallback": false, "booking_url": "https://example.com" } ], "post_call_sync": { "enabled": true, "field_mapping": [ { "source": "email", "hubspot_property": "email" } ] } }, "slack": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "channels": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "name": "Appointment reminder" } ] }, "teams": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "channels": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "name": "Appointment reminder", "team_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "team_name": "Sales" } ] }, "zoho": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "module": "Leads", "log_call_activity": false, "field_mapping": [ { "source": "email", "zoho_field": "Email" } ], "template": "{{outcome}}: {{summary}}\n{{call_url}}" }, "custom_tools": [ { "name": "appointment_reminder", "description": "Books a slot in the agenda.", "method": "GET", "url": "https://example.com", "headers": [{ "key": "crm_id", "value": "lead_8812" }], "query_params": [ { "key": "crm_id", "value": "lead_8812" } ], "body_template": "{\"email\": \"{{email}}\", \"name\": \"{{first_name}}\"}", "input_schema": [ { "name": "budget", "type": "string", "description": "Books a slot in the agenda.", "required": false, "enum_options": ["enum option"] } ] } ], "from_phone_number": "+33187654321", "demo_page_url": "https://example.com", "precall_lookup_url": "https://example.com", "precall_lookup_headers": [ { "key": "crm_id", "value": "lead_8812" } ], "organization_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "name": "Appointment reminders", "is_inbound_receptionist": false, "created_by": { "id": "5a7c9e1b-3d5f-4a2c-8e6b-0f1a2b3c4d5e", "email": "jane@example.com", "first_name": "Marie", "last_name": "Martin" }, "created_at": "2026-11-05T09:00:00Z", "updated_at": "2026-11-05T09:02:41Z" }, "from_phone_number": "+33187654321", "max_concurrent_calls": 1, "call_retry_config": { "calling_windows": [ { "calling_window_start_time": "09:00", "calling_window_end_time": "18:00", "retry_delay_seconds": 7200 } ], "max_retry_attempts": 1, "allowed_days": [ "monday", "tuesday", "wednesday", "thursday", "friday" ], "excluded_dates": ["2026-11-05"], "call_twice_in_a_row": false }, "timezone": "Europe/Paris", "status": "completed", "is_cancelled": false, "row_stats": { "not_launched": 1, "skipped": 1, "pending": 1, "calling": 1, "retry": 1, "completed": 1, "failed": 1, "total": 3 }, "metadata_keys": ["metadata key"], "funnel_stats": { "total_leads": 1, "hot": 1, "talked_to_human": 1 }, "created_by": { "id": "6f9a3c1e-2b7d-4e58-9a10-3d2c4b5e6f70", "email": "jane@example.com", "first_name": "Marie", "last_name": "Martin" }, "created_at": "2026-11-05T09:00:00Z", "updated_at": "2026-11-05T09:02:41Z" } ``` ### Fields - `id` (string): Unique ID of the campaign (UUID). Example: `"9b2d7e41-6c3f-4a8e-b5d0-2f7a1c9e4b63"`. - `organization_id` (string): ID of the organization that owns the campaign. - `name` (string): Name of the campaign, unique within the organization. Example: `"November reminders"`. - `assistant_id` (string): ID of the assistant that places the campaign's calls. Set at creation, cannot be changed. - `assistant` ([Assistant](https://www.getrevox.com/docs/api/objects/assistant.md), may be absent): The assistant that places the campaign's calls, when it still exists. - `from_phone_number` (string | null, may be absent): Phone number the campaign's calls are placed from, in E.164 format. Null: the assistant's from_phone_number, or else the organization's default number. - `max_concurrent_calls` (number | null, may be absent): Maximum number of the campaign's calls in progress at the same time. Null: no campaign cap, only your organization's limit applies. - `call_retry_config` ([CallRetryConfig](https://www.getrevox.com/docs/api/objects/call-retry-config.md) | null, may be absent): Retry configuration of the campaign's calls (calling windows, allowed days, delay between attempts, max attempts). Null: the default configuration. - `timezone` (string | null, may be absent): IANA timezone of this campaign's calls. Null: its assistant's timezone, followed live. - `status` ("running" | "paused" | "completed"): Where the campaign stands. A cancelled campaign is flagged by is_cancelled, not by its status. - `"running"`: Active: its launched calls are placed. A campaign is running from its creation on, before any call is launched too. - `"paused"`: No new call is placed until the campaign is resumed ([`POST /campaigns/{id}/resume`](https://www.getrevox.com/docs/api/campaigns/resume-a-paused-campaign.md)). - `"completed"`: Every contact is done. Launching calls again sets it back to running. - `is_cancelled` (boolean): True when the campaign was cancelled: its pending calls were aborted. Launching calls again clears it. - `row_stats` (object, may be absent): Contacts of the campaign counted by dialing state. Each contact counts in one state only, by priority completed > calling > retry > pending > not_launched / failed / skipped. - `row_stats.not_launched` (number): Contacts whose call was never launched (see [`POST /campaigns/{id}/launch-calls`](https://www.getrevox.com/docs/api/campaigns/launch-a-campaigns-calls.md)). - `row_stats.skipped` (number): Contacts whose call was deleted. Normally 0: undialable contacts are never added to a campaign. - `row_stats.pending` (number): Contacts launched but not dialed yet: waiting for their turn, or for their first scheduled attempt. - `row_stats.calling` (number): Contacts being called right now, or whose call is being analysed after hang-up. - `row_stats.retry` (number): Contacts already called at least once and waiting for their next attempt. - `row_stats.completed` (number): Contacts whose call is completed or cancelled. - `row_stats.failed` (number): Contacts whose call ended in an error. - `row_stats.total` (number): All contacts in the campaign. - `metadata_keys` (array of string, may be absent): Every metadata key found on the campaign's calls, sorted. Not returned by the list endpoint [`GET /campaigns`](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md). - `funnel_stats` (object, may be absent): Sales funnel of the campaign, counted in contacts. - `funnel_stats.total_leads` (number): All contacts in the campaign (same as row_stats.total). - `funnel_stats.hot` (number): Contacts with a call whose outcome is 'interested' or 'requested_callback_later'. - `funnel_stats.talked_to_human` (number): Contacts with a call whose outcome is 'completed'. - `created_by` ([OrgMember](https://www.getrevox.com/docs/api/objects/org-member.md) | null, may be absent): The user who created the campaign. Null for campaigns created before this was tracked, and when that user was deleted. - `created_at` (string (date-time)): When the campaign was created (ISO 8601). - `updated_at` (string (date-time)): When the campaign was last modified (ISO 8601). ### Returned by - [Create a campaign](https://www.getrevox.com/docs/api/campaigns/create-a-campaign.md): `POST /campaigns` - [Get campaign by ID](https://www.getrevox.com/docs/api/campaigns/get-campaign-by-id.md): `GET /campaigns/{id}` - [List campaigns](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md): `GET /campaigns` - [Update a campaign](https://www.getrevox.com/docs/api/campaigns/update-a-campaign.md): `PATCH /campaigns/{id}` - [Add contacts to a campaign](https://www.getrevox.com/docs/api/campaigns/add-contacts-to-a-campaign.md): `POST /campaigns/{id}/rows` --- ## The OrgMember object A member of the current organization. ```json { "id": "6f9a3c1e-2b7d-4e58-9a10-3d2c4b5e6f70", "email": "jane@example.com", "first_name": "Marie", "last_name": "Martin" } ``` ### Fields - `id` (string): User ID of the team member, the value of a call's assignee.id. - `email` (string): The user's email address. - `first_name` (string | null): The user's first name. Null when not set on their account. - `last_name` (string | null): The user's last name. Null when not set on their account. ### Returned by - [Create a campaign](https://www.getrevox.com/docs/api/campaigns/create-a-campaign.md): `POST /campaigns` - [Get campaign by ID](https://www.getrevox.com/docs/api/campaigns/get-campaign-by-id.md): `GET /campaigns/{id}` - [List campaigns](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md): `GET /campaigns` - [Update a campaign](https://www.getrevox.com/docs/api/campaigns/update-a-campaign.md): `PATCH /campaigns/{id}` - [Add contacts to a campaign](https://www.getrevox.com/docs/api/campaigns/add-contacts-to-a-campaign.md): `POST /campaigns/{id}/rows` - [Get phone numbers](https://www.getrevox.com/docs/api/phone-numbers/get-phone-numbers.md): `GET /phone-numbers` - [Update a phone number](https://www.getrevox.com/docs/api/phone-numbers/update-a-phone-number.md): `PATCH /phone-numbers/{id}` --- ## The PhoneNumber object A phone number of your organization: a caller ID for outbound calls and, for an owned number, a line whose inbound calls an assistant can answer. ```json { "id": "6f9a3c1e-2b7d-4e58-9a10-3d2c4b5e6f70", "phone_number": "+33199001234", "label": "Main line", "provider": "twilio", "inbound_assistant": { "id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "prompt": "You are Julie from Acme. You call {{first_name}} to confirm tomorrow's appointment.", "post_call_prompt": "Send the appointment address by SMS if asked.", "first_sentence": "Hello {{first_name}}, this is Julie from Acme.", "first_sentence_mode": "generated", "end_of_call_sentence": "Thank you, have a good day.", "voice": { "provider": "cartesia", "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6", "speed": 1, "volume": 1, "model": "sonic-3" }, "voice_languages": [ { "language": "en", "voice": { "provider": "cartesia", "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6", "speed": 1, "volume": 1, "model": "sonic-3" } } ], "cartesia_dictionary_pronunciation_id": "6f9a3c1e-2b7d-4e58-9a10-3d2c4b5e6f70", "llm_model": { "type": "recommended" }, "webhook_url": "https://example.com/revox-webhook", "max_call_duration_secs": 600, "max_duration_end_message": "Thank you, have a good day.", "structured_output_config": [ { "name": "budget", "type": "string", "description": "Books a slot in the agenda.", "required": false, "enum_options": ["enum option"] } ], "structured_output_prompt": "Send the appointment address by SMS if asked.", "call_retry_config": { "calling_windows": [ { "calling_window_start_time": "09:00", "calling_window_end_time": "18:00", "retry_delay_seconds": 7200 } ], "max_retry_attempts": 1, "allowed_days": [ "monday", "tuesday", "wednesday", "thursday", "friday" ], "excluded_dates": ["2026-11-05"], "call_twice_in_a_row": false }, "timezone": "Europe/Paris", "background_sound": "audio/office.ogg", "background_sound_volume": 1, "thinking_sound": "city-ambience.ogg", "thinking_sound_volume": 1, "thinking_sound_probability": 0, "transfer_destinations": [ { "label": "Main line", "phone_number": "+33612345678" } ], "human_transfer_mode": "warm", "warm_transfer_summary_instructions": "Send the appointment address by SMS if asked.", "warm_transfer_voice_speed": 1, "ivr_navigation_enabled": true, "voicemail_message": "Thank you, have a good day.", "stt_context": { "general": [{ "key": "crm_id", "value": "lead_8812" }], "terms": ["term"] }, "stt_model": "stt-rt-v4", "first_sentence_delay_ms": 400, "calendars": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "assistant_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "handle": "google_calendar_jane_at_example.com", "provider": "google-calendar", "status": "ready", "connection": { "provider": "google-calendar", "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "settings": { "calendar_id": "primary", "time_zone": "Europe/Paris", "duration_minutes": 30, "days": [1, 2, 3, 4, 5], "start_time": "09:00", "end_time": "18:00", "google_meet": false, "location": "{{site_address}}" } }, "account_label": "Main line", "connected_via_invite": false, "invite": { "url": "https://example.com", "status": "completed", "created_at": "2026-11-05T09:00:00Z", "expires_at": "2026-11-05T09:00:00Z" }, "created_at": "2026-11-05T09:00:00Z" } ], "calendly": null, "cal": null, "google_calendar": null, "hubspot": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "precall_lookup_enabled": true, "meeting_links": [ { "slug": "jane-martin", "label": "Main line", "duration_ms": 1800000, "is_fallback": false, "booking_url": "https://example.com" } ], "post_call_sync": { "enabled": true, "field_mapping": [ { "source": "email", "hubspot_property": "email" } ] } }, "slack": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "channels": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "name": "Appointment reminder" } ] }, "teams": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "channels": [ { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "name": "Appointment reminder", "team_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "team_name": "Sales" } ] }, "zoho": { "connection_id": "9b8a7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d", "module": "Leads", "log_call_activity": false, "field_mapping": [ { "source": "email", "zoho_field": "Email" } ], "template": "{{outcome}}: {{summary}}\n{{call_url}}" }, "custom_tools": [ { "name": "appointment_reminder", "description": "Books a slot in the agenda.", "method": "GET", "url": "https://example.com", "headers": [{ "key": "crm_id", "value": "lead_8812" }], "query_params": [ { "key": "crm_id", "value": "lead_8812" } ], "body_template": "{\"email\": \"{{email}}\", \"name\": \"{{first_name}}\"}", "input_schema": [ { "name": "budget", "type": "string", "description": "Books a slot in the agenda.", "required": false, "enum_options": ["enum option"] } ] } ], "from_phone_number": "+33187654321", "demo_page_url": "https://example.com", "precall_lookup_url": "https://example.com", "precall_lookup_headers": [ { "key": "crm_id", "value": "lead_8812" } ], "organization_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "name": "Appointment reminders", "is_inbound_receptionist": false, "created_by": { "id": "5a7c9e1b-3d5f-4a2c-8e6b-0f1a2b3c4d5e", "email": "jane@example.com", "first_name": "Marie", "last_name": "Martin" }, "created_at": "2026-11-05T09:00:00Z", "updated_at": "2026-11-05T09:02:41Z" }, "source": "user_imported", "type": "owned_number", "created_at": "2026-11-05T09:00:00Z", "inbound_sip_uri": "sip:4k2m9x7q1z.sip.livekit.cloud", "created_by": { "id": "6f9a3c1e-2b7d-4e58-9a10-3d2c4b5e6f70", "email": "jane@example.com", "first_name": "Marie", "last_name": "Martin" }, "health_status": "healthy", "spam_score": 1, "health_checked_at": "2026-11-05T09:00:00Z" } ``` ### Fields - `id` (string): Unique ID of the phone number record (UUID): the {id} of PATCH and [`DELETE /phone-numbers/{id}`](https://www.getrevox.com/docs/api/phone-numbers/delete-a-phone-number.md). - `phone_number` (string): The phone number, in E.164 format. Example: `"+33199001234"`. - `label` (string | null): Free-text name you gave the number (e.g. 'Paris office'). Null when unset. - `provider` ("twilio" | "telnyx" | "sip"): Carrier the number is connected through. - `"twilio"`: Connected through Twilio. - `"telnyx"`: Connected through Telnyx. - `"sip"`: Brought over your own SIP trunk. - `inbound_assistant` ([Assistant](https://www.getrevox.com/docs/api/objects/assistant.md) | null): The assistant that answers inbound calls to this number. Null when inbound calls are not routed to an assistant. - `source` (enum (3 values)): How the number came in. - `"user_imported"`: You connected a number you own. - `"revox_provisioned"`: Bought automatically by Revox with your subscription or a top-up. Deleting it also releases it. - `"revox_purchased"`: Bought from the dashboard. Deleting it also releases it. - `type` ("owned_number" | "verified_caller_id"): What the number can be used for. - `"owned_number"`: A number Revox can place and receive calls on. - `"verified_caller_id"`: An outside number verified with Twilio, only shown as the caller ID of outbound calls. It cannot receive calls. - `created_at` (string (date-time)): When the number was added (ISO 8601). - `inbound_sip_uri` (string | null): For a 'sip' number: the SIP URI to configure on your carrier or PBX so inbound calls reach Revox. Null for other providers. - `created_by` ([OrgMember](https://www.getrevox.com/docs/api/objects/org-member.md) | null): The user who added the number. Null for numbers provisioned by Revox and for numbers added before this was tracked. - `health_status` ("unknown" | "healthy" | "warning" | "burned"): Spam reputation from the last check. A number is never taken out of service for its reputation. - `"unknown"`: Never checked, or the check gave no usable signal. Not a sign the number is clean. - `"healthy"`: Clean everywhere the check looks. - `"warning"`: Early signs of a spam flag: worth watching, still used. - `"burned"`: Flagged as spam: used last in the outbound rotation. - `spam_score` (number | null): Spam score from 0 to 100 at the last check, higher meaning more likely flagged as spam. Null when no check reported one. - `health_checked_at` (string (date-time) | null): When the reputation was last checked (ISO 8601). Null when never checked. ### Returned by - [Get phone numbers](https://www.getrevox.com/docs/api/phone-numbers/get-phone-numbers.md): `GET /phone-numbers` - [Update a phone number](https://www.getrevox.com/docs/api/phone-numbers/update-a-phone-number.md): `PATCH /phone-numbers/{id}` --- ## The StructuredOutputField object One value to extract from a call (an entry of an assistant's structured_output_config), or one parameter of a custom tool (an entry of its input_schema). ```json { "name": "budget", "type": "string", "description": "Books a slot in the agenda.", "required": false, "enum_options": ["enum option"] } ``` ### Fields - `name` (string): Name of the value (e.g. 'email', 'budget'). In an assistant's structured_output_config, its key in the call attempt's structured_output; in a custom tool's input_schema, the name of the parameter passed to the tool. At least 1 character. Example: `"budget"`. - `type` (enum (6 values)): Type of the extracted value. - `"string"`: Free text. - `"number"`: A JSON number. - `"boolean"`: true or false. - `"enum"`: One of enum_options. With fewer than 2 options, extracted as free text. - `"date"`: A date, as an ISO 8601 string (YYYY-MM-DD). - `"datetime"`: A date and time, as an ISO 8601 string. - `description` (string, may be absent): What the value is, in plain words, for the LLM that fills it in (e.g. 'The budget the prospect mentions, in euros'). - `required` (boolean, default false): When false (the default), the value may be null or missing when the conversation did not provide it. - `enum_options` (array of string, may be absent): The allowed values when type is 'enum'. With fewer than 2 options the field is extracted as a free string. ### Returned by - [Place a call](https://www.getrevox.com/docs/api/calls/place-a-call.md): `POST /call` - [Get call by ID](https://www.getrevox.com/docs/api/calls/get-call-by-id.md): `GET /call/{id}` - [Search calls](https://www.getrevox.com/docs/api/calls/search-calls.md): `POST /call/search` - [Create an assistant](https://www.getrevox.com/docs/api/assistants/create-an-assistant.md): `POST /assistants` - [Get assistant by ID](https://www.getrevox.com/docs/api/assistants/get-assistant-by-id.md): `GET /assistants/{id}` - [Get assistants](https://www.getrevox.com/docs/api/assistants/get-assistants.md): `GET /assistants` - [Update an assistant](https://www.getrevox.com/docs/api/assistants/update-an-assistant.md): `PATCH /assistants/{id}` - [Clone an assistant](https://www.getrevox.com/docs/api/assistants/clone-an-assistant.md): `POST /assistants/{id}/clone` - [Create a campaign](https://www.getrevox.com/docs/api/campaigns/create-a-campaign.md): `POST /campaigns` - [Get campaign by ID](https://www.getrevox.com/docs/api/campaigns/get-campaign-by-id.md): `GET /campaigns/{id}` - [List campaigns](https://www.getrevox.com/docs/api/campaigns/list-campaigns.md): `GET /campaigns` - [Update a campaign](https://www.getrevox.com/docs/api/campaigns/update-a-campaign.md): `PATCH /campaigns/{id}` - [Add contacts to a campaign](https://www.getrevox.com/docs/api/campaigns/add-contacts-to-a-campaign.md): `POST /campaigns/{id}/rows` - [Get campaign rows](https://www.getrevox.com/docs/api/campaigns/get-campaign-rows.md): `GET /campaigns/{id}/rows` - [Get phone numbers](https://www.getrevox.com/docs/api/phone-numbers/get-phone-numbers.md): `GET /phone-numbers` - [Update a phone number](https://www.getrevox.com/docs/api/phone-numbers/update-a-phone-number.md): `PATCH /phone-numbers/{id}` --- ## The StructuredOutputFieldInput object One value to extract from a call (an entry of an assistant's structured_output_config), or one parameter of a custom tool (an entry of its input_schema). ```json { "name": "budget", "type": "string", "description": "Books a slot in the agenda.", "required": false, "enum_options": ["enum option"] } ``` ### Fields - `name` (string, required): Name of the value (e.g. 'email', 'budget'). In an assistant's structured_output_config, its key in the call attempt's structured_output; in a custom tool's input_schema, the name of the parameter passed to the tool. At least 1 character. Example: `"budget"`. - `type` (enum (6 values), required): Type of the extracted value. - `"string"`: Free text. - `"number"`: A JSON number. - `"boolean"`: true or false. - `"enum"`: One of enum_options. With fewer than 2 options, extracted as free text. - `"date"`: A date, as an ISO 8601 string (YYYY-MM-DD). - `"datetime"`: A date and time, as an ISO 8601 string. - `description` (string, optional): What the value is, in plain words, for the LLM that fills it in (e.g. 'The budget the prospect mentions, in euros'). - `required` (boolean, optional, default false): When false (the default), the value may be null or missing when the conversation did not provide it. - `enum_options` (array of string, optional): The allowed values when type is 'enum'. With fewer than 2 options the field is extracted as a free string. --- ## The Usage object ```json { "period": { "from": "from", "to": "to", "granularity": "hour", "timezone": "Europe/Paris" }, "previous_period": { "from": "from", "to": "to" }, "totals": { "credits_used": 1, "amount_cents": 1, "calls": 1, "connected_calls": 1, "talk_seconds": 98, "credits_by_kind": { "reached": 1, "not_reached": 1, "inbound": 1, "per_minute": 1 }, "credits_added": 1 }, "previous_totals": { "credits_used": 1, "amount_cents": 1, "calls": 1, "connected_calls": 1, "talk_seconds": 98, "credits_by_kind": { "reached": 1, "not_reached": 1, "inbound": 1, "per_minute": 1 }, "credits_added": 1 }, "series": [ { "credits_used": 1, "amount_cents": 1, "calls": 1, "connected_calls": 1, "talk_seconds": 98, "credits_by_kind": { "reached": 1, "not_reached": 1, "inbound": 1, "per_minute": 1 }, "start": "start" } ], "by_assistant": [ { "assistant_id": "3f6c2a1e-8b4d-4c7a-9e2f-5d1b7a9c0e34", "name": "Appointment reminder", "credits_used": 1, "amount_cents": 1, "calls": 1, "connected_calls": 1, "talk_seconds": 98 } ], "by_campaign": [ { "campaign_id": "9b2d7e41-6c3f-4a8e-b5d0-2f7a1c9e4b63", "name": "Appointment reminder", "credits_used": 1, "amount_cents": 1, "calls": 1, "connected_calls": 1, "talk_seconds": 98 } ], "balance": { "credits": 1, "plan": "starter", "plan_monthly_credits": 1, "next_expiry": { "credits": 1, "expires_at": "2026-11-05T09:00:00Z" }, "daily_average_credits": 1, "depletion_date": "2026-11-02" } } ``` ### Fields - `period` (object) - `period.from` (string): Start of the period, ISO 8601. - `period.to` (string): End of the period (excluded), ISO 8601. - `period.granularity` ("hour" | "day" | "week" | "month"): The size of each point. - `period.timezone` (string): The timezone the points are cut in. - `previous_period` (object): The period of the same length just before, to compare against. - `previous_period.from` (string): ISO 8601. - `previous_period.to` (string): ISO 8601, the start of `period`. - `totals` (object): Totals over the period. - `totals.credits_used` (number): Credits charged (1 credit = 1 worked contact = €0.50 excl. VAT). A contact's credit is dated by its last call. Fractional only for per-minute charges from before flat pricing. - `totals.amount_cents` (integer): What those credits cost, in euro cents excluding VAT. - `totals.calls` (integer): Phone calls placed or answered: every dial counts, retries included. Browser test calls are free and not counted. - `totals.connected_calls` (integer): Calls answered by someone: a person or a phone menu on an outbound call, or any inbound call. A voicemail does not count. - `totals.talk_seconds` (integer): Time on the line, from pickup to hang-up, summed over every answered call (voicemails included). - `totals.credits_by_kind` (object): Credits used, split by what they paid for. - `totals.credits_by_kind.reached` (number): An outbound contact someone picked up (a person or a phone menu), or who called back. - `totals.credits_by_kind.not_reached` (number): An outbound contact billed without anyone picking up: every attempt it was allowed went unanswered or reached a voicemail. - `totals.credits_by_kind.inbound` (number): An inbound call your assistant answered. - `totals.credits_by_kind.per_minute` (number): A charge by the minute, under the pricing in place before flat per-contact credits. - `totals.credits_added` (integer): Credits added to the balance over the period: plan invoices, top-ups and admin grants. - `previous_totals` (object): Totals over the previous period. - `previous_totals.credits_used` (number): Credits charged (1 credit = 1 worked contact = €0.50 excl. VAT). A contact's credit is dated by its last call. Fractional only for per-minute charges from before flat pricing. - `previous_totals.amount_cents` (integer): What those credits cost, in euro cents excluding VAT. - `previous_totals.calls` (integer): Phone calls placed or answered: every dial counts, retries included. Browser test calls are free and not counted. - `previous_totals.connected_calls` (integer): Calls answered by someone: a person or a phone menu on an outbound call, or any inbound call. A voicemail does not count. - `previous_totals.talk_seconds` (integer): Time on the line, from pickup to hang-up, summed over every answered call (voicemails included). - `previous_totals.credits_by_kind` (object): Credits used, split by what they paid for. - `previous_totals.credits_by_kind.reached` (number): An outbound contact someone picked up (a person or a phone menu), or who called back. - `previous_totals.credits_by_kind.not_reached` (number): An outbound contact billed without anyone picking up: every attempt it was allowed went unanswered or reached a voicemail. - `previous_totals.credits_by_kind.inbound` (number): An inbound call your assistant answered. - `previous_totals.credits_by_kind.per_minute` (number): A charge by the minute, under the pricing in place before flat per-contact credits. - `previous_totals.credits_added` (integer): Credits added to the balance over the period: plan invoices, top-ups and admin grants. - `series` (array of object): The period point by point, oldest first, empty points included. - `series.credits_used` (number): Credits charged (1 credit = 1 worked contact = €0.50 excl. VAT). A contact's credit is dated by its last call. Fractional only for per-minute charges from before flat pricing. - `series.amount_cents` (integer): What those credits cost, in euro cents excluding VAT. - `series.calls` (integer): Phone calls placed or answered: every dial counts, retries included. Browser test calls are free and not counted. - `series.connected_calls` (integer): Calls answered by someone: a person or a phone menu on an outbound call, or any inbound call. A voicemail does not count. - `series.talk_seconds` (integer): Time on the line, from pickup to hang-up, summed over every answered call (voicemails included). - `series.credits_by_kind` (object): Credits used, split by what they paid for. - `series.credits_by_kind.reached` (number): An outbound contact someone picked up (a person or a phone menu), or who called back. - `series.credits_by_kind.not_reached` (number): An outbound contact billed without anyone picking up: every attempt it was allowed went unanswered or reached a voicemail. - `series.credits_by_kind.inbound` (number): An inbound call your assistant answered. - `series.credits_by_kind.per_minute` (number): A charge by the minute, under the pricing in place before flat per-contact credits. - `series.start` (string): Start of the point, ISO 8601 in UTC. Points are cut on the local calendar of `timezone`: a day point starts at local midnight. - `by_assistant` (array of object): The period per assistant, most credits first. - `by_assistant.assistant_id` (string | null): The assistant. Null for calls whose assistant was deleted. - `by_assistant.name` (string | null): The assistant's name. - `by_assistant.credits_used` (number): Credits charged (1 credit = 1 worked contact = €0.50 excl. VAT). A contact's credit is dated by its last call. Fractional only for per-minute charges from before flat pricing. - `by_assistant.amount_cents` (integer): What those credits cost, in euro cents excluding VAT. - `by_assistant.calls` (integer): Phone calls placed or answered: every dial counts, retries included. Browser test calls are free and not counted. - `by_assistant.connected_calls` (integer): Calls answered by someone: a person or a phone menu on an outbound call, or any inbound call. A voicemail does not count. - `by_assistant.talk_seconds` (integer): Time on the line, from pickup to hang-up, summed over every answered call (voicemails included). - `by_campaign` (array of object): The period per campaign, most credits first. - `by_campaign.campaign_id` (string | null): The campaign. Null for calls made outside any campaign (API, dashboard, inbound) or in a deleted one. - `by_campaign.name` (string | null): The campaign's name. - `by_campaign.credits_used` (number): Credits charged (1 credit = 1 worked contact = €0.50 excl. VAT). A contact's credit is dated by its last call. Fractional only for per-minute charges from before flat pricing. - `by_campaign.amount_cents` (integer): What those credits cost, in euro cents excluding VAT. - `by_campaign.calls` (integer): Phone calls placed or answered: every dial counts, retries included. Browser test calls are free and not counted. - `by_campaign.connected_calls` (integer): Calls answered by someone: a person or a phone menu on an outbound call, or any inbound call. A voicemail does not count. - `by_campaign.talk_seconds` (integer): Time on the line, from pickup to hang-up, summed over every answered call (voicemails included). - `balance` (object): The balance now and how long it lasts at the recent pace. Does not depend on the period. - `balance.credits` (integer): Credits left now, whatever the period asked: each one pays for one contact. - `balance.plan` ("starter" | "business" | null): The organization's subscription plan; null when it has none. - `balance.plan_monthly_credits` (integer | null): Credits the plan adds every month; null without a plan. - `balance.next_expiry` (object | null): The plan credits that expire next if they are not used in time. Null when none are due to expire. - `balance.next_expiry.credits` (integer): Unused plan credits set to expire. - `balance.next_expiry.expires_at` (string): When they expire, ISO 8601. - `balance.daily_average_credits` (number): Credits used per day on average over the last 14 days. - `balance.depletion_date` (string | null): When the balance runs out at that daily average, ISO 8601. Null when nothing was used over the last 14 days. ### Returned by - [Get credit and call usage](https://www.getrevox.com/docs/api/usage/get-credit-and-call-usage.md): `GET /usage` --- ## The User object The current authenticated user. ```json { "id": "b2d4f6a8-1c3e-4a5b-8d7f-9e0a1b2c3d4e", "email": "jane@example.com", "first_name": "Marie", "last_name": "Martin", "organization_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "organization_country": "FR", "created_at": "2026-11-05T09:00:00Z", "updated_at": "2026-11-05T09:02:41Z" } ``` ### Fields - `id` (string): The unique identifier of the user. - `email` (string): The email address of the user. - `first_name` (string | null): The first name of the user. - `last_name` (string | null): The last name of the user. - `organization_id` (string): The ID of the organization the user belongs to. - `organization_country` (string | null, may be absent): ISO 3166-1 alpha-2 country code of the organization (e.g. FR). Used as the default region when normalizing national-format phone numbers. - `created_at` (string (date-time)): The time the user was created. - `updated_at` (string (date-time)): The time the user was last updated. ### Returned by - [Get the current user](https://www.getrevox.com/docs/api/users/get-the-current-user.md): `GET /users/me` --- ## The Voice object A voice an assistant can speak with: a preset voice of its provider, or a voice your organization cloned. ```json { "provider": "cartesia", "id": "4325f426-c4e0-418e-a0e5-97fcdfcdf8e6", "name": "Camille", "description": "Books a slot in the agenda.", "language": "en", "accent": "Parisian", "gender": "female", "isCloned": false, "modelCompat": "universal" } ``` ### Fields - `provider` ("cartesia" | "elevenlabs" | "gradium"): The provider of the voice. - `id` (string): ID of the voice at its provider: voice.id of an assistant. At least 1 character. Example: `"4325f426-c4e0-418e-a0e5-97fcdfcdf8e6"`. - `name` (string): The name of the voice. Example: `"Camille"`. - `description` (string): The description of the voice. - `language` (enum (8 values)): The voice's language, which is the language of the calls made with it. - `"en"`: English - `"fr"`: French - `"es"`: Spanish - `"de"`: German - `"it"`: Italian - `"pt"`: Portuguese - `"ru"`: Russian - `"zh"`: Mandarin Chinese - `accent` (string, may be absent): The accent/dialect of the voice (e.g. 'american', 'british', 'australian', 'quebec'). - `gender` (string, may be absent): The gender of the voice (e.g. 'male', 'female', 'neutral'). - `isCloned` (boolean, may be absent): Whether this is a cloned voice. - `modelCompat` (enum (4 values), may be absent): Cartesia model compatibility. Used to filter the voice list by the selected model. Absent/undefined is treated as 'universal'. Values: `"universal"`, `"sonic-3"`, `"sonic-3.5"`, `"sonic-3.6"`. ### Returned by - [Get voices](https://www.getrevox.com/docs/api/voices/get-voices.md): `GET /voices`