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

# Troncos SIP

> Conecte o seu PBX ou tronco SIP existente às chamadas do WhatsApp de um número conectado.

Um tronco SIP conecta um sistema telefônico que você já opera, como um PBX ou
uma plataforma de central de atendimento, às chamadas do WhatsApp de um número
conectado. As chamadas recebidas do WhatsApp podem tocar no seu PBX, e o seu
PBX pode ligar para usuários do WhatsApp pelo número. A Polymorfa não hospeda um
PBX e não fornece números de telefone.

Os troncos SIP fazem parte das Chamadas. Toda equipe que usa as Chamadas pode
criar troncos em qualquer um dos seus projetos; não é preciso se inscrever. No
Console, proprietários e administradores da equipe adicionam, alteram e excluem
troncos. Leia o endereço SIP e as portas aos quais o seu PBX se conecta pela API
ou pelo Console; consulte [Encontre o endereço SIP](#find-the-sip-address).

## Como um tronco funciona

Um tronco pertence a um projeto e tem uma direção:

| `direction` | Efeito |
| - | - |
| `outbound` | A Polymorfa envia ao seu PBX as chamadas recebidas do WhatsApp das sessões roteadas. |
| `inbound` | O seu PBX faz chamadas do WhatsApp por uma sessão do projeto. |
| `both` | As duas opções acima. |

Em uma chamada, o tronco é um participante chamado `server:sip:<trunkId>`. A
conexão dele informa o transporte `sip`. As pessoas no WhatsApp sempre ouvem o
seu PBX, e o seu PBX sempre as ouve. Ele nunca ouve o próprio áudio. Se o seu
PBX e os seus outros participantes ouvem uns aos outros depende do
[modo conferência](/pt-br/guides/calls/overview#conference-mode) da sessão:
ativado (o padrão), eles se ouvem; desativado, cada um ouve apenas as pessoas
no WhatsApp. Os troncos SIP transportam apenas áudio.

Gerencie os troncos com a Platform API. A leitura exige `sessions:read`; toda
alteração exige `sessions:manage`. Use uma chave de equipe com `projectId`, ou
um token de projeto para o próprio projeto. Tokens de cliente não podem
gerenciar troncos.

O SDK TypeScript gerencia os troncos com `sipTrunks`; consulte [Conecte um tronco SIP](/pt-br/sdks/typescript/calls#conecte-um-tronco-sip). Você também pode gerenciar os troncos no Console: abra um
projeto, acesse **Chamadas** e escolha **Gerenciar troncos SIP**. Consulte
[Chamadas no Console](/pt-br/console/calls#sip-trunks).

## Encontre o endereço SIP

Todos os troncos de todos os projetos usam o mesmo endereço SIP. Leia-o com
`GET /platform/sip/endpoint`. Ele exige `sessions:read` e aceita uma chave de
equipe ou um token de projeto:

```bash theme={null}
curl "https://api.polymorfa.com/platform/sip/endpoint" \
  -H "Authorization: Bearer $POLYMORFA_KEY"
```

```json theme={null}
{
  "success": true,
  "data": {
    "status": "hosted",
    "host": "SIP_HOST",
    "transports": [
      { "transport": "udp", "port": 5060, "srtp": "not_supported" },
      { "transport": "tcp", "port": 5060, "srtp": "not_supported" },
      { "transport": "tls", "port": 5061, "srtp": "required" }
    ],
    "rtp": { "protocol": "udp", "portMin": 31000, "portMax": 31099 }
  }
}
```

A resposta descreve o ambiente ao qual a sua chave pertence, então use os
valores que ela retorna em vez dos marcadores acima.

| Campo | Descrição |
| - | - |
| `status` | `hosted`, ou `sip_not_hosted` quando o ambiente não tem endereço SIP. |
| `host` | Nome do host para o qual o seu PBX envia SIP. `null` quando `status` é `sip_not_hosted`. |
| `transports` | Cada transporte SIP com a porta dele. `srtp` é `required` para `tls` e `not_supported` para `udp` e `tcp`. Vazio quando `status` é `sip_not_hosted`. |
| `rtp` | Intervalo de portas UDP que a Polymorfa usa para o áudio das chamadas. `null` quando `status` é `sip_not_hosted`. |

Quando `status` é `sip_not_hosted`, o ambiente não tem um endereço SIP ao qual
um PBX possa se conectar, e a resposta não retorna host nem portas.

Configure o seu firewall com estes valores:

* Permita SIP nas portas listadas, nos dois sentidos, entre o seu PBX e os
  endereços para os quais `host` resolve.
* Permita UDP nos dois sentidos entre as portas de mídia do seu PBX e o
  intervalo `rtp` nos mesmos endereços.
* Prefira `tls`: ele criptografa a sinalização, e a exigência de SRTP dele
  criptografa o áudio. `udp` e `tcp` transportam os dois sem criptografia.

Você também encontra o endereço no Console, na página **Troncos SIP**, ou pode lê-lo com `sipTrunks.endpoint()` no SDK TypeScript.

## Crie um tronco

```bash theme={null}
curl -X POST "https://api.polymorfa.com/platform/sip-trunks" \
  -H "Authorization: Bearer $POLYMORFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "projectId": "PROJECT_ID",
    "name": "Head office PBX",
    "direction": "both",
    "outbound": {
      "targetUri": "sip:whatsapp@pbx.example.com:5061",
      "transport": "tls",
      "authUsername": "polymorfa",
      "authPassword": "PBX_PASSWORD"
    },
    "inbound": {
      "session": "support",
      "allowedAddresses": ["203.0.113.10", "198.51.100.0/28"],
      "allowedDestinations": ["+44", "+1415"]
    },
    "codecs": ["PCMA", "PCMU", "opus"],
    "maxConcurrentCalls": 30
  }'
```

A resposta retorna `201` com o tronco e, para troncos `inbound` e `both`,
`inboundCredentials`:

```json theme={null}
{
  "success": true,
  "data": {
    "trunk": { "id": "TRUNK_ID", "direction": "both", "revision": 1, "...": "..." },
    "inboundCredentials": {
      "username": "tq7m4k2xmabn5c3dpe6fr2hw",
      "password": "SHOWN_ONCE",
      "realm": "polymorfa"
    }
  }
}
```

> [!WARNING]
>
> A senha de entrada aparece apenas nesta resposta e em uma resposta de rotação
> de credenciais. Guarde-a no seu PBX imediatamente. As respostas nunca
> retornam senhas de novo; `outbound.hasPassword` mostra se há uma senha
> armazenada.

Um projeto comporta até 100 troncos. Cada tronco transporta no máximo
`maxConcurrentCalls` chamadas ao mesmo tempo (de 1 a 500, padrão 30).

## Envie chamadas do WhatsApp para o seu PBX

Defina estes campos em `outbound`:

| Campo | Descrição |
| - | - |
| `targetUri` | URI `sip:` ou `sips:` do seu PBX, com um nome de host público ou endereço IP e uma porta opcional. Uma parte de usuário, como em `sip:support@pbx.example.com`, se torna o usuário chamado. |
| `transport` | `udp`, `tcp` ou `tls`. Uma URI `sips:` exige `tls`. A porta padrão é 5060, ou 5061 para `tls`. |
| `authUsername` | Usuário com que a Polymorfa responde quando o seu PBX envia um desafio digest. Defina-o junto com `authPassword`. |
| `authPassword` | Senha somente de escrita para `authUsername`. |
| `fromUser` | Substituição opcional do usuário do cabeçalho From. Defina-a quando o seu PBX exigir um endereço de origem fixo. |

Depois, roteie as chamadas recebidas da sessão para o tronco:

```bash theme={null}
curl -X PUT "https://api.polymorfa.com/platform/sessions/support/call-settings" \
  -H "Authorization: Bearer $POLYMORFA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "inboundRoute": "sip_trunk",
    "sipTrunkId": "TRUNK_ID",
    "sipClaim": true
  }'
```

O tronco precisa pertencer ao projeto da sessão e ter a direção `outbound` ou
`both`. As configurações que você omite mantêm os valores; uma atualização
posterior sem `sipTrunkId` mantém o tronco. Para parar de enviar chamadas ao
tronco, envie `"inboundRoute": "clients"`, o que também limpa `sipTrunkId`. Em
um número da Cloud API, as chamadas recebidas só chegam ao tronco quando
`hostCloudApiCalls` é `true`; consulte
[Números da Cloud API](/pt-br/guides/calls/overview#cloud-api-numbers). Consulte
[Update call settings](/api-reference/platform/calls/update-call-settings).

Quando uma chamada roteada toca, a Polymorfa liga para `targetUri`. A chamada
continua tocando para os participantes do seu SDK, e eles podem atendê-la
primeiro. A requisição para o seu PBX leva o ID da chamada do WhatsApp no
cabeçalho `X-Polymorfa-Call-ID`.

* Quando o seu PBX atende, a Polymorfa atende a chamada do WhatsApp como
  `server:sip:<trunkId>`. Com `sipClaim: true`, o atendimento faz o claim da
  chamada: os outros participantes param de tocar e não podem entrar. Com
  `sipClaim: false`, a chamada continua compartilhada e outros participantes
  podem entrar. Consulte
  [Atender, entrar ou recusar](/pt-br/guides/calls/overview#answer-join-or-decline).
* Quando o seu PBX não atende, a chamada do WhatsApp continua tocando para os
  seus outros participantes até ser atendida ou recusada, ou até a janela de
  toque terminar.
* Quando o seu PBX desliga, a conexão dele sai. Se o tronco fez o claim da
  chamada, a chamada termina. Quando a chamada do WhatsApp termina, a Polymorfa
  desliga o seu PBX.

O evento `call.connection_left` do tronco informa por que a conexão dele saiu:

| `reason` | Significado |
| - | - |
| `left` | O seu PBX desligou. |
| `call_ended` | A chamada do WhatsApp terminou. |
| `claimed` | Outro participante fez o claim da chamada antes. |
| `sip_busy` | O seu PBX respondeu ocupado (`486` ou `600`). |
| `sip_declined` | O seu PBX recusou a chamada (`603` ou `403`). |
| `sip_no_answer` | O seu PBX não atendeu em 60 segundos, ou respondeu `408`, `480` ou `487`. |
| `sip_auth_failed` | O seu PBX rejeitou `authUsername` e `authPassword`. |
| `sip_unavailable` | O destino estava inacessível, recusou a chamada ou retornou uma resposta inutilizável, inclusive um endereço de mídia para o qual a Polymorfa não envia. |

Um tronco que nunca atendeu informa apenas a saída, sem uma entrada anterior.

Os controles de mídia ao vivo informam `call_ended` quando uma conexão
estabelecida fecha porque a chamada terminou. Um desligamento normal pelo PBX
continua como `left`. Os webhooks encerram as conexões ainda abertas com
`call.ended`, sem um evento `call.connection_left` adicional.

## Ligue para o WhatsApp a partir do seu PBX

Configure o seu PBX com:

* o `host` e uma porta de [Encontre o endereço SIP](#find-the-sip-address);
* `inboundCredentials.username` e `password` para a autenticação digest; e
* o número do WhatsApp a chamar, no formato E.164, como parte de usuário da URI
  da requisição, por exemplo `sip:+14155550100@SIP_HOST`. O `+` inicial é
  opcional e um prefixo `00` é aceito.

Defina `inbound.session` como a sessão que faz as chamadas. A Polymorfa só
aceita uma chamada quando as credenciais digest são válidas, a requisição vem de
um dos `allowedAddresses`, o tronco está ativado, o projeto dele está ativo e o
número corresponde a um dos `allowedDestinations` (ou a lista está vazia). A
chamada conta para o mesmo limite por minuto de chamadas realizadas que as
chamadas feitas pela API a partir dessa sessão.

O tronco faz o claim de toda chamada que faz. O seu PBX recebe:

| Resposta | Quando |
| - | - |
| `401` | A requisição não tinha credenciais, ou reutilizou um desafio expirado ou já usado. Responda ao novo desafio. |
| `403` | A autenticação falhou, o endereço ou o destino não é permitido, o tronco está desativado ou as chamadas estão desativadas na sessão dele. |
| `404` | O usuário da URI da requisição não é um número de telefone, ou o número não está no WhatsApp. |
| `180` | O telefone do usuário do WhatsApp está tocando. |
| `200` | O usuário do WhatsApp atendeu. |
| `408` | O usuário do WhatsApp não atendeu. |
| `480` | Nenhuma sessão está definida, ou não foi possível conectar a chamada. |
| `486` | O tronco já está transportando `maxConcurrentCalls` chamadas. |
| `488` | A oferta não tem nenhum codec suportado, a segurança de mídia dela não corresponde ao transporte ou o endereço de mídia dela não é aceito (consulte [Mídia e segurança](#media-and-security)). |
| `503` | A capacidade de chamadas ou o limite por minuto foi atingido. Tente novamente mais tarde, depois do intervalo de `Retry-After` quando ele for enviado. |
| `603` | O usuário do WhatsApp recusou a chamada. |

Toda recusa de autenticação é o mesmo `403`, então a resposta não revela qual
verificação falhou. Falhas repetidas de autenticação bloqueiam temporariamente
o endereço de origem. Quando o seu PBX cancela uma chamada que está tocando, a
chamada do WhatsApp termina. Quando o seu PBX desliga uma chamada conectada, a
chamada termina para todos.

## Mídia e segurança

* **Codecs.** PCMU e PCMA (8 kHz) e Opus (48 kHz, mono), na ordem de `codecs`.
  Para Opus, anuncie `opus/48000/2` no SDP; o áudio continua mono. Se um
  mapeamento de Opus for inutilizável, um codec PCMU ou PCMA oferecido pode
  transportar a chamada. O seu PBX precisa oferecer mídia no INVITE inicial;
  chamadas sem oferta são recusadas com `488`. As respostas a chamadas da
  Polymorfa precisam manter o número de carga RTP de um codec oferecido.
  Alterações de mídia durante a chamada são recusadas.
* **Pacotes.** 20 ms de áudio por pacote RTP.
* **Criptografia.** Com `tls`, a sinalização é criptografada e a mídia usa SRTP
  com chaves SDES (`AES_CM_128_HMAC_SHA1_80` ou `AES_CM_128_HMAC_SHA1_32`).
  Ofertas de RTP simples sobre TLS e ofertas de SRTP sobre UDP ou TCP são
  recusadas. Use `tls` quando o seu PBX estiver acessível pela internet.
* **Endereços.** Envie mídia a partir do endereço na descrição de sessão do seu
  PBX ou a partir do endereço de onde vem a sua sinalização. A Polymorfa envia a
  mídia de volta ao endereço de onde chega o seu primeiro pacote de mídia.
* **PBX atrás de NAT.** Um endereço privado (`10.0.0.0/8`, `172.16.0.0/12`,
  `192.168.0.0/16`, `100.64.0.0/10` ou `fc00::/7`) na descrição de sessão só
  funciona quando a sua sinalização vem de um endereço público. Nesse caso, a
  Polymorfa não envia mídia até que o primeiro pacote de mídia do seu PBX chegue
  desse endereço de sinalização, então o seu PBX precisa começar a enviar mídia.
* **Endereços recusados.** Descrições de sessão com um endereço de mídia de
  loopback, link-local, multicast, não especificado ou reservado são recusadas:
  a chamada do seu PBX recebe `488`, e uma chamada para o seu PBX termina com
  `sip_unavailable`. Destinos de tronco em endereços privados, de loopback ou
  link-local são rejeitados.

## Gerencie os troncos

| Operação | Requisição |
| - | - |
| Listar os troncos de um projeto | `GET /platform/sip-trunks?projectId=PROJECT_ID` |
| Ler um tronco | `GET /platform/sip-trunks/{trunkId}` |
| Alterar um tronco | `PATCH /platform/sip-trunks/{trunkId}` |
| Excluir um tronco | `DELETE /platform/sip-trunks/{trunkId}` |
| Fazer a rotação da senha de entrada | `POST /platform/sip-trunks/{trunkId}/credentials` |
| Ler o endereço SIP | `GET /platform/sip/endpoint` |

* `PATCH` altera apenas os campos que você envia. Omita `authPassword` para
  manter a senha armazenada; envie `authUsername: null` para remover os dois.
  Envie `expectedRevision` para recusar a alteração com
  `409 sip_trunk_revision_conflict` quando outra pessoa tiver alterado o tronco
  antes.
* Mudar `direction` para `outbound` remove as credenciais de entrada. Mudar um
  tronco `outbound` para `inbound` ou `both` cria um novo usuário; faça a
  rotação das credenciais dele para obter a senha.
* A rotação de credenciais substitui a senha. A senha antiga deixa de funcionar
  em cerca de um minuto. A rotação retorna `409 state_conflict` para troncos
  `outbound`.
* Excluir um tronco para o qual uma sessão ainda envia chamadas retorna
  `409 sip_trunk_in_use`. Antes, faça a sessão voltar a usar `clients`.
* As alterações chegam ao roteamento de chamadas em cerca de um minuto. As
  chamadas em andamento continuam.
* Quando o projeto de um tronco é desativado, alterar o tronco ou fazer a
  rotação das credenciais dele retorna `404 resource_not_found`. A Polymorfa
  deixa de enviar chamadas ao tronco e recusa as chamadas do PBX dele em cerca
  de um minuto. Você ainda pode listar, ler e excluir o tronco.

## Erros

| Status | `code` | Significado |
| - | - | - |
| `400` | `invalid_parameter` | Um campo está ausente ou é inválido; `param` indica qual. |
| `400` | `invalid_sip_trunk` | O tronco roteado não está no projeto da sessão ou não pode receber chamadas. |
| `403` | `permission_denied` | A credencial é um token de cliente ou não alcança esse projeto. |
| `404` | `resource_not_found` | O tronco ou o projeto não existe para a sua credencial, ou o projeto está desativado. |
| `409` | `sip_trunk_in_use` | Uma sessão envia chamadas para o tronco. |
| `409` | `sip_trunk_revision_conflict` | O tronco mudou depois da revisão que você enviou. |
| `409` | `sip_trunk_limit` | O projeto já tem 100 troncos. |
| `503` | `sip_unavailable` | Os troncos SIP não estão disponíveis no momento. |

Consulte [Erros](/api/errors) para o formato completo de erro.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.