Operação
Números e pareamento
O número é a linha por onde se fala, e o canal é propriedade dele. Você usa o
numberId para enviar, e o estado de conexão para saber se aquela
linha está de pé.
Listar os seus números
GET /v1/numbers
curl -H "x-api-key: $NUNTIS_API_KEY" \
https://api.nuntis.com.br/v1/numbers
{
"data": [
{
"id": "num_4711",
"channel": "whatsapp-unofficial",
"label": "Comercial",
"phoneE164": "+5511999990000",
"status": "connected",
"since": "2026-08-13T13:30:00.000Z",
"sinceUnix": 1786533000,
"lastCheckedAt": "2026-08-13T13:44:30.000Z",
"lastCheckedAtUnix": 1786534070
},
{
"id": "num_4712",
"channel": "telegram",
"label": "Bot de atendimento",
"phoneE164": null,
"status": "connected",
"since": null,
"sinceUnix": null,
"lastCheckedAt": null,
"lastCheckedAtUnix": null
}
]
}
A resposta traz todos os seus números e nunca é truncada em silêncio — não há paginação nesta rota. Se um dia houver, ela entra de forma aditiva, sem mudar o que já existe.
Se você ainda não tem número nenhum, a resposta é 200 com
data: [] — nunca 404.
Não há como criar, editar ou apagar número por este contrato. O cadastro é operação administrativa. Esta rota só lê, e só o que é seu.
Estados de conexão
| Estado | Significa |
|---|---|
connected | Transporte ligado e sessão pareada. Pronto para enviar. |
disconnected | Transporte desligado. |
qr_required | Transporte ligado, sessão não pareada. Precisa escanear o código. |
connecting | Conexão pedida, ainda sem um estado conclusivo. |
unreachable | O canal parou de responder. É veredito do Nuntis, não do canal. |
banned | O número foi bloqueado pelo canal. |
disconnected
O conjunto é aditivo: valores novos podem aparecer. Um
switch exaustivo que hoje compila vai encontrar um valor que
não conhece amanhã, em produção. O default seguro é
disconnected — ele leva você a verificar, em vez de assumir que
está tudo bem. A mesma regra vale para channel.
Não há ordem entre os estados
Ao contrário do status de mensagem, aqui não existe escada. Um número vai e volta livremente entre conectado, desconectado e pareamento pendente — um telefone sai do ar e volta, e um “estado que só avança” faria o contrato mentir sobre a realidade física.
Consultar o estado de um número
GET /v1/numbers/{id}/status
{
"status": "connected",
"since": "2026-08-13T13:30:00.000Z",
"sinceUnix": 1786533000,
"lastCheckedAt": "2026-08-13T13:44:30.000Z",
"lastCheckedAtUnix": 1786534070
}
lastCheckedAt
A resposta vem do estado que o Nuntis mantém, por
verificação periódica — não de uma consulta ao canal feita agora.
lastCheckedAt é a idade da informação, e um valor
antigo significa que o próprio canal pode estar inalcançável.
disconnected com lastCheckedAt: null quer dizer
“nunca verifiquei”, que é diferente de “verifiquei e está fora”.
Você não precisa consultar em laço: mudanças de estado chegam sozinhas pelo
evento connection.updated, e
o numberId de lá é o mesmo dos eventos de mensagem.
Parear um número
POST /v1/numbers/{id}/pairing
curl -X POST -H "x-api-key: $NUNTIS_API_KEY" \
https://api.nuntis.com.br/v1/numbers/num_4711/pairing
{
"status": "qr_required",
"qr": {
"code": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
"format": "png-data-uri",
"obtainedAt": "2026-08-13T13:45:12.000Z",
"obtainedAtUnix": 1786534112
},
"hint": { "refreshAfterSeconds": 20 }
}
O qr.code é um data URI completo, pronto para usar
direto:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..." alt="Código de pareamento">
Chame de novo para obter um código fresco enquanto o operador não escaneia —
use o hint.refreshAfterSeconds como intervalo. Não existe
“sessão de pareamento” para você manter do seu lado, e não há nada para
encerrar se o operador desistir.
Se o número já estiver conectado, a resposta é
200 com status: "connected" e qr: null.
Pedir pareamento do que já está pareado não é erro.
| Resposta | Quando |
|---|---|
404 NOT_FOUND | Número inexistente — ou de outro produto. |
422 CHANNEL_CAPABILITY_UNSUPPORTED | O canal não usa pareamento por código. |
503 CHANNEL_UNREACHABLE | Canal indisponível. retryable: true. |
504 PAIRING_QR_TIMEOUT | O canal não produziu um código a tempo. retryable: true. |
Fluxo de pareamento
- Chame
POST /v1/numbers/{id}/pairing. - Se vier
status: "connected", acabou. - Exiba o
qr.codeao operador. - Repita a chamada a cada ~20 s e substitua a imagem, enquanto ninguém escanear.
- Pare quando chegar
connection.updatedcomstate: "connected", ou quando a chamada devolverconnected.
Encerrar a sessão
DELETE /v1/numbers/{id}/session
curl -X DELETE -H "x-api-key: $NUNTIS_API_KEY" \
https://api.nuntis.com.br/v1/numbers/num_4711/session
Destrói a sessão pareada: o número volta a exigir pareamento. É idempotente — sessão já encerrada devolve o mesmo resultado.
O número continua cadastrado e continua existindo no canal. O que morre é a sessão; não há rota de contrato que descadastre um número.
Sinalizar presença
POST /v1/numbers/{id}/presence
curl -X POST https://api.nuntis.com.br/v1/numbers/num_4711/presence \
-H "x-api-key: $NUNTIS_API_KEY" \
-H "content-type: application/json" \
-d '{ "conversationId": "conv_991", "state": "typing" }'
Estados aceitos: typing, recording,
paused e seen. O último marca como lidas as
mensagens recebidas daquela conversa. A resposta é 204, sem
corpo.
Ao contrário do envio de mensagem, presença vale agora ou não vale.
“Digitando…” entregue 40 segundos depois não é atraso, é mentira — o
operador já parou de digitar. Por isso não há garantia de entrega, não há
registro no histórico da conversa, e a proteção contra abuso é um teto por
minuto que devolve 429 RATE_LIMITED.
Capacidade do canal
GET /v1/channels
Consulte uma vez, no boot da sua aplicação, e guarde. A declaração diz o que cada canal sabe fazer:
{
"data": [
{
"id": "whatsapp-unofficial",
"texto": true,
"midia": ["image", "audio", "video", "document"],
"reply": true,
"audioPtt": true,
"deliveryReceipts": "read",
"janelaResposta": { "exige": false },
"template": { "exige": false },
"presence": true
},
{
"id": "telegram",
"deliveryReceipts": "none"
}
]
}
| Campo | O que decide na sua interface |
|---|---|
deliveryReceipts |
none · delivered · read — até onde vão as confirmações. Com none, sent é o estado final de sucesso. |
midia | Tipos de mídia aceitos por este canal. |
janelaResposta | Se o canal exige que o contato tenha falado primeiro. |
template | Se o canal exige template pré-aprovado. |
audioPtt | Se aceita áudio como nota de voz. |
presence | Se aceita sinalização de presença. |
Canal novo aparece aqui de forma aditiva. Se você lê a declaração em vez de assumir, o seu código já nasce pronto para ele.