> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pilotstatus.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Referência da API de Chamadas

> Todos os endpoints /v1/calls — iniciar, atender, rejeitar e encerrar chamadas, configurações de chamadas e permissões de chamada.

# Referência da API de Chamadas

URL base: `https://pilotstatus.com.br/v1` Cabeçalhos: `Content-Type: application/json`, `x-api-key: <your_api_key>` (ou `x-api-key-id`).

<Note>
  As chamadas funcionam em **dois provedores**: números **Meta Cloud API** e números **não oficiais (Pilot Status web)** (conectados por QR). Qualquer outro provedor retorna `400 FEATURE_NOT_SUPPORTED`. Todos os endpoints exigem uma chave **com escopo de número**. Veja a [visão geral](/pt-BR/api/calls/overview).
</Note>

<Warning>
  **Meta exige SDP.** No provedor Meta a mídia flui pelo navegador via WebRTC — você fornece uma oferta SDP ao iniciar e uma resposta SDP ao atender. **O provedor não oficial não usa SDP:** a mídia é tratada no **servidor**, então `sdpOffer`/`sdpAnswer` permanecem `null` e não há modelo de permissão BIC nem superfície de configurações de chamada.
</Warning>

## Endpoints

Os provedores marcados são os que suportam cada endpoint. Chamar um endpoint em um provedor não suportado retorna `400 FEATURE_NOT_SUPPORTED`. Se um número não oficial não estiver conectado, os endpoints retornam `409 WHATSAPP_INSTANCE_NOT_CONNECTED`.

| Método | Endpoint                              | Provedores              | Descrição                                                                                      |
| ------ | ------------------------------------- | ----------------------- | ---------------------------------------------------------------------------------------------- |
| `POST` | `/v1/calls`                           | META, não oficial       | Inicia uma chamada iniciada pela empresa (BIC).                                                |
| `GET`  | `/v1/calls`                           | META, não oficial       | Lista as chamadas do número (mais recentes primeiro; `limit` 1–100, `before` cursor ISO 8601). |
| `GET`  | `/v1/calls/{callId}`                  | META, não oficial       | Uma chamada; adicione `?includeSdp=1` para receber `sdpOffer`/`sdpAnswer` (Meta).              |
| `POST` | `/v1/calls/{callId}/accept`           | META, não oficial       | Atende uma chamada recebida (UIC). No Meta, com resposta SDP; no não oficial, sem SDP.         |
| `POST` | `/v1/calls/{callId}/reject`           | META, não oficial       | Recusa uma chamada recebida (sem corpo).                                                       |
| `POST` | `/v1/calls/{callId}/terminate`        | META, não oficial       | Desliga uma chamada ativa (sem corpo).                                                         |
| `POST` | `/v1/calls/{callId}/pre-accept`       | **Somente META**        | Resposta SDP antecipada OPCIONAL (reduz cortes no áudio; a chamada só conecta ao aceitar).     |
| `GET`  | `/v1/calls/settings`                  | **Somente META**        | Lê o objeto de configurações `calling` do número.                                              |
| `PUT`  | `/v1/calls/settings`                  | **Somente META**        | Atualização parcial das configurações `calling`.                                               |
| `GET`  | `/v1/calls/permissions?to=<phone>`    | **Somente META**        | Verifica se a empresa pode ligar para `to`.                                                    |
| `POST` | `/v1/calls/permissions/request`       | **Somente META**        | Envia a solicitação interativa de permissão de chamada (dentro da janela de 24h).              |
| `POST` | `/v1/calls/{callId}/play`             | **Somente não oficial** | Reproduz um arquivo de áudio na chamada (mídia no servidor); `hangupAfterPlay` opcional.       |
| `POST` | `/v1/calls/{callId}/realtime-session` | **Somente não oficial** | Abre uma sessão WebSocket full-duplex de áudio PCM16.                                          |

`{callId}` aceita **ou** o id de chamada do Pilot Status (`call_...`) **ou** o id de chamada da Meta (`wacid...`).

## 1. Iniciar uma chamada (BIC)

<CodeGroup>
  ```bash Meta (com SDP) theme={null}
  curl -X POST "https://pilotstatus.com.br/v1/calls" \
    -H "Content-Type: application/json" \
    -H "x-api-key: ps_your_key_here" \
    -d '{
      "to": "+5511999999999",
      "sdp": "v=0\r\no=- 4611731400430051336 2 IN IP4 127.0.0.1\r\n...",
      "sdpType": "offer",
      "bizOpaqueCallbackData": "order-42"
    }'
  ```

  ```bash Não oficial (sem SDP) theme={null}
  curl -X POST "https://pilotstatus.com.br/v1/calls" \
    -H "Content-Type: application/json" \
    -H "x-api-key: ps_your_key_here" \
    -d '{ "to": "+5511999999999" }'
  ```
</CodeGroup>

```json theme={null}
HTTP 201
{ "id": "call_01HZX...", "externalCallId": "wacid.ABGG...", "status": "INITIATED" }
```

