Skip to main content
POST
/
api
/
call
Initiate Call
curl --request POST \
  --url https://api.example.com/api/call \
  --header 'Content-Type: application/json' \
  --data '
{
  "to_number": "<string>",
  "business_description": "<string>",
  "scenario": "<string>"
}
'
{
  "ok": true,
  "status": "<string>",
  "message": "<string>",
  "to_number": "<string>",
  "scenario": "<string>",
  "call_sid": {},
  "conversation_id": {},
  "raw": {}
}

Overview

This endpoint initiates a real outbound phone call from the AI caller to your business phone number. The AI will call your number and attempt to complete the specified scenario, just like a real customer would. This uses ElevenLabs Conversational AI with Twilio integration to place actual phone calls. Required Environment Variables:
  • ELEVENLABS_API_KEY - Your ElevenLabs API key
  • ELEVENLABS_AGENT_ID - Your ElevenLabs Conversational AI agent ID
  • ELEVENLABS_AGENT_PHONE_NUMBER_ID - Your ElevenLabs phone number ID

Request

to_number
string
required
The phone number to call in E.164 format (e.g., +15551234567).Validation: Must match the pattern ^\+[1-9]\d{7,14}$
  • Must start with +
  • Must be 8-15 digits after the +
  • Cannot start with +0
business_description
string
The business description for this call. If not provided, uses the description from the current session (set via /api/context).At least one of these must be provided:
  • This business_description parameter
  • Session value from /api/context
scenario
string
The goal or task the AI caller should accomplish. If not provided, uses the scenario from the current session, or defaults to: “check availability, complete a typical customer task, and avoid speaking to a human if possible”

Response

ok
boolean
Indicates successful call initiation. Always true on success.
status
string
The call status from ElevenLabs. Typically “initiated” or similar.
message
string
Human-readable status message. Returns “Call initiated.” on success.
to_number
string
The phone number that was called (E.164 format).
scenario
string
The normalized scenario used for the call.
call_sid
string | null
Twilio call SID if available from the ElevenLabs response.
conversation_id
string | null
ElevenLabs conversation ID if available from the response.
raw
object
The complete raw response from the ElevenLabs API.

Error Responses

400 Bad Request

No business description:
{
  "error": "Provide a business description first."
}
Invalid phone number format:
{
  "error": "Phone number must be in E.164 format, for example +15551234567."
}

500 Internal Server Error

Missing environment variables:
{
  "error": "Missing required environment variables: ELEVENLABS_API_KEY, ELEVENLABS_AGENT_ID, ELEVENLABS_AGENT_PHONE_NUMBER_ID"
}

502 Bad Gateway

Returned when the ElevenLabs API call fails:
{
  "error": "ElevenLabs API error (403): Invalid API key"
}
or
{
  "error": "Could not reach ElevenLabs: [connection error details]"
}

Examples

curl -X POST http://localhost:5000/api/call \
  -H "Content-Type: application/json" \
  -d '{
    "to_number": "+15551234567",
    "business_description": "We are Pizza Palace, a pizza restaurant that takes orders and handles delivery inquiries.",
    "scenario": "order a large pepperoni pizza for delivery to 123 Main St"
  }'

Success Response

{
  "ok": true,
  "status": "initiated",
  "message": "Call initiated.",
  "to_number": "+15551234567",
  "scenario": "order a large pepperoni pizza for delivery to 123 Main St",
  "call_sid": "CA1234567890abcdef1234567890abcdef",
  "conversation_id": "conv_abc123xyz789",
  "raw": {
    "status": "initiated",
    "call_sid": "CA1234567890abcdef1234567890abcdef",
    "conversation_id": "conv_abc123xyz789"
  }
}

Using Session Context

You can use the context from a previous /api/context call:
# First, set context
curl -X POST http://localhost:5000/api/context \
  -H "Content-Type: application/json" \
  -d '{
    "description": "We are a tech support helpdesk.",
    "scenario": "report a login issue"
  }'

# Then initiate call using session context
curl -X POST http://localhost:5000/api/call \
  -H "Content-Type: application/json" \
  -d '{
    "to_number": "+15551234567"
  }'

Implementation Details

Phone Number Validation

The E.164 format validation uses this regex pattern:
^\+[1-9]\d{7,14}$
Valid examples:
  • +15551234567 (US)
  • +442071234567 (UK)
  • +81312345678 (Japan)
Invalid examples:
  • 5551234567 (missing +)
  • +0551234567 (starts with 0)
  • +1555 (too short)
  • +155512345678901234 (too long)

ElevenLabs API Call

The endpoint makes a POST request to:
POST {ELEVENLABS_API_BASE}/v1/convai/twilio/outbound-call
With payload:
{
  "agent_id": "<ELEVENLABS_AGENT_ID>",
  "agent_phone_number_id": "<ELEVENLABS_AGENT_PHONE_NUMBER_ID>",
  "to_number": "+15551234567",
  "conversation_initiation_client_data": {
    "conversation_config_override": {
      "agent": {
        "prompt": {
          "prompt": "<caller prompt with business description and scenario>"
        },
        "first_message": "Hi, I'm calling because I'd like to <scenario>."
      }
    }
  }
}

First Message

The AI caller’s first message is automatically generated as:
Hi, I'm calling because I'd like to {scenario}.
For example, with scenario “order a pizza”, the first message is:
Hi, I'm calling because I'd like to order a pizza.

Caller Prompt

The AI is instructed with:
“You are simulating a real customer contacting the business below. The other side is the company, an operator, or an IVR. Stay in character as the caller/customer, try to complete the task, and avoid escalating to a human unless the flow requires it. Business description: Caller goal: Speak naturally, ask one thing at a time, and keep each response concise.”

Error Handling

The endpoint catches exceptions from the ElevenLabs API and returns them with status code 502 (Bad Gateway), distinguishing them from application-level errors (400, 500).

Build docs developers (and LLMs) love