Skip to content
View as Markdown

Place an AI call ​

POST /v1/calls

Asks an existing outbound AI agent to call one lead once.

Scope: calls:write

Access: The key's member needs the Manual call permission in the agent's campaign and must be able to see the lead; creating the lead by phone also needs permission to manage that campaign's leads.

The caller owns when to call. The call is placed by the agent you name, in its normal outbound mode with its own first message and prompt, exactly as when the campaign calls a lead; it is not treated as a callback. The agent must be an enabled outbound voice agent in a campaign the key may reach (otherwise 404), and that campaign is the call's campaign.

Name the lead with lead_id (a lead in the agent's campaign) or with phone. With phone, the campaign's lead with that number is called as it is; if there is none, it is created exactly as POST /v1/leads creates it, before the call is checked, so a call that is then refused still leaves the new lead behind. To send more details, create or update the lead first and call it by lead_id.

Every call goes through DialEcho's existing automated-call checks, when you send the request and again right before dialing: a number on the do-not-call list or one that cannot be called is refused with 409, and outside the lead's calling hours the call is accepted as scheduled and starts at scheduled_for without another request from you. Once a call is requested for a lead, the campaign's own automated dialing leaves that lead alone.

Idempotency-Key is required so retries never dial a person twice: DialEcho places at most one call per key. The same request with the same key returns the same call_id with the call's current status, as long as the key's member may still see the lead; otherwise it is 404 not_found, as a new request for that lead would be. Derive the key from what the call is for, for example info-form:<lead_id>, so one event can never cause two calls. Every request, replays included, also draws from the per-key call limit.

Headers ​

NameTypeRequiredDescription
Idempotency-KeystringYesIdentifies this call for your API key. Reusing it with a different body is 409 idempotency_conflict. 16 to 128 printable ASCII characters, no spaces.

Body ​

Content type: application/json

NameTypeRequiredDescription
agent_idUUIDYesAn enabled outbound voice agent.
lead_idUUIDNoA lead in the agent's campaign, for example the lead_id POST /v1/leads returned. Send exactly one of lead_id or phone.
phonestringNoNormalized to E.164 like POST /v1/leads. Send exactly one of lead_id or phone. Up to 40 characters.
first_namestringNoOnly with phone; used only when the lead is created. Up to 100 characters.
last_namestringNoOnly with phone; used only when the lead is created. Up to 100 characters.
emailstringNoOnly with phone; used only when the lead is created. A valid email address, up to 254 characters.

Response ​

Status: 202 Accepted

A new request always answers queued or scheduled. The other statuses are what a replay of the same request reports once the call has moved on. Responses never contain the lead's personal data.

NameTypeDescription
call_idUUIDThe call; the same value on every replay.
lead_idUUIDThe lead being called.
statusstringqueued: starting now (normally within seconds). scheduled: outside calling hours, starts at scheduled_for. dialing: placed. completed: answered. no_answer: not answered, busy or voicemail; not retried. failed: could not be placed (for example the checks before dialing refused it), or DialEcho restarted while starting it and it is never dialed again. canceled: canceled in DialEcho before it was placed. One of queued, scheduled, dialing, completed, no_answer, failed, canceled.
scheduled_fortimestampOnly present when status is scheduled: when the call starts (RFC 3339, UTC).

Example request ​

curl

bash
curl -X POST "https://development.agencydevworks.ai/v1/calls" \
  -H "Authorization: Bearer dei_your_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: info-form:aaaaaaaa-0000-4000-8000-000000000001" \
  -d '{
  "agent_id": "99999999-0000-4000-8000-000000000001",
  "lead_id": "aaaaaaaa-0000-4000-8000-000000000001"
}'

JavaScript

js
const response = await fetch("https://development.agencydevworks.ai/v1/calls", {
  method: "POST",
  headers: {
    "Authorization": "Bearer dei_your_key",
    "Content-Type": "application/json",
    "Idempotency-Key": "info-form:aaaaaaaa-0000-4000-8000-000000000001",
  },
  body: JSON.stringify({
    "agent_id": "99999999-0000-4000-8000-000000000001",
    "lead_id": "aaaaaaaa-0000-4000-8000-000000000001"
  }),
});
const data = await response.json();

Example response ​

Status: 202 Accepted

json
{
  "call_id": "33333333-0000-4000-8000-000000000001",
  "lead_id": "aaaaaaaa-0000-4000-8000-000000000001",
  "status": "scheduled",
  "scheduled_for": "2026-11-02T14:00:00Z"
}

Errors ​

HTTPCodeWhen
403insufficient_scopeThe key does not have calls:write.
403permission_deniedThe key's member may not place AI calls in the agent's campaign, or (with phone) may not manage its leads.
404not_foundThe agent does not exist, is not an enabled outbound agent or is outside the key's campaigns, or the lead is not in the agent's campaign or the member cannot see it (a replay of an earlier request included).
409do_not_callThe number is on the do-not-call list. Final; do not retry.
409invalid_phoneThe lead's number cannot be called. Final; do not retry.
409not_callableThe lead is outside calling hours and no later calling window can be found.
409idempotency_conflictThe Idempotency-Key was already used for a different request. Nothing was dialed.
413payload_too_largeThe body is larger than 1 MB. It was not read and nothing was dialed.
422invalid_requestThe body or header is invalid: a missing or malformed Idempotency-Key, unknown fields, an invalid phone or email, or not exactly one of lead_id and phone (or names sent with lead_id), which is reported as field body.
503dependency_unavailableThe do-not-call list or the campaign's calling-hours settings cannot be read right now. Nothing was placed; retry with the same Idempotency-Key.

Every endpoint can also answer 401 invalid_api_key, 429 rate_limited and 503 dependency_unavailable. See Errors in the overview.