* **Meta:** `sdp` é a **oferta** RFC 8866 produzida pelo SEU cliente WebRTC. O SDP do lado da empresa deve usar `a=setup:active`. Sem permissão, a Meta retorna 138006 → o endpoint expõe `code: "META_CALL_PERMISSION_REQUIRED"`.
* **não oficial:** não envie `sdp` — a mídia é tratada no servidor. Não há modelo de permissão BIC.
* `bizOpaqueCallbackData` (opcional, Meta) é devolvido no webhook de encerramento.

## 2. Atender uma chamada recebida (UIC)

Quando um usuário liga para o seu número, você recebe o webhook **`call.ringing`**. Então:

<CodeGroup>
  ```bash Meta (com resposta SDP) theme={null}
  # busca a chamada com a oferta SDP
  curl "https://pilotstatus.com.br/v1/calls/wacid.ABGG...?includeSdp=1" \
    -H "x-api-key: ps_your_key_here"

  # atende (corpo: sua resposta SDP; sdpType usa "answer" como padrão)
  curl -X POST "https://pilotstatus.com.br/v1/calls/wacid.ABGG.../accept" \
    -H "Content-Type: application/json" \
    -H "x-api-key: ps_your_key_here" \
    -d '{ "sdp": "v=0\r\n..." }'
  ```

  ```bash Não oficial (sem SDP) theme={null}
  curl -X POST "https://pilotstatus.com.br/v1/calls/call_01HZX.../accept" \
    -H "x-api-key: ps_your_key_here"
  ```
</CodeGroup>

```bash theme={null}
# recusa / desliga (sem corpo, ambos provedores)
curl -X POST "https://pilotstatus.com.br/v1/calls/wacid.ABGG.../reject" -H "x-api-key: ps_your_key_here"
curl -X POST "https://pilotstatus.com.br/v1/calls/wacid.ABGG.../terminate" -H "x-api-key: ps_your_key_here"
```

`accept`/`pre-accept`/`reject`/`terminate` respondem `{ "success": true, "id": "call_...", "status": "..." }`. O `pre-accept` (**somente Meta**) é opcional (resposta SDP antecipada para reduzir cortes); a chamada só conecta no `accept`.

## 3. Habilitar chamadas e configurações (somente Meta)

<Note>
  As seções 3 e 4 aplicam-se **apenas a números Meta**. No provedor não oficial não há superfície de configurações de chamada nem modelo de permissão BIC — chamar esses endpoints retorna `400 FEATURE_NOT_SUPPORTED`.
</Note>

O Pilot Status tenta habilitar chamadas automaticamente quando um número Meta conecta. Leia/ajuste a qualquer momento:

```bash theme={null}
curl "https://pilotstatus.com.br/v1/calls/settings" \
  -H "x-api-key: ps_your_key_here"

curl -X PUT "https://pilotstatus.com.br/v1/calls/settings" \
  -H "Content-Type: application/json" \
  -H "x-api-key: ps_your_key_here" \
  -d '{ "status": "ENABLED", "call_icon_visibility": "DEFAULT" }'
```

* O `PUT` é **parcial**: envie apenas `status`, `call_icon_visibility`, `callback_permission_status`, `call_hours`, `voicemail` (o objeto `sip` é rejeitado).
* Um `call_hours` enviado **substitui** o objeto armazenado por completo (semântica da Meta).
* Números com um limite de mensagens **abaixo de 2.000/dia ainda não podem habilitar chamadas** (erro 138015 da Meta).
* Credenciais SIP nunca são solicitadas nem retornadas.

## 4. Permissão de chamada (somente Meta, obrigatória antes de uma BIC)

```bash theme={null}
# verificar
curl "https://pilotstatus.com.br/v1/calls/permissions?to=%2B5511999999999" \
  -H "x-api-key: ps_your_key_here"

# solicitar (dentro da janela de atendimento de 24h)
curl -X POST "https://pilotstatus.com.br/v1/calls/permissions/request" \
  -H "Content-Type: application/json" \
  -H "x-api-key: ps_your_key_here" \
  -d '{ "to": "+5511999999999", "text": "May we call you about your order?" }'
```

Resposta da verificação:

```json theme={null}
{
  "permission": { "status": "temporary", "expiration_time": 1768550400 },
  "actions": [
    {
      "action_name": "start_call",
      "can_perform_action": true,
      "limits": [{ "time_period": "PT24H", "max_allowed": 1, "current_usage": 0 }]
    }
  ]
}
```

A resposta do usuário chega como o evento de webhook **`call.permission_updated`** (`status`: `NO_PERMISSION` | `TEMPORARY` | `PERMANENT`). A Meta limita a taxa de solicitações de permissão (erro 138009) e o volume de BIC (100 chamadas/24h por número — erro 138012).

## 5. Reproduzir áudio na chamada (somente não oficial)

