Calls
Trigger outbound voice calls with patient lineage, goal context, and end-to-end traceability in the world model.
The outbound call endpoint lets you place a voice call from a workspace phone number to a patient. Every call is linked to a patient entity and a reason, so the platform tracks who requested the call, why, and what happened - from the moment you make the API request through to the call outcome.
You only need an API key. No triggers, campaigns, or scheduling infrastructure required.
When to use this vs triggers. This endpoint is for on-demand calls - a CRM event fires, a care coordinator clicks a button, or your backend decides a patient needs a callback right now. For recurring or event-driven outreach (appointment reminders every 48 hours, lab result notifications), use Triggers instead - they handle scheduling, retry, and business-hours windows automatically.
Quick Start
curl -X POST https://api.platform.amigo.ai/v1/{workspace_id}/calls/outbound \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone_to": "+18005551234",
"phone_from": "+12125559876",
"patient_entity_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"reason": "lab_results"
}'The response includes a call_sid for tracking and an event_id pointing to the world model event:
{
"call_sid": "CA1234567890abcdef",
"status": "queued",
"phone_from": "+12125559876",
"setup_id": null,
"event_id": "f9e8d7c6-b5a4-3210-fedc-ba0987654321"
}Endpoint
POST /v1/{workspace_id}/calls/outbound
Required Fields
phone_to
string
Destination phone number in E.164 format (e.g. +18005551234). Max 16 characters.
phone_from
string
Caller ID in E.164 format. Must belong to this workspace. Required if use_case_id is not provided.
use_case_id
string (UUID)
Use case identifier - the platform picks the best outbound number automatically. Required if phone_from is not provided.
patient_entity_id
string (UUID)
The patient this call is about. Must be an existing person entity in your workspace.
reason
string
Why the call is being made. 1-256 characters. Examples: appointment_reminder, follow_up, lab_results, billing, care_plan_review.
phone_from and use_case_id are mutually exclusive. Provide exactly one. If you provide phone_from, the platform uses that number directly (it must be registered in your workspace). If you provide use_case_id, the platform selects the optimal outbound number for that use case.
Optional Fields
service_id
string
Which voice agent service to use. Max 64 characters. If omitted, the workspace default is used.
system_prompt
string
Override the agent's system prompt for this call. Max 10,000 characters.
goal
string
What the call should accomplish. This is injected into the agent's context so it knows the objective before the patient answers. Max 2,000 characters.
tags
array of strings
Classification tags for filtering and analytics (e.g. ["scheduling", "q2_campaign"]). Max 10 items, each max 64 characters.
metadata
object
Arbitrary key-value pairs for correlating with external systems. Max 20 entries, keys max 64 characters, values max 256 characters.
derived_from_call_sid
string
If this call is a callback from a prior conversation, pass the original call_sid here. Creates an explicit lineage chain between calls. Max 64 characters.
idempotency_key
string
Pass the same key on retries to prevent duplicate calls. Auto-generated if omitted. Max 128 characters.
outbound_task_entity_id
string
Link to an existing outbound task entity for completion feedback. Max 64 characters.
Response (201 Created)
call_sid
string
Unique call identifier. Use this to look up call status and intelligence.
status
string
Initial call status - typically queued.
phone_from
string or null
The resolved caller ID. Always populated; shows the selected number when use_case_id was used.
setup_id
string (UUID) or null
Setup identifier when use_case_id was used.
event_id
string (UUID) or null
The world model event ID for the outbound.initiated event. Use this for lineage queries.
How It Works
When you create an outbound call, the platform handles the full lifecycle automatically:
Validation — The platform verifies the patient entity exists, resolves the caller ID, and queues the call with Twilio.
Pre-warming — While the phone rings (typically 5-15 seconds), the agent loads the patient's full world model context, generates a greeting, and pre-renders the audio. This means zero cold-start delay when the patient answers.
Connection — When the patient picks up, the agent joins the call immediately with the pre-generated greeting. The patient hears the agent speak within ~1 second of answering.
Conversation — The call proceeds exactly like an inbound call. The agent has full access to tools, clinical context, and the conversation state machine.
Completion — Call outcomes, intelligence, and analytics are computed and available via the calls list, call detail, and trace analysis endpoints.
The status field in the response starts as queued and progresses through ringing → in-progress → completed (or failed/no-answer/busy). Use the call detail endpoint with the returned call_sid to check status and retrieve intelligence after the call.
How the Agent Uses Your Context
When you provide a goal, the platform appends it to the agent's system prompt before the call connects. The agent reads it during the pre-warming phase (while the phone is ringing) so it knows the objective by the time the patient answers.
The patient_entity_id also drives context loading. During pre-warming, the agent reads the patient's world model projection - demographics, active conditions, medications, upcoming appointments, and prior interaction history. The agent starts the call with full patient knowledge without needing to "look up" anything.
patient_entity_id
Full patient context from the world model (demographics, clinical, history)
goal
Injected into the system prompt as a call objective
system_prompt
Replaces the default system prompt entirely
system_prompt + goal
Goal is appended to your custom prompt
Neither system_prompt nor goal
Default agent behavior with patient context only
Phone Number Selection
You have two ways to specify the outbound caller ID:
Direct: phone_from
phone_fromPass the exact phone number to call from. The number must be registered in your workspace. Use this when your system already knows which number to use.
Automatic: use_case_id
use_case_idPass a use case identifier and the platform selects the optimal phone number based on the use case configuration (geography, capability, load balancing). The resolved number and setup ID are returned in the response.
Response:
Callback Chains
When a call is a follow-up to a previous conversation, pass derived_from_call_sid with the original call's identifier. This creates an explicit link in the world model so you can trace the full outreach sequence.
The patient's timeline will show both calls and the lineage between them.
External System Correlation
Use tags and metadata to connect calls to records in your other systems. These values are stored in the world model event and available in analytics.
Tags are useful for filtering calls in analytics dashboards. Metadata is useful for joining call outcomes back to your source systems.
Idempotency
To safely retry a request without creating a duplicate call, include an idempotency_key:
If you send the same idempotency_key again within the deduplication window, you get back the original response instead of placing a second call. If you omit the key, the platform generates one automatically (no deduplication across retries).
World Model Lineage
Every outbound call emits an outbound.initiated event on the patient entity's timeline the moment the call is created (before it connects). This event captures:
Who requested the call - the API key identifier (not the secret)
Why - the
reasonandgoalyou providedWhat external systems are involved - your
tagsandmetadataWhere it fits in a sequence -
derived_from_call_sidif this is a callback
The event_id in the response points to this event. You can use it to:
Correlate initiation with downstream call events (connected, completed, failed)
Query the patient's timeline to see all outreach attempts
Build analytics on API-initiated calls vs agent-scheduled calls vs trigger-driven calls
API-initiated calls appear in the same unified timeline as all other patient interactions.
Error Responses
400
Phone number is not valid E.164 format, or both phone_from and use_case_id are provided/missing
Fix the request body. E.164 = + followed by 1-15 digits, first digit 1-9.
404
Patient entity does not exist in this workspace (or is not a person entity), or no phone number is available for the use_case_id
Verify the patient_entity_id exists via GET /v1/{workspace_id}/entities/{id}. For use case 404s, check your phone number provisioning.
403
The phone_from number is not registered in this workspace
Check GET /v1/{workspace_id}/phone-numbers/ for available numbers.
422
Missing required fields (patient_entity_id, reason, or phone source)
Add the missing fields. Both patient_entity_id and reason are required on every request.
429
Rate limit exceeded
Back off and retry. Rate limits apply per API key and per source phone number independently.
502
The voice infrastructure returned an error
Retry with the same idempotency_key. If persistent, check service status.
503
Voice agent or outbound calling is not configured for this workspace
Contact support to enable outbound calling.
504
Phone number selection timed out (when using use_case_id)
Retry. If persistent, try using phone_from directly instead.
Full Example
A CRM webhook fires when a patient's lab results are ready. Your backend calls the outbound API to notify them:
The agent receives the patient's full clinical context (conditions, medications, appointments) plus the goal. When the patient answers, the agent already knows their name, their A1C order, and what to discuss.
Rate Limits
Outbound calls are rate-limited at two levels:
API gateway - per API key, shared with all other Platform API endpoints
Voice infrastructure - per source phone number (10 calls per rate window)
Both limits are enforced independently. If you hit either, you receive a 429 response. Use idempotency_key so you can safely retry after the rate limit resets.
Troubleshooting
Call connects but patient hears silence/hold music
Agent failed to join the conference. Check that the voice agent service is running and the workspace has a valid service configuration.
Verify service_id is correct, or omit it to use the workspace default.
503 Service Unavailable
Outbound calling is not enabled for this workspace, or the voice infrastructure is temporarily unavailable.
Contact support to verify outbound calling is configured.
404 Not Found on patient_entity_id
The entity doesn't exist, isn't in this workspace, or isn't a person entity type.
Check the entity via GET /v1/{workspace_id}/entities/{id}.
403 Forbidden on phone_from
The phone number isn't registered in your workspace.
List available numbers via GET /v1/{workspace_id}/phone-numbers/.
Call rings but goes to voicemail
The patient didn't answer. This is normal behavior — check call status via the call detail endpoint.
Consider retry logic with idempotency_key and derived_from_call_sid.
Agent speaks but has no patient context
patient_entity_id points to an entity with no enrichment data.
Verify the entity has been enriched via connectors or manual data entry.
Last updated
Was this helpful?

