Quickstart: your first call
In this quickstart you check an API key, pick an agent, place a call in test mode, follow it until it is final, and read its transcript, recording and analysis: eight requests, about five minutes.
Before you begin
- A RelationsAI workspace with API access. The API is in private preview: a workspace that has not been enabled answers every authenticated request with
api_access_not_enabled. Write to support@relationsai.com to request access. - A workspace owner or admin to create the key (only they can create keys).
- One of:
curl; Node.js 20 or newer (built-infetch); Python 3.9 or newer withrequests(pip install requests). - No agent of your own is needed. Test mode has a built-in Sample agent (
agent_1ZltiWzxrXmMprGD6q63) that is always ready.
Create a test API key
In the RelationsAI platform (voice.relationsai.com), open Settings → API Keys and select Create API key (step by step: Get an API key):
- Name it after what will use it, for example
Quickstart. - Choose the Test environment.
- Keep the default read permissions and also tick Place calls (
calls:write). - Choose an expiry. Test keys may also be set to never expire.
- Select Create API key, copy the key and confirm that you have stored it. The key is shown once.
In the requests on this page, replace
<token>with that key. The ids shown (call_6Vb3Nm8Qw2Er5Ty9Ui4Op7and so on) are examples: use the ids from your own responses. Keep the key in a secret manager, never in source code. See API keys for scopes, expiry and rotation.- Name it after what will use it, for example
Check the key
Retrieve the workspace. It is the quickest way to check that a key works, which mode it is in and which scopes it has, and it never changes anything.
GET/workspaceJSONNext: check that
livemodeisfalse(a test key) and thatapi_key.scopescontainscalls:write.List agents
List the agents your key can use. Test mode lists your workspace's real agents plus the built-in Sample agent, marked
GET"sample": true./agentsJSONNext: use the Sample agent's
id,agent_1ZltiWzxrXmMprGD6q63. It has the same id in every workspace, exists only in test mode, and calls from the sample number+12025550150. Ifhas_moreistrue, see Pagination.Check that the agent is ready
Ask whether the agent can place calls right now. The Sample agent is always ready; one of your own agents reports every problem it has, such as being switched off in the console.
GET/agents/{agent_id}/readinessJSONThis example from the API reference is a live agent; for the Sample agent in test mode,
agent_idisagent_1ZltiWzxrXmMprGD6q63andlivemodeisfalse.Next: continue when
readyistrue. Otherwise each entry inreasonssays what to fix in the console.Place a test call
Send the agent and a destination number. In test mode the destination chooses the simulated result:
POST+12025550100answers and completes a conversation.variablesare values the agent can use in the conversation;metadatais your own data, returned as sent. EachPOST /v1/callsplaces a call: if a request times out, list your calls before sending it again, or send an optionalIdempotency-Keyso that a retry returns the same call (see Idempotency)./callsJSON202means the call passed every check and was accepted; it does not mean anyone answered. Other test numbers simulate other results:Destination Simulated result outcome+12025550100Answered and completed, with transcript, recording and analysis completed+12025550101No answer no_answer+12025550102Busy busy+12025550103Failed: the call could not be connected failed+12025550104Answered by voicemail; nobody spoke no_response+12025550105Completed after a longer conversation completed+12025550106The person hangs up early; short duration completedAny other valid number Completed completedNext: keep the call's
idand read the call until it is settled.Retrieve the call
Read the call. A test call reaches
GETstatus: endedwithin about 20 seconds andsettled: truewithin about 30 seconds;settledmeans everything about the call is final: outcome, duration, artifacts and charge./calls/{call_id}JSONThis example from the API reference is a settled live call; a settled test call looks the same except that
livemodeisfalseandcost.amountis always0.Next: repeat this request every few seconds until
settledistrue. In production, let RelationsAI tell you instead (last step).Read the transcript
Once
GETartifacts.transcript.stateisready, read the conversation turn by turn, verbatim. This needstranscripts:read, which is in the default scopes of a new key./calls/{call_id}/transcriptJSONIn test mode the transcript is a fixture with
"simulated": trueand"livemode": false; this example from the API reference comes from a live call.Next: read the recording.
Get the recording link
Ask for a short-lived link to the audio (about 15 minutes, see
GETexpires_at). This needsrecordings:read./calls/{call_id}/recordingJSONThe link works without an API key, so treat it like a password: use it right away, do not log or store it, and ask for a new one when you need it. It also stops working as soon as the key that obtained it is revoked or expires, loses
recordings:read, or its creator leaves the workspace. In test mode the audio is a short syntheticaudio/wavfile and the recording has"simulated": true.Next: download the audio with a plain
GETofurl(noAuthorizationheader), or go on to the analysis.Read the analysis
Read the summary, the fields the agent extracts (configured in the console) and whether the call met its goal. This needs
GETanalysis:read./calls/{call_id}/analysisJSONIn test mode the analysis is a fixture with
"simulated": true. More in Retrieving recordings and transcripts and Working with analysis results.Next: stop polling and receive events instead.
Get notified instead of polling
Register a webhook endpoint and RelationsAI sends your server a signed
call.endedevent when the call ends andcall.settledwhen everything is final, in test mode too. Webhook delivery is a separate private preview: check thatcapabilities.webhooksistruein the workspace response from step 2 before you build on it. Follow Receiving webhooks, then Verifying webhook signatures.
Run the whole flow
The same flow as one tested program in cURL, JavaScript and Python: it checks the key (and refuses anything but a test key), finds the Sample agent, checks readiness, places a call to +12025550100, polls until the call settles and prints the transcript, the recording state and the analysis.
Complete runnable example
Quickstart: place a simulated call in test mode and read its results.
The same steps as a complete script, with error handling, tested against test mode on every docs build. Each script reads your test key from an environment variable named in its first lines.
- cURL script (bash)
quickstart.sh - JavaScript (Node.js 20+)
quickstart.mjs - Python 3.9+ (requests)
quickstart.py
What can go wrong
authentication_required: NoAuthorizationheader, or not in the formBearer <key>. Check that theAuthorizationheader carries your key in place of<token>.invalid_api_key: The key is mistyped, truncated or not an API key. Copy it again from where you stored it. If it is lost, create a new key: secrets are shown only once.legacy_api_key_not_supported: An oldersk_live_key. Create a scoped key under Settings → API Keys.api_access_not_enabled: The workspace is not in the API preview. Write to support@relationsai.com to request access.insufficient_scopeonPOST /calls: The key has nocalls:write. Create a test key with Place calls ticked.details.required_scopeslists what is missing.live_key_not_allowed_in_browser: A live key was sent from browser code. Use a test key, and call the API from a server.resource_not_found: The id is wrong, from another workspace or from the other mode. The Sample agent exists only in test mode; copy ids from your own responses.agent_not_ready: One of your own agents cannot call yet. Read its readinessreasonsand fix them in the console, or use the Sample agent.dnc_listedorconsent_required: Your test-mode do-not-call list or consent rules refuse the number. Test mode applies these exactly as live mode. Use another test number, or see Consent and do-not-call.rate_limited: Too many requests in a minute. Wait forRetry-Afterseconds. See Rate limits.
Every error has the same shape and a request_id; see Error handling.
Check that it worked
- The call's
settledistrue,outcomeiscompletedand all threeartifactsareready. - Every object you received has
"livemode": false, and the call'scost.amountis0. Nothing was charged. - Test-mode calls are kept apart from live data: they do not appear in the console's call history or to live keys. Read them with your test key.
Next steps
- Authentication and API keys: scopes, expiry, rotation.
- Test mode: every simulated outcome and what is enforced.
- Making an outbound call and Tracking call progress in depth.
- Receiving webhooks instead of polling.
- Going live when you are ready for real calls.