Skip to main content
Outbound calls let your agents proactively reach out to contacts — for appointment reminders, sales follow-ups, lead qualification, notifications, and more. This guide walks through placing a single call via the API, handling the response, and monitoring call progress.
Need to call hundreds or thousands of contacts? Use Batch Calls instead. This guide focuses on one-off, programmatically triggered calls.

Prerequisites

Before placing an outbound call, verify that:
  1. You have an active agent — the agent must be published, not in draft. You can confirm this in the dashboard under Agents, or by checking status: "active" on the agent object.
  2. A phone number is assigned to the agent — outbound calls are placed from a Truedy number that belongs to your account and is linked to the agent. If no number is assigned, the call will fail immediately with a no_phone_number_configured error.
  3. You have a valid API key — all API requests require Authorization: Bearer YOUR_API_KEY in the request headers.
You can assign a phone number to an agent from the dashboard under Settings → Phone Numbers, or programmatically via the phone numbers API.

Placing a Call

Send a POST request to /calls with the agent and destination phone number.

Endpoint

POST https://api.truedy.ai/api/public/v1/calls

Request Body

FieldTypeRequiredDescription
agent_idstringYesThe ID of the agent that will handle the call
phone_numberstringYesThe destination phone number in E.164 format (e.g. +14155551234)
variablesobjectNoKey-value pairs for template substitution in the agent’s prompt
from_numberstringNoOverride the caller ID (must be a number assigned to the agent). If omitted, Truedy picks from the agent’s assigned outbound numbers automatically
call_settingsobjectNoPer-call overrides for recording, greeting, and timeouts (see below)
call_settings fields (all optional):
FieldTypeDescription
recording_enabledbooleanWhether to record this call. Default: true
transcription_enabledbooleanWhether to transcribe this call. Default: true
greetingstringOverride the agent’s opening line for this call only
max_durationstringMax call duration, e.g. "1800s". Overrides agent default
join_timeoutstringTimeout for callee to answer, e.g. "30s". Overrides agent default

About variables

Your agent’s prompt can include template placeholders using double curly braces: {{first_name}}, {{appointment_date}}, etc. When you pass a variables object with the call, Truedy substitutes those values into the prompt before the conversation starts. This lets a single agent handle personalised calls at scale without creating separate agents per contact. For example, a prompt containing:
You are calling {{first_name}} to confirm their appointment on {{appointment_date}} at {{appointment_time}}.
…would be rendered with the values you pass in variables.

Examples

curl -X POST https://api.truedy.ai/api/public/v1/calls \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "agent_01hx2a7b3cd4ef5gh6ij7kl8mn",
    "phone_number": "+14155551234",
    "variables": {
      "first_name": "Sarah",
      "appointment_date": "April 10th",
      "appointment_time": "2:00 PM"
    }
  }'

Response

A successful request returns HTTP 201 Created with the newly created call object:
{
  "id": "call_01hx3k9p2qw7v8n4m6j5r0y1tz",
  "status": "queued",
  "direction": "outbound",
  "agent_id": "agent_01hx2a7b3cd4ef5gh6ij7kl8mn",
  "phone_number": "+14155551234",
  "from_number": "+18005559876",
  "duration_seconds": null,
  "transcript": null,
  "recording_url": null,
  "variables": {
    "first_name": "Sarah",
    "appointment_date": "April 10th",
    "appointment_time": "2:00 PM"
  },
  "created_at": "2024-04-05T14:21:58Z",
  "started_at": null,
  "ended_at": null
}
The id field is the call identifier you will use to poll for status or match against webhook events.

Monitoring Call Progress

Once you have the call ID, you can track the call to completion using polling or webhooks.

Option 1: Polling

Call GET /calls/{id} repeatedly until the status reaches a terminal state (ended, failed, or cancelled).
import requests
import time

CALL_ID = "call_01hx3k9p2qw7v8n4m6j5r0y1tz"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}
TERMINAL_STATUSES = {"ended", "failed", "cancelled"}

while True:
    response = requests.get(
        f"https://api.truedy.ai/api/public/v1/calls/{CALL_ID}",
        headers=HEADERS,
    )
    call = response.json()

    print(f"Status: {call['status']}")

    if call["status"] in TERMINAL_STATUSES:
        break

    time.sleep(5)  # wait 5 seconds before checking again

print(f"Call finished with status: {call['status']}")
if call["status"] == "ended":
    print(f"Duration: {call['duration_seconds']}s")
    print(f"Outcome: {call['outcome']}")
Polling is simple but inefficient. Avoid polling intervals shorter than 5 seconds, and prefer webhooks for any integration processing more than a few dozen calls per day.
Register a webhook endpoint and Truedy will deliver a call.ended event to your server automatically when the call finishes — no polling required. See Webhooks Overview to set up your endpoint. The call.ended event payload includes the full call object, including transcript and recording URL.

Phone Number Format

The phone_number field must use E.164 format:
  • Starts with +
  • Followed by the country code and subscriber number, no spaces or dashes
  • Examples: +14155551234 (US), +447911123456 (UK), +61291234567 (AU)
Passing a phone number in any other format (e.g. (415) 555-1234, 415-555-1234, or 14155551234 without the leading +) will result in a 422 Unprocessable Entity error.

Common Errors

HTTP StatusError CodeMeaningResolution
404 Not Foundagent_not_foundNo agent exists with the given agent_idVerify the agent ID in your dashboard
422 Unprocessable Entityno_phone_number_configuredThe agent has no outbound number assignedAssign a phone number to the agent in Settings → Phone Numbers
422 Unprocessable Entityinvalid_phone_numberphone_number is not valid E.164 formatReformat the number (e.g. +14155551234)
422 Unprocessable Entityagent_not_activeThe agent is in draft or paused statePublish the agent before placing calls
429 Too Many Requestsrate_limitedYou’ve exceeded the API rate limitImplement exponential backoff and retry
402 Payment Requiredinsufficient_creditsYour account balance is too lowTop up credits or check your billing plan

Next Steps

Calls Overview

Understand call statuses, directions, and lifecycle

Batch Calls & Campaigns

Call many contacts at once with campaigns

Webhooks Overview

Receive real-time events instead of polling

Call Management

List, filter, and retrieve call records