Nuntis documentação Referência da API

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

bash
curl -H "x-api-key: $NUNTIS_API_KEY" \
  https://api.nuntis.com.br/v1/numbers
200 OK
{
  "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.

Isto não é CRUD de número

Não há como criar, editar ou apagar número por este contrato. O cadastro é operação administrativa. Esta rota só , e só o que é seu.

Estados de conexão

EstadoSignifica
connectedTransporte ligado e sessão pareada. Pronto para enviar.
disconnectedTransporte desligado.
qr_requiredTransporte ligado, sessão não pareada. Precisa escanear o código.
connectingConexão pedida, ainda sem um estado conclusivo.
unreachableO canal parou de responder. É veredito do Nuntis, não do canal.
bannedO número foi bloqueado pelo canal.
Trate estado desconhecido como 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

200 OK
{
  "status": "connected",
  "since": "2026-08-13T13:30:00.000Z",
  "sinceUnix": 1786533000,
  "lastCheckedAt": "2026-08-13T13:44:30.000Z",
  "lastCheckedAtUnix": 1786534070
}
Leia o 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

bash
curl -X POST -H "x-api-key: $NUNTIS_API_KEY" \
  https://api.nuntis.com.br/v1/numbers/num_4711/pairing
200 OK
{
  "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:

html
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..." alt="Código de pareamento">
O código é perecível (~20 s) e a rota é reentrante

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.

RespostaQuando
404 NOT_FOUNDNúmero inexistente — ou de outro produto.
422 CHANNEL_CAPABILITY_UNSUPPORTEDO canal não usa pareamento por código.
503 CHANNEL_UNREACHABLECanal indisponível. retryable: true.
504 PAIRING_QR_TIMEOUTO canal não produziu um código a tempo. retryable: true.

Fluxo de pareamento

  1. Chame POST /v1/numbers/{id}/pairing.
  2. Se vier status: "connected", acabou.
  3. Exiba o qr.code ao operador.
  4. Repita a chamada a cada ~20 s e substitua a imagem, enquanto ninguém escanear.
  5. Pare quando chegar connection.updated com state: "connected", ou quando a chamada devolver connected.

Encerrar a sessão

DELETE /v1/numbers/{id}/session

bash
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

bash
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.

Presença é efêmera e não é enfileirada

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:

200 OK — trecho
{
  "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"
    }
  ]
}
CampoO que decide na sua interface
deliveryReceipts none · delivered · read — até onde vão as confirmações. Com none, sent é o estado final de sucesso.
midiaTipos de mídia aceitos por este canal.
janelaRespostaSe o canal exige que o contato tenha falado primeiro.
templateSe o canal exige template pré-aprovado.
audioPttSe aceita áudio como nota de voz.
presenceSe 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.