phone-arrow-up-rightCalls

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.

circle-info

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

Field
Type
Description

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.

circle-exclamation

Optional Fields

Field
Type
Description

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)

Field
Type
Description

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:

  1. Validation — The platform verifies the patient entity exists, resolves the caller ID, and queues the call with Twilio.

  2. 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.

  3. 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.

  4. Conversation — The call proceeds exactly like an inbound call. The agent has full access to tools, clinical context, and the conversation state machine.

  5. 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 ringingin-progresscompleted (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.

You provide
The agent gets

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

Pass 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

Pass 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 reason and goal you provided

  • What external systems are involved - your tags and metadata

  • Where it fits in a sequence - derived_from_call_sid if 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

Status
When
What to do

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:

  1. API gateway - per API key, shared with all other Platform API endpoints

  2. 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

Symptom
Cause
Fix

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?