Nos números não oficiais a mídia é tratada no servidor, então você pode instruir o backend a **baixar um arquivo de áudio e reproduzi-lo** na chamada ativa. O backend busca a URL através de um guard de SSRF.

```bash theme={null}
curl -X POST "https://pilotstatus.com.br/v1/calls/call_01HZX.../play" \
  -H "Content-Type: application/json" \
  -H "x-api-key: ps_your_key_here" \
  -d '{ "url": "https://example.com/audio.ogg" }'
```

<Warning>
  Endpoint **somente não oficial** — em um número Meta retorna `400 FEATURE_NOT_SUPPORTED`.
</Warning>

## 6. Sessão de áudio em tempo real (somente não oficial)

Abre uma sessão WebSocket **full-duplex de áudio PCM16** para transmitir áudio de/para a chamada ao vivo.

```bash theme={null}
curl -X POST "https://pilotstatus.com.br/v1/calls/call_01HZX.../realtime-session" \
  -H "x-api-key: ps_your_key_here"
```

```json theme={null}
{ "wsUrl": "wss://<host-de-mídia-dedicado>/...", "token": "...", "expiresIn": 120 }
```

<Note>
  A `wsUrl` retornada aponta para um **host de mídia dedicado** — conecte-se **diretamente** a ela (não é feito proxy). O token é de **uso único** com TTL de \~2 minutos. A camada HTTP não faz upgrade de WebSocket. Endpoint **somente não oficial** (Meta → `400 FEATURE_NOT_SUPPORTED`).
</Note>

## 7. Objeto de chamada (DTO)

```json theme={null}
{
  "id": "call_01HZX...",
  "externalCallId": "wacid.ABGG...",
  "direction": "INBOUND",
  "status": "COMPLETED",
  "peerNumber": "5511999999999",
  "fromNumber": "5511999999999",
  "conversationId": "conv_abc",
  "bizOpaqueCallbackData": null,
  "startedAt": "2026-07-03T15:00:00.000Z",
  "connectedAt": "2026-07-03T15:00:05.000Z",
  "endedAt": "2026-07-03T15:02:05.000Z",
  "durationSeconds": 120,
  "errorCode": null,
  "errorMessage": null,
  "createdAt": "2026-07-03T15:00:00.000Z",
  "updatedAt": "2026-07-03T15:02:05.000Z"
}
```

* `status`: `INITIATED` | `RINGING` | `ACCEPTED` | `REJECTED` | `COMPLETED` | `FAILED` | `MISSED`.
* `direction`: `INBOUND` (UIC) | `OUTBOUND` (BIC).
* Os SDPs (`sdpOffer`/`sdpAnswer`) aparecem apenas com `?includeSdp=1` em `GET /v1/calls/{callId}` — nunca na listagem. No provedor não oficial permanecem `null` (mídia no servidor).
* `durationSeconds` é definido apenas quando a chamada foi atendida.

## Webhooks

Estes eventos disparam para **ambos os provedores** (META e não oficial):

<Card title="Eventos de chamada" icon="phone">
  `call.ringing` · `call.connected` · `call.ended` (com `duration` em segundos quando atendida) · `call.missed`
</Card>

O evento `call.permission_updated` é **exclusivo da Meta** — números não oficiais não têm modelo de permissão de chamada. (No objeto de chamada REST retornado por `GET /v1/calls`, o campo equivalente é `durationSeconds`.)

## Faturamento

* **Meta:** as BIC são cobradas pela Meta na WABA (por minuto, pulsos de 6s, apenas quando atendida). As UIC são gratuitas.
* **não oficial:** sem cobrança por minuto da Meta.
* O Pilot Status não cobra nada pelas chamadas em nenhum dos provedores.

## Erros comuns

* `400 FEATURE_NOT_SUPPORTED` — o número da chave não suporta o endpoint (ex.: um provedor não suportado, ou um endpoint exclusivo de um provedor chamado no outro).
* `409 WHATSAPP_INSTANCE_NOT_CONNECTED` — número não oficial não conectado.
* `400 NUMBER_NOT_FOUND` — a chave não está vinculada a um número.
* `400` — validação do corpo, `INVALID_LIMIT`, `INVALID_BEFORE`, `MISSING_TO`.
* `401` — `x-api-key` / `x-api-key-id` ausente/inválido.
* `403` — chave com escopo de tenant (os endpoints de chamadas têm escopo de número).
* `404 CALL_NOT_FOUND` — o callId/wacid não pertence ao número da chave.
* Erros de chamada da Meta são encaminhados com um `code` mapeado — ex.: `META_CALL_PERMISSION_REQUIRED` (138006), limite de solicitação de permissão (138009), limite de BIC de 100 chamadas/24h (138012), chamadas não habilitadas (138000), tier de mensagens muito baixo para habilitar (138015), `META_CALLING_PAYMENT_REQUIRED` (131044 — a WABA não tem método de pagamento; chamadas iniciadas pela empresa são cobradas pela Meta, adicione um cartão em Configurações de pagamento do WhatsApp Manager).
