> This page is for Cloud Call Center.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.hams.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.hams.ai/_mcp/server.

# Outbound calls

> Ring an extension, then dial the destination through the outbound routes of your account.

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

```bash
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" }'
```

| Field               | Meaning                                                                                                                  |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `from_extension_id` | The id of the extension that rings first. It must be an active extension of the account                                  |
| `to`                | The 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](/cloud-call-center/api/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:

| `outcome`   | `outcome_detail`              | What happened                                              |
| ----------- | ----------------------------- | ---------------------------------------------------------- |
| `no_answer` | `agent_declined`              | The agent rejected the ring                                |
| `no_answer` | `agent_no_answer`             | The extension rang and nobody answered                     |
| `failed`    | `agent_unreachable`           | No device had registered the extension                     |
| `failed`    | `unreachable` or `congestion` | The 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

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

> **Note**
>
> 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.

## Related

* [Quickstart](/cloud-call-center/api/quickstart)
* [Call history and recordings](/cloud-call-center/api/call-history-and-recordings)
* [Errors](/cloud-call-center/api/errors)
* [API Reference](/cloud-call-center/reference)