aethexDocs

API Reference

Calls API

Place outbound phone calls, log inbound ones, dispatch batches, and inspect status. Reads use calls:read; anything that triggers a dial (single, batch, or log) uses calls:write.

Base URL
https://api.aethexai.com/api/v1
Endpoints
18
Scopes
calls:readcalls:write
GET/calls

Paginated history of every call recorded for the account.

List Calls

Returns every call on your account, newest first. Filter by status, direction, or both.

Path & Query

4
  • statusstringoptional

    Filter by call status. One of queued, ringing, in-progress, connected, completed, failed, no-answer, busy, or canceled.

  • directionstringoptional

    Filter by direction. One of inbound or outbound.

  • limitintegeroptional

    Maximum number of results to return. Default 50, minimum 1, maximum 1000.

  • offsetintegeroptional

    Number of results to skip from the beginning of the result set. Default 0, minimum 0.

Errors

3
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:read scope.

Use an API key that has calls:read.

422Unprocessable Entity

limit is outside [1, 1000] or offset is negative, or direction is not inbound/outbound.

Clamp limit to [1, 1000], set offset >= 0, and use a valid direction value.

POST/calls

Persist a Call row without dialing anyone.

Create Call Record

Creates a Call record without dialing anyone. Useful for logging calls that came in through another system, or pre-staging metadata before something else does the dial. To actually place an outbound call, use POST /calls/trigger.

Request body

5
  • agent_idstring (uuid)required

    The agent associated with the call. It does not need to be dialable; this endpoint only logs the record.

  • directionstringoptional

    Call direction. One of inbound or outbound. Defaults to outbound when omitted, but always send an explicit value; the default may be removed in a future release.

  • to_numberstring (E.164)optional

    E.164 phone number of the callee, e.g. +14155551234. Validated against ^\+[1-9]\d{1,14}$.

  • from_numberstring (E.164)optional

    E.164 phone number of the caller. Example: +14155559876. Validated against the regex ^\+[1-9]\d{1,14}$. This endpoint only logs the record, so from_number is optional here. POST /calls/trigger and per-recipient entries in POST /calls/batch both reject a missing from_number with 422 from_number_required.

  • metadataobjectoptional

    Arbitrary JSON stored on the call for your own bookkeeping (campaign tags, lead IDs, etc.). Returned verbatim on GET /calls/{id}. Defaults to {'}.

Errors

4
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:write scope.

Use an API key that has calls:write.

404Not Found

No agent exists with that ID.

Check the agent ID with GET /agents, or create the agent first.

422Unprocessable Entity

agent_id is empty, direction is not inbound/outbound, or to_number/from_number is not valid E.164 (^\+[1-9]\d{1,14}$).

Send a non-empty agent_id, a valid direction, and E.164 numbers like +14155551234.

POST/calls/trigger

Persist a Call row and dial the recipient asynchronously (returns 202).

Trigger Outbound Call

Triggers an outbound call. Returns 202 Accepted immediately with the queued Call record; the actual dial runs in the background. Poll GET /calls/{id} for terminal status.The from_number must be a phone number registered to your account with outbound enabled (see Phone Numbers). The provider is resolved from that registration automatically. If the dial cannot start, the Call row is marked failed and metadata.error_message carries the reason.

Request body

5
  • agent_idstring (uuid)required

    The agent that should handle this call.

  • to_numberstring (E.164)required

    Recipient phone number in E.164 format, e.g. +14155551234. Must match ^\+[1-9]\d{1,14}$.

  • from_numberstring (E.164)required

    Caller ID in E.164 format. Example: +14155559876. Validated against the regex ^\+[1-9]\d{1,14}$. Must be a phone number registered to this account with outbound enabled (see Phone Numbers). Required — omitting it returns 422 from_number_required.

  • dynamic_variablesobjectoptional

    Per-call values for {{ variable_name }} placeholders defined on the agent. Values stored on the agent act as defaults; pass keys here to override them per call and to fill any placeholder that has no default. A placeholder with no value does not refuse the call: the model reads [name: not provided] in its place, and the agent's webhook gets agent.prompt_variables.unfilled (at most once a day). Values must be strings, numbers, or booleans. Keys using the reserved system__ prefix are rejected because supported system placeholders are filled by Aethex.

  • metadataobjectoptional

    Arbitrary JSON stored on the call for your own bookkeeping (campaign tags, lead IDs, etc.). Returned verbatim on GET /calls/{id}. Defaults to {'}.

Errors

12
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

402Payment Required

The account is in a hard-blocked billing state (e.g. canceled grace expired, payment failed past dunning window).

Visit the action_url returned in the error payload to update billing, or contact support. The error body includes code and message describing the exact alert.

403Forbidden

API key does not have the calls:write scope.

Use an API key that has calls:write.

403Number suppressed

to_number is on your account's do-not-call list (code: number_suppressed). The response says which source suppressed it: an entry you added, the person's own request, or a STOP they texted one of your numbers. No call was created.

Do not retry: nothing about this number changes the answer. Drop it from the list you dial from. If the entry was added in error and is yours to lift, release it with POST /suppressions/{id}/release — entries recording the person's own request cannot be released.

404Not Found

No agent exists with that ID.

Check the agent ID with GET /agents.

422Missing from_number

No from_number was provided in the request body.

Send a from_number that is registered to your account with outbound enabled.

422Unprocessable Entity (from_number not registered)

The resolved from_number is not registered to this account. Error body: invalid_recipients: [{..., reason: "not_registered"}].

Register the number via POST /api/v1/phone-numbers/{provider}/register first, then retry.

422Unprocessable Entity (outbound disabled)

The resolved from_number is registered but has outbound calling disabled. Error body: invalid_recipients: [{..., reason: "outbound_disabled"}].

Enable outbound on the number via PATCH /api/v1/phone-numbers/{id}.

422Unprocessable Entity (validation)

agent_id empty, to_number missing or not E.164, from_number not E.164, or invalid dynamic_variables.

Send a non-empty agent_id, a to_number matching ^\+[1-9]\d{1,14}$, a valid E.164 from_number, and dynamic_variables as a flat object of scalars.

429Too Many Requests

Your account or the shared capacity pool is at its limit. The response includes a Retry-After header.

Honor the Retry-After header and retry. If you hit this consistently, your plan needs more concurrent-call capacity.

503Service temporarily unavailable

We're at capacity right now.

Retry the request after a short back-off. If it persists, contact our team at [email protected].

503Suppression list unreadable

The do-not-call list could not be read (code: suppression_check_unavailable), so the call was refused rather than placed. Transient, and deliberately not a 403: silence from the list is never permission.

Retry after Retry-After seconds. The same request is safe to send again; no call was created.

POST/calls/batch

Enqueue 1–10,000 outbound calls for an agent in one request.

Batch Outbound Calls

Dispatches up to 10,000 outbound calls for an agent and returns a batch_id. Accepts the compatibility shape (call_name, recipient phone_number, agent_phone_number_id, scheduled_time_unix, telephony_call_config, target_concurrency_limit) and the legacy Aethex shape (name, recipient to_number, per-recipient from_number, start_at). The same lifecycle is also available at the compatibility aliases POST /convai/batch-calling/submit, GET /convai/batch-calling/workspace, GET /convai/batch-calling/{batch_id}, POST /convai/batch-calling/{batch_id}/cancel, POST /convai/batch-calling/{batch_id}/retry, and DELETE /convai/batch-calling/{batch_id}. Poll GET /calls/batch/{batch_id} for detailed recipient status.Scheduling. Pass scheduled_time_unix or start_at to defer dispatch. end_at remains a hard deadline for abandoning recipients that have not started.Status vocabulary. Canonical /calls/batch responses use raw Aethex states: scheduled, queued, running, completed, failed, expired, or cancelled. The /convai/batch-calling/* compatibility aliases map those to pending, in_progress, completed, failed, or cancelled and keep the raw state in legacy_status.Transport support. Phone-number recipients are dialed over Twilio and SIP. With whatsapp_params the batch is called on WhatsApp instead: recipients who already allow calls from the number are rung at once, and everyone else is sent the call-permission template and called the moment they tap Allow. A recipient waiting on that reads awaiting_permission, and the batch stays running until the last one has been called, declined, or let the request lapse (24 hours, or end_at).

Request body

13
  • agent_idstring (uuid)required

    The agent that should handle every call in the batch.

  • recipientsobject[]required

    Array of recipient objects. Minimum 1, maximum 10,000. Each entry may use phone_number (compatibility shape) or to_number (legacy), plus optional id, from_number, variables, and conversation_initiation_client_data.dynamic_variables. On a WhatsApp batch, whatsapp_user_id (the person's WhatsApp number, digits) may stand in for phone_number, and from_number does not apply. If agent_phone_number_id is omitted, every phone recipient must provide a tenant-owned outbound-capable from_number. A recipient may also carry transfer_number: where that call transfers to, overriding the agent's own destination for that call alone. One E.164 number, or an array of up to five tried in order when a leg is not answered. Omit it to keep the agent's own setting. Batch recipients are stored durably, so variables cannot include secret__* keys; use POST /calls/trigger for per-call secret dynamic variables.

  • call_namestringoptional

    Compatibility batch label. name is accepted as a legacy alias.

  • namestringoptional

    Optional human-readable batch label, max 255 characters.

  • descriptionstringoptional

    Optional description, max 2000 characters. Omitting it returns as "" in responses.

  • start_atstring (ISO 8601, timezone-aware)optional

    Defer the first dial until this timestamp. Must include a timezone offset. When in the future the batch starts as scheduled; otherwise the field is ignored and the batch starts as queued.

  • end_atstring (ISO 8601, timezone-aware)optional

    Hard deadline. The dialer abandons any recipients still un-started past this timestamp. Must include a timezone offset, must be in the future, and must be strictly after start_at if both are set.

  • scheduled_time_unixintegeroptional

    Unix timestamp for scheduled dispatch. Accepted as an alias for start_at; if both are supplied they must represent the same instant.

  • agent_phone_number_idstring (uuid)optional

    Tenant phone-number UUID to use as the default sender for recipients that omit from_number.

  • whatsapp_paramsobjectoptional

    Call the batch on WhatsApp. whatsapp_phone_number_id names the connected number (its id or Meta's phone-number id; optional when the workspace has one), and whatsapp_call_permission_request_template_name with whatsapp_call_permission_request_template_language_code name an approved template with a call-permission request and no variables — every recipient receives it as written. Each person may appear once, and a recipient given both phone_number and whatsapp_user_id must be the same person. Needs the whatsapp_messages:write scope and counts against the WhatsApp send budget. agent_phone_number_id and from_number do not apply.

  • telephony_call_configobjectoptional

    Optional telephony settings. ringing_timeout_secs controls how long Twilio or SIP rings before giving up; default is 60 seconds.

  • target_concurrency_limitintegeroptional

    Maximum simultaneous calls for this batch. The worker also remains subject to tenant and cluster admission limits.

  • timezonestringoptional

    Optional IANA timezone label returned with the batch for UI/reporting; scheduling is still driven by absolute timestamps.

Errors

9
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:write scope.

Use an API key that has calls:write.

403Missing scope

A WhatsApp batch sends every recipient a call-permission request, and the key lacks whatsapp_messages:write.

Use a key with whatsapp_messages:write: new keys have it. Rotating keeps a key's scopes, so create a new key rather than rotating an older one.

422Calling unavailable from this number

WhatsApp does not let businesses place calls from numbers registered in the United States, Canada, Egypt, Vietnam or Nigeria.

Run the batch from a number registered in another country.

422Calling is off for this number

Meta has calling switched off for the WhatsApp number, or has not switched it on yet (code: whatsapp_calling_off). The batch is refused before anyone is asked.

Turn calling on with POST /whatsapp-accounts/:account_id/calling, then submit the batch again.

404Not Found

No agent exists with that ID.

Check the agent ID with GET /agents.

422Invalid recipients

One or more recipients have a from_number that is missing, not registered, or has outbound disabled. The error body lists each failing row under invalid_recipients[*] with recipient_index, from_number, and reason (not_registered or outbound_disabled).

Fix every offending row before resubmitting. For not_registered, register the number first; for outbound_disabled, enable outbound on it. Partial batches are not accepted.

422Validation error

recipients is empty or longer than 10,000; any to_number is not E.164; name is over 255 chars; description is over 2000 chars; start_at/end_at lack a timezone; end_at is in the past; or end_at <= start_at.

Stick to the field limits listed above and include a timezone on every datetime.

503Service temporarily unavailable

We're at capacity right now.

Retry the request after a short back-off. If it persists, contact our team at [email protected].

GET/calls/batch

List batch calling jobs for the workspace.

List Batch Calls

Returns batch jobs for the current tenant, ordered newest first. Use last_doc with the returned next_doc value for cursor pagination.

Path & Query

3
  • limitintegeroptional

    Page size, 1 to 1000. Defaults to 100.

  • last_docstringoptional

    Cursor returned as next_doc from the previous page.

  • agent_idstring (uuid)optional

    Filter batch jobs to one agent.

Errors

2
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:read scope.

Use an API key that has calls:read.

GET/calls/batch/:batch_id

Poll the lifecycle of a batch dispatch.

Get Batch Status

Returns the current state of a batch with per-recipient detail. A recipient on the account's do-not-call list comes back skipped and is counted under skipped rather than failed; a skip is a settled outcome, so a batch of nothing but skips is fully resolved. Skipped recipients send no call.ended — there is no call to report. Canonical /calls/batch responses use raw Aethex states; /convai/batch-calling/* aliases map those states to the compatibility vocabulary and keep the raw value in legacy_status.

Path & Query

1
  • batch_idstring (uuid)required

    UUID of the batch returned from POST /calls/batch.

Errors

4
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:read scope.

Use an API key that has calls:read.

404Not Found

No batch with this ID exists.

Confirm the batch_id returned from POST /calls/batch.

422Unprocessable Entity

batch_id is not a valid UUID.

Pass the UUID returned by POST /calls/batch.

POST/calls/batch/:batch_id/cancel

Stop future dispatch for a batch and mark recipients cancelled.

Cancel Batch Calls

Cancels the batch control plane and prevents remaining recipients from being dispatched. Calls already handed to a carrier are not forcibly dropped by this endpoint.

Path & Query

1
  • batch_idstring (uuid)required

    UUID of the batch returned from POST /calls/batch.

Errors

2
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:write scope.

Use an API key that has calls:write.

POST/calls/batch/:batch_id/retry

Retry failed and no-answer recipients.

Retry Batch Calls

Resets failed, busy, no-answer, cancelled-provider, and deferred recipients to pending and enqueues the batch again. Successful recipients are not duplicated. Recipients skipped for the do-not-call list are never resurrected: nothing about those numbers will be different on a later pass.

Path & Query

1
  • batch_idstring (uuid)required

    UUID of the batch returned from POST /calls/batch.

Errors

2
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:write scope.

Use an API key that has calls:write.

DELETE/calls/batch/:batch_id

Delete the batch and recipient records.

Delete Batch Calls

Deletes the batch resource and its recipient attempt records. Conversation and call history remain available through the calls and conversations APIs.

Path & Query

1
  • batch_idstring (uuid)required

    UUID of the batch returned from POST /calls/batch.

Errors

2
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:write scope.

Use an API key that has calls:write.

POST/convai/batch-calling/submit

The same call as `POST /calls/batch`, under the common batch-calling name.

Submit a batch (compatibility alias)

An alias for POST /calls/batch, so a client written against the familiar submit/workspace/cancel/retry names works unchanged. Same body, same implementation, one difference in the response: status is reported as pending, in_progress, completed, failed or cancelled, and the raw internal value moves to legacy_status. See POST /calls/batch above for the full body.

Errors

2
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:write scope.

Use an API key that has calls:write.

GET/convai/batch-calling/workspace

The same list as `GET /calls/batch`, under the workspace name.

List batches (compatibility alias)

An alias for GET /calls/batch. Each row carries the mapped status alongside the raw legacy_status; everything else matches the canonical list.

Errors

2
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:read scope.

Use an API key that has calls:read.

GET/convai/batch-calling/:batch_id

The same record as `GET /calls/batch/{batch_id}`.

Get a batch (compatibility alias)

An alias for GET /calls/batch/{batch_id}, with status mapped to the pending/in_progress vocabulary and the raw value in legacy_status.

Path & Query

1
  • batch_idstring (uuid)required

    UUID of the batch returned from POST /calls/batch.

Errors

2
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:read scope.

Use an API key that has calls:read.

POST/convai/batch-calling/:batch_id/cancel

The same call as `POST /calls/batch/{batch_id}/cancel`.

Cancel a batch (compatibility alias)

An alias for POST /calls/batch/{batch_id}/cancel. Stops dialling the recipients that have not started; calls already in progress run to their end.

Path & Query

1
  • batch_idstring (uuid)required

    UUID of the batch returned from POST /calls/batch.

Errors

2
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:write scope.

Use an API key that has calls:write.

POST/convai/batch-calling/:batch_id/retry

The same call as `POST /calls/batch/{batch_id}/retry`.

Retry a batch (compatibility alias)

An alias for POST /calls/batch/{batch_id}/retry. Re-dials the recipients that failed, leaving the ones that connected alone.

Path & Query

1
  • batch_idstring (uuid)required

    UUID of the batch returned from POST /calls/batch.

Errors

2
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:write scope.

Use an API key that has calls:write.

DELETE/convai/batch-calling/:batch_id

The same call as `DELETE /calls/batch/{batch_id}`.

Delete a batch (compatibility alias)

An alias for DELETE /calls/batch/{batch_id}. Returns 204 with no body.

Path & Query

1
  • batch_idstring (uuid)required

    UUID of the batch returned from POST /calls/batch.

Errors

2
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:write scope.

Use an API key that has calls:write.

GET/calls/:call_id

Fetch a single Call row by ID.

Get Call

Returns the full record for a single call. Failed dials carry a metadata.error_message explaining what went wrong. The provider field reflects how the call was placed: twilio, sip, aethex-sip, webrtc (for in-browser sessions), or websocket (for a call streamed over the WebSocket API).

Path & Query

1
  • call_idstring (uuid)required

    UUID of the call.

Errors

4
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:read scope.

Use an API key that has calls:read.

404Not Found

No call with this ID exists.

Confirm the call_id from POST /calls/trigger or GET /calls.

422Unprocessable Entity

call_id is not a valid UUID.

Pass the call ID from POST /calls/trigger or GET /calls.

GET/calls/:call_id/status

Lightweight telephony-status read for polling.

Get Call Status

A lightweight version of Get Call that returns only the status, provider, and elapsed duration. Use this for tight polling loops where you do not need the full record.

Path & Query

1
  • call_idstring (uuid)required

    UUID of the call.

Errors

4
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:read scope.

Use an API key that has calls:read.

404Not Found

No call with this ID exists.

Confirm the call_id from POST /calls/trigger or GET /calls.

422Unprocessable Entity

call_id is not a valid UUID.

Pass the call ID from POST /calls/trigger or GET /calls.

POST/calls/:call_id/end

Hang up a live call now, on any carrier.

End a Call

Hangs up a live call immediately, even mid-sentence, whichever carrier it is on: Twilio, SIP, Microsoft Teams, WhatsApp, a browser session or a WebSocket call, whose client is told the call ended. status in the response says what happened. ending means the carrier was asked to hang up; the call then reaches its final status through the carrier's usual callback, usually within seconds. If the call had already ended, the response carries its final status (completed, failed, busy, no-answer or canceled), or ended when the carrier reports the call over before that final status is recorded. Only ending means this request ended the call. Safe to repeat.

Path & Query

1
  • call_idstring (uuid)required

    UUID of the call to hang up.

Errors

7
401Unauthorized

Missing or invalid API key.

Send a valid live key in X-API-Key or Authorization: Bearer ....

403Forbidden

API key does not have the calls:write scope.

Use an API key that has calls:write.

404Not Found

No call with this ID exists for your account.

Confirm the call_id from POST /calls/trigger or GET /calls.

409Conflict

The call has no carrier leg or live session to end yet, for example a batch call still waiting to be dialed, or its provider cannot be ended this way.

For a batch call that has not been dialed, cancel its batch instead. Otherwise retry once the call has connected.

422Unprocessable Entity

call_id is not a valid UUID.

Pass the call ID from POST /calls/trigger or GET /calls.

502Bad Gateway

The carrier did not accept the hang-up or could not be reached. The call may still be live.

Retry the request.

503Service Unavailable

The carrier credentials stored for this call cannot be used right now.

Retry later. Contact support if it keeps happening.