# RelationsAI API > Build AI voice calling into your product: place calls with voice agents, run campaigns, sync contacts and do-not-call lists, and receive signed webhook events. Instructions for AI agents: - Base URL: https://voice-api.relationsai.com/v1. JSON over HTTPS; snake_case fields. - Authenticate with `Authorization: Bearer `. Keys start with `rai_test_` (test mode, simulated, free) or `rai_live_` (live calls, billed). Use test keys while developing and never put keys in browser code. - `Idempotency-Key` is optional. To make a retry of a POST or DELETE safe to repeat, send one (for example a UUID) and reuse it only for the identical retry. - Errors return `{"error": {"code", "message", "details", "request_id", "retry", "doc_url"}}`. Branch on `error.code`; `retry` is "no", "yes" or "after" (wait for Retry-After). - Test mode destination numbers choose the outcome: +12025550100 completed (transcript, recording, analysis), +12025550101 no_answer, +12025550102 busy, +12025550103 failed (network error), +12025550104 answered but nobody spoke (no_response, recording only), +12025550105 completed after a longer conversation, +12025550106 the person hangs up early (completed, short). Any other number completes normally. - The OpenAPI contract is at /openapi.json and /openapi.yaml. Every page is available as Markdown by adding .md to its URL. ## Getting started - [RelationsAI developer documentation](/getting-started/introduction.md): Build AI voice calling into your product: place calls, run campaigns, sync contacts and react to events. - [Platform overview](/getting-started/platform-overview.md): How RelationsAI places AI voice calls and how the API, the console and webhooks fit together. - [Quickstart: your first call](/getting-started/quickstart.md): Create a test key, place a simulated call and read its result in about five minutes, free of charge. - [Authentication](/getting-started/authentication.md): Authenticate every request with a RelationsAI API key sent as a Bearer token. - [API keys](/getting-started/api-keys.md): Create, scope, rotate and revoke RelationsAI API keys in the console. - [Environments](/getting-started/environments.md): Test mode and live mode: what each key can reach and how data stays separate. - [Test mode](/getting-started/test-mode.md): Simulated calls and campaigns for building and testing your integration at no cost. - [Core concepts](/getting-started/core-concepts.md): Workspaces, agents, phone numbers, contacts, calls, campaigns and events. - [API availability](/getting-started/api-availability.md): What API v1 covers today, what stays in the console and what is planned. ## Guides - [Creating and preparing agents](/guides/creating-and-preparing-agents.md): Build and publish an agent in the console, then check from the API that it is ready to call. - [Making an outbound call](/guides/making-an-outbound-call.md): Place a call with an agent, pass variables and metadata, and handle refusals. - [Tracking call progress](/guides/tracking-call-progress.md): Follow a call from queued to settled with webhooks or polling. - [Retrieving recordings and transcripts](/guides/retrieving-recordings-and-transcripts.md): Fetch a call's transcript and recording once the call has settled. - [Working with analysis results](/guides/working-with-analysis-results.md): Read the summary, extracted fields and goal result of a settled call. - [Running campaigns](/guides/running-campaigns.md): Create a campaign, add recipients, start it and follow its results. - [Managing contacts](/guides/managing-contacts.md): Create, update and look up contacts, and use their fields in calls. - [Consent and DNC](/guides/consent-and-dnc.md): How consent, do-not-call lists and calling rules are enforced on every call. - [Receiving webhooks](/guides/receiving-webhooks.md): Register an endpoint and process RelationsAI events reliably. - [Verifying webhook signatures](/guides/verifying-webhook-signatures.md): Check the RelationsAI-Signature header so you only trust events RelationsAI sent. - [Retry and reliability practices](/guides/retry-and-reliability.md): Retry safely: check state before resending, read the retry hint, back off, and optionally add an idempotency key. - [Integrating with CRM systems](/guides/integrating-with-crm-systems.md): Trigger calls from CRM events and write outcomes back with webhooks. - [Common integration patterns](/guides/common-integration-patterns.md): Proven designs for CRM-triggered calls, nightly campaigns and no-code tools. - [Going live](/guides/going-live.md): A checklist for moving your integration from test mode to real calls. ## API fundamentals - [Base URL and versioning](/fundamentals/base-url-and-versioning.md): Where to send requests and how the API evolves without breaking your code. - [Authentication](/fundamentals/authentication.md): The Authorization header, key formats and authentication errors in detail. - [Requests and responses](/fundamentals/requests-and-responses.md): JSON bodies, object shape, request ids and response headers. - [Error handling](/fundamentals/error-handling.md): The error envelope, retry hints and how to branch on error codes. - [Error-code reference](/fundamentals/error-codes.md): Every error code the RelationsAI API can return, with its HTTP status, meaning, fix and retry advice. - [Idempotency](/fundamentals/idempotency.md): The optional Idempotency-Key header makes a retried POST or DELETE safe: the action runs at most once. - [Pagination](/fundamentals/pagination.md): Cursor-based pagination for every list operation. - [Filtering](/fundamentals/filtering.md): Narrow list results by creation time and resource-specific filters. - [Concurrency](/fundamentals/concurrency.md): ETags and If-Match prevent lost updates on campaigns and contacts. - [Rate limits](/fundamentals/rate-limits.md): Per-key and per-workspace limits, the RateLimit headers and how to handle 429. - [Data types](/fundamentals/data-types.md): Formats for ids, timestamps, money, phone numbers and enums. - [Webhooks](/fundamentals/webhooks.md): Delivery guarantees, headers, signature scheme and retry schedule for webhooks. - [Security practices](/fundamentals/security-practices.md): Protect your keys, your webhook endpoint and your customers' data. ## API reference - [API reference: Agents](/api/agents.md): AI voice agents. Agents are created, configured and published in the console; the API reads them and tells you whether one is ready to place calls. Agent editing through the API is planned. - [API reference: Analysis](/api/analysis.md) - [API reference: Calls](/api/calls.md): Place outbound calls and read their status, outcome, transcript, recording and analysis. - [API reference: Campaigns](/api/campaigns.md): Call a list of contacts with one agent, with pause, resume and stop. - [API reference: Contacts](/api/contacts.md): People you call, with consent and custom fields that become call variables. - [API reference: Do-not-call list](/api/do-not-call-list.md): Numbers that must never be called. Checked, in both modes, on every `POST /v1/calls`, when a campaign starts and when it resumes (the resume re-screens). A number added while a campaign is running is not removed from that run: pause and resume the campaign to re-screen it, or stop the campaign. - [Events](/api/events.md): The event types RelationsAI sends to your webhook endpoints, with example payloads. - [API reference: Phone numbers](/api/phone-numbers.md): The workspace's phone numbers and which agents use them. Numbers are added and assigned in the console. - [API reference: Recordings](/api/recordings.md) - [API reference: Transcripts](/api/transcripts.md) - [API reference: Webhook endpoints](/api/webhook-endpoints.md): Receive signed event notifications on your server. - [API reference: Workspace](/api/workspace.md): The workspace and API key a request is authenticated as, and what they can do. ## Error codes - [account_inactive](/errors/account_inactive.md): Workspace account inactive. This workspace cannot place calls because its account is not active. - [agent_not_ready](/errors/agent_not_ready.md): Agent not ready to call. This agent cannot place calls right now. - [api_access_not_enabled](/errors/api_access_not_enabled.md): API access not enabled. API access is not enabled for this workspace. - [api_key_expired](/errors/api_key_expired.md): API key expired. This API key has expired. - [api_key_revoked](/errors/api_key_revoked.md): API key revoked. This API key has been revoked. - [authentication_required](/errors/authentication_required.md): Authentication required. Send your API key as a Bearer token in the Authorization header. - [call_not_accepted](/errors/call_not_accepted.md): Call not accepted. The call could not be placed. Nothing was dialled and nothing was charged. - [calling_capacity_reached](/errors/calling_capacity_reached.md): Calling capacity reached. Too many calls are being started right now. Retry after the number of seconds in the Retry-After header. - [calling_not_configured](/errors/calling_not_configured.md): Calling not set up. Calling is not set up for this workspace yet. - [campaign_budget_reached](/errors/campaign_budget_reached.md): Campaign budget reached. This campaign has reached its budget cap. - [campaign_dnc_override_enabled](/errors/campaign_dnc_override_enabled.md): Campaign calls numbers on the do-not-call list. This campaign is set in the console to also call contacts on the do-not-call list, so it cannot be started or resumed through the API. - [campaign_has_no_recipients](/errors/campaign_has_no_recipients.md): Campaign has no recipients. This campaign has no recipients to call. - [campaign_not_resumable](/errors/campaign_not_resumable.md): Campaign cannot be resumed. This campaign cannot be resumed. Start it again to begin a new run. - [campaign_operation_in_progress](/errors/campaign_operation_in_progress.md): Another start or resume is in progress. This campaign is being started or resumed by another request. Retry shortly. - [campaign_outcome_unknown](/errors/campaign_outcome_unknown.md): Campaign start or resume not confirmed. The request was sent but its outcome is not confirmed yet. Check the campaign before trying again. - [campaign_pause_not_confirmed](/errors/campaign_pause_not_confirmed.md): Pause not confirmed. The pause was requested but not confirmed. The campaign may still be dialling. - [campaign_recipients_blocked](/errors/campaign_recipients_blocked.md): Recipients now blocked by compliance. Some recipients of this campaign are now blocked by compliance rules, so it was not resumed. - [campaign_recipients_suppressed](/errors/campaign_recipients_suppressed.md): Every recipient is suppressed. Every recipient of this campaign is blocked by your compliance settings. Nothing was dialled. - [campaign_recipients_unavailable](/errors/campaign_recipients_unavailable.md): Recipients could not be checked. The campaign's recipients could not be read for screening right now, so nothing was dialled. - [campaign_state_conflict](/errors/campaign_state_conflict.md): Campaign is in the wrong state. This action is not allowed in the campaign's current status. - [campaign_too_large](/errors/campaign_too_large.md): Campaign too large. This campaign has too many recipients to start in one run. - [consent_required](/errors/consent_required.md): Consent required. This contact has no recorded consent, and consent is required for calls in this workspace. - [contact_already_exists](/errors/contact_already_exists.md): Contact already exists. A contact with this phone number already exists. - [contact_daily_limit_reached](/errors/contact_daily_limit_reached.md): Daily call limit for this number reached. This number has already been called the maximum number of times allowed in 24 hours. - [contact_limit_reached](/errors/contact_limit_reached.md): Contact limit reached. No more contacts can be created right now. - [contact_on_dnc_list](/errors/contact_on_dnc_list.md): Contact is on the do-not-call list. This contact is on the do-not-call list. Remove its do-not-call entry before deleting it. - [custom_field_not_found](/errors/custom_field_not_found.md): Custom field not found. This custom field does not exist in the workspace. - [daily_call_limit_reached](/errors/daily_call_limit_reached.md): Daily call limit reached. This workspace has reached its daily limit of calls placed through the API. - [dnc_listed](/errors/dnc_listed.md): Number on the do-not-call list. This number is on your do-not-call list, so the call was not placed. - [idempotency_key_in_progress](/errors/idempotency_key_in_progress.md): Request with this Idempotency-Key in progress. A request with this Idempotency-Key is still being processed. - [idempotency_key_reused](/errors/idempotency_key_reused.md): Idempotency-Key reused. This Idempotency-Key was already used with a different request. - [idempotency_outcome_unknown](/errors/idempotency_outcome_unknown.md): Outcome of the earlier request unknown. An earlier request with this Idempotency-Key did not finish, and its outcome is unknown. - [insufficient_balance](/errors/insufficient_balance.md): Insufficient balance. The workspace balance is too low to start this call. Top up to continue. - [insufficient_permissions](/errors/insufficient_permissions.md): Key creator lacks permission. The member who created this API key no longer has permission for this operation. - [insufficient_scope](/errors/insufficient_scope.md): Insufficient scope. This API key does not have the scope this operation requires. - [internal_error](/errors/internal_error.md): Internal error. Something went wrong on our side. - [invalid_api_key](/errors/invalid_api_key.md): Invalid API key. The API key is not valid. - [invalid_cursor](/errors/invalid_cursor.md): Invalid pagination cursor. The pagination cursor is invalid or does not match these filters. - [invalid_idempotency_key](/errors/invalid_idempotency_key.md): Invalid Idempotency-Key. The Idempotency-Key header must be 1 to 255 printable ASCII characters with no spaces. - [invalid_json](/errors/invalid_json.md): Invalid JSON body. The request body is not valid JSON. - [invalid_phone_number](/errors/invalid_phone_number.md): Invalid phone number. The phone number is not a valid E.164 number. - [ip_not_allowed](/errors/ip_not_allowed.md): IP address not allowed. Requests from this IP address are not allowed for this workspace. - [legacy_api_key_not_supported](/errors/legacy_api_key_not_supported.md): Legacy API key not supported. Legacy API keys cannot be used with the v1 API. Create a scoped key in the console. - [live_key_not_allowed_in_browser](/errors/live_key_not_allowed_in_browser.md): Live key used from a browser. Live API keys cannot be used from a browser. Use a test key, or call the API from your server. - [media_link_expired](/errors/media_link_expired.md): Recording link expired. This recording link has expired. Retrieve the recording again for a new link. - [method_not_allowed](/errors/method_not_allowed.md): Method not allowed. This route does not support that HTTP method. - [outside_calling_hours](/errors/outside_calling_hours.md): Outside calling hours. This is outside the permitted calling window for this workspace. Nothing was dialled. - [payload_too_large](/errors/payload_too_large.md): Payload too large. The request body is too large. - [phone_number_not_usable](/errors/phone_number_not_usable.md): Phone number cannot be used for this call. This phone number cannot place outbound calls for this agent. - [phone_number_required](/errors/phone_number_required.md): Caller number must be chosen. This agent has more than one outbound number. Choose one with phone_number_id. - [precondition_required](/errors/precondition_required.md): If-Match required. This update needs an If-Match header with the ETag of the version you read. - [rate_limited](/errors/rate_limited.md): Rate limit exceeded. Too many requests. Retry after the number of seconds in the Retry-After header. - [recipient_contacts_not_found](/errors/recipient_contacts_not_found.md): Contacts not found. Some contact ids do not name contacts in this workspace. - [resource_not_found](/errors/resource_not_found.md): Resource not found. No such resource. - [route_not_found](/errors/route_not_found.md): Route not found. No such route. - [service_unavailable](/errors/service_unavailable.md): Service temporarily unavailable. The service is temporarily unavailable. Retry after the number of seconds in the Retry-After header. - [spend_limit_reached](/errors/spend_limit_reached.md): Monthly spend limit reached. This workspace has reached the monthly spend limit set by its admin. - [telephony_disconnected](/errors/telephony_disconnected.md): Telephony connection down. The telephony connection for this workspace is not working, so the campaign was paused. - [unsupported_media_type](/errors/unsupported_media_type.md): Unsupported media type. Request bodies must be sent as application/json. - [validation_error](/errors/validation_error.md): Validation failed. One or more fields are invalid. - [version_conflict](/errors/version_conflict.md): Version conflict. The resource changed since you read it. - [webhook_delivery_not_retryable](/errors/webhook_delivery_not_retryable.md): Delivery cannot be retried. This delivery cannot be retried in its current status. - [webhook_endpoint_disabled](/errors/webhook_endpoint_disabled.md): Webhook endpoint disabled. This webhook endpoint is disabled. - [webhook_endpoint_limit_reached](/errors/webhook_endpoint_limit_reached.md): Webhook endpoint limit reached. This workspace already has the maximum number of webhook endpoints for this mode. - [webhook_url_not_allowed](/errors/webhook_url_not_allowed.md): Webhook URL not allowed. This URL cannot receive webhooks. - [webhooks_not_enabled](/errors/webhooks_not_enabled.md): Webhooks not enabled. Webhook delivery is not available yet. ## Resources - [Changelog](/resources/changelog.md): Changes to the RelationsAI API and these docs. - [Troubleshooting](/resources/troubleshooting.md): Diagnose common integration problems step by step. - [FAQs](/resources/faq.md): Answers to common questions about the RelationsAI API. - [Status and service availability](/resources/status.md): How to tell whether the API is available and what to do during an incident. - [Security and data handling](/resources/security-and-data-handling.md): How RelationsAI protects API access and the call data you work with. - [Support](/resources/support.md): How to contact RelationsAI support about the API. ## Machine-readable contract - [OpenAPI 3.1 (JSON)](/openapi.json) - [OpenAPI 3.1 (YAML)](/openapi.yaml)