Skip to navigation

Outbound calls

POST /calls places a call for one of your extensions. The key must have the calls:write scope.

curl -X POST https://telephony.hams.ai/api/developer/v1/calls \
-H "Authorization: Bearer $CCC_KEY" \
-H "Content-Type: application/json" \
-d '{ "from_extension_id": "01924f8e-...", "to": "+971500000000" }'
FieldMeaning
from_extension_idThe id of the extension that rings first. It must be an active extension of the account
toThe number to dial after the extension answers. It has 2 to 32 characters: digits, *, #, and an optional leading +

The response is 202 with { "id": "..." }. This id is the one id of the call. Call history, the live board, every webhook about the call, and GET /cdrs all use it.

How the call runs

  1. The extension rings. The phone of the agent shows the number that the system is about to dial.
  2. The agent answers. The system dials the number through the outbound route that matches it.
  3. The agent hears ringback during the whole dial. Then the far end answers or does not answer.

The outbound route sets the trunk and the recording policy. The caller ID is the outbound caller ID of the extension. If the extension has none, it is the default caller ID of the trunk. If the trunk has none, it is the extension number. The caller_out rules of the route can then change it. The result is the same as when the agent dials the number on the phone.

The call is a normal call from the moment the system places it. It shows on the live board with the extension as its agent. It produces a full record when it ends. If the route records the call, the system merges the recording and sends call.recording_ready.

Numbers in the call record

In the record of a call that the API places, the numbers are the ones that the carrier saw:

  • from_number is the caller ID that the carrier saw. from_type is did.
  • to_number is the number that the system dialed, after the callee_out rules of the route.
  • agent_extension_snapshot is the extension that placed the call.

The call.completed webhook carries the same numbers as the record. The live events that come before it show the extension as from and the dialed number as to. See Webhooks.

When the call does not connect

If the extension never takes the call, the record names the agent side as the cause. It does not name the destination. Read outcome_detail in the record:

outcomeoutcome_detailWhat happened
no_answeragent_declinedThe agent rejected the ring
no_answeragent_no_answerThe extension rang and nobody answered
failedagent_unreachableNo device had registered the extension
failedunreachable or congestionThe extension answered, but the carrier refused the number

If the destination answers, the record shows outcome: answered. An API-placed call has one outbound leg, so outcome_detail is outbound.

Errors for this endpoint

StatusMeaning
403The key does not have the calls:write scope
404from_extension_id is not an active extension of this account
422No outbound route matches to, or to is not a valid number (validation_error)
429The limit for the key or the limit of calls each second for the account is exceeded. Wait for Retry-After
503No call server is available (service_unavailable). Try again later

The limit on new calls is separate from the request limit for the rest of the API. By default, an account can start 5 new calls each second, and each key can make 10 requests each second. A deployment can set both limits. A burst of dials can reach it while ordinary reads still succeed.