Making Your First Call
The simplest way to make a call is with a task:
curl -X POST https://api.topcalls.ai/v1/calls \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+14155551234",
"from_number": "+18005551234",
"task": "You are calling to confirm John's dental appointment tomorrow at 3 PM. Be friendly and professional.",
"voice": "alloy"
}'
Simple vs Advanced Configuration
Simple Mode (Task)
Perfect for straightforward calls:
{
"phone_number": "+14155551234",
"task": "Call to confirm appointment...",
"voice": "alloy"
}
Advanced Mode (Instructions)
For complex conversations with full control:
{
"phone_number": "+14155551234",
"instructions": "You are Sarah, a senior scheduler...",
"first_sentence": "Hi, this is Sarah from TopView Dental...",
"voice": "alloy",
"temperature": 0.7,
"max_duration": 10
}
Required Parameters
| Parameter | Type | Description |
|---|
phone_number | string | Destination number (E.164 format: +14155551234) |
task OR instructions | string | What the AI should do (one is required) |
Optional Parameters
Voice & Model
{
"voice": "alloy", // Realtime: alloy, echo, shimmer, etc.
"model": "gpt-realtime-mini-2025-12-15",
"mode": "realtime" // or "legacy"
}
Model Selection
TopCalls supports multiple models for different use cases:
- Realtime Mode: Uses speech-to-speech models optimized for ultra-low latency (~200-500ms)
- Legacy Mode: Supports multiple LLM models including GPT-4o, GPT-5, and Gemini models with varying latency and capabilities
Model Availability: Check the current list of available models via the API endpoint GET /v1/models. Model availability may change over time.GPT-5 reasoning models have the latest knowledge and are automatically optimized for voice conversations with concise responses. They use max_completion_tokens instead of max_tokens.Temperature support: Some models support custom temperature values, while others use optimized defaults. Check model details via the API.For fastest voice calls, we recommend non-reasoning models which typically have lower latency.
Call Control
{
"from_number": "+18005551234", // Caller ID
"max_duration": 10, // Minutes (1-60)
"first_sentence": "Hi, this is Sarah...", // Opening line
"background_audio": "office", // Background ambiance: "office" or "none"
"background_audio_gain": "medium" // Volume: "low", "medium", or "high"
}
Context & Knowledge
{
"knowledge_base_ids": ["kb_xyz789"], // Attach knowledge bases
"request_data": {
"patient_name": "John Smith",
"appointment_date": "2025-12-24"
}
}
Function Calling
{
"tools": [
{
"name": "check_availability",
"description": "Check if a time slot is available",
"parameters": {
"date": { "type": "string" },
"time": { "type": "string" }
}
}
]
}
Webhooks
{
"webhook_url": "https://your-app.com/webhooks/call-complete",
"webhook_events": ["call.completed", "call.failed"]
}
Complete Example: Appointment Reminder
{
"phone_number": "+14155551234",
"from_number": "+18005551234",
"instructions": "You are Sarah, a friendly appointment coordinator at TopView Dental. Your goal is to confirm {{patient_name}}'s appointment on {{appointment_date}} at {{appointment_time}}. Be warm, professional, and concise.",
"first_sentence": "Hi {{patient_name}}, this is Sarah from TopView Dental. I'm calling to confirm your appointment tomorrow at {{appointment_time}}.",
"voice": "alloy",
"mode": "realtime",
"temperature": 0.7,
"max_duration": 5,
"request_data": {
"patient_name": "John Smith",
"appointment_date": "2025-12-24",
"appointment_time": "3:00 PM"
},
"webhook_url": "https://your-app.com/webhooks/call-complete"
}
Response
{
"call_id": "564d4fd4-03bc-400a-abe0-05540fbeff88",
"provider_call_id": "64e9bf0e-7c2f-4443-a759-7eb1731cd583",
"status": "queued"
}
Checking Call Status
Use the call_id to check status:
curl https://api.topcalls.ai/v1/calls/564d4fd4-03bc-400a-abe0-05540fbeff88 \
-H "Authorization: Bearer YOUR_API_KEY"
Call Statuses
| Status | Description |
|---|
queued | Call created, waiting to be dispatched |
in_progress | Call is active |
completed | Call finished successfully |
failed | Call failed (busy, no answer, error) |
cancelled | Call was cancelled |
Call Ending Behavior
By default, the AI agent can end calls gracefully when the conversation is complete. This happens automatically when:
- The user says goodbye or thanks you
- All questions have been answered
- The user explicitly asks to end the call
- The conversation naturally concludes
The AI will speak a contextual farewell message before hanging up (e.g., “Thanks for calling! Your appointment is confirmed. Have a great day!”).
You can influence this behavior in your instructions: “Always confirm the next steps before ending the call” or “Ask if there’s anything else before saying goodbye.”
Common Patterns
Pattern 1: Simple Reminder
{
"phone_number": "+14155551234",
"task": "Remind the user about their appointment tomorrow at 3 PM. Be brief and friendly.",
"voice": "alloy"
}
Pattern 2: Sales Call with Function Calling
{
"phone_number": "+14155551234",
"instructions": "You are Alex, a sales rep. Qualify the lead and book a demo if interested.",
"tools": [
{
"name": "book_demo",
"description": "Book a demo call",
"parameters": {
"email": { "type": "string" },
"preferred_time": { "type": "string" }
}
}
]
}
Pattern 3: Multi-Language Support
{
"phone_number": "+14155551234",
"instructions": "Habla solo en español. Eres un asistente de servicio al cliente...",
"mode": "legacy",
"stt_language": "es-ES",
"voice": "aura-2-thalia-es",
"tts_provider": "deepgram"
}
Error Handling
Invalid Phone Number
{
"status": 400,
"title": "Invalid request body",
"errors": [
{
"path": "phone_number",
"message": "Phone number must be in E.164 format (e.g., +14155551234)"
}
]
}
Insufficient Quota
{
"status": 402,
"title": "Insufficient Quota",
"detail": "You need 5 minutes but have 3.5 remaining"
}
Best Practices
✅ Do This
- Validate phone numbers: Ensure E.164 format (
+14155551234)
- Set first_sentence: Control how the call starts
- Use request_data: Personalize with variables
- Configure webhooks: Get notified when calls complete
- Test first: Try with your own number before production
❌ Don’t Do This
- Invalid formats: Always use E.164 format
- Missing instructions: Provide clear task or instructions
- Too long: Keep instructions focused (200-500 words)
- Ignore errors: Handle API errors gracefully
Next Steps