Instâncias e pareamento
Uma instância é um número de WhatsApp conectado ao Recadu como aparelho vinculado. O número continua no celular; o Recadu ocupa uma das 4 vagas de "Aparelhos conectados" e aparece lá como Recadu.
Criar
curl -X POST https://api.recadu.com.br/v1/instances \
-H "Authorization: Bearer $GW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "loja-centro", "interactive_mode": "native+text"}'
| Campo | ||
|---|---|---|
name |
obrigatório | Único na conta |
kind |
web (padrão) ou sandbox |
sandbox: veja abaixo |
interactive_mode |
native+text (padrão), native ou text |
Como botões e listas saem: veja interativos |
O número de instâncias depende do plano; acima dele, 409 instance-limit-reached.
Parear
Por QR
curl -X POST https://api.recadu.com.br/v1/instances/ins_.../pairing \
-H "Authorization: Bearer $GW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"method": "qr"}'
{
"instance_id": "ins_...",
"state": "pairing",
"qr": {
"code": "2@AbC...",
"expires_in_s": 20,
"image": "data:image/png;base64,iVBORw0..."
}
}
qr.image vai direto num <img src>. O WhatsApp troca o QR a cada ~20 s: para mostrar sempre o atual, use o stream (abaixo) ou consulte GET /v1/instances/{id}/pairing de novo.
No celular: WhatsApp → Configurações → Aparelhos conectados → Conectar um aparelho, e aponte para o QR.
Por código
Quando não dá para ler o QR (o celular é o mesmo aparelho que mostra a tela, por exemplo):
curl -X POST https://api.recadu.com.br/v1/instances/ins_.../pairing \
-H "Authorization: Bearer $GW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"method": "code", "phone": "5537999990000"}'
# {"state": "pairing", "pairing_code": "ABCD1234", ...}
No celular: Aparelhos conectados → Conectar um aparelho → Conectar com número de telefone e digite o código.
Acompanhar ao vivo (SSE)
curl -N https://api.recadu.com.br/v1/instances/ins_.../pairing/stream \
-H "Authorization: Bearer $GW_API_KEY"
event: qr
data: {"code": "2@...", "expires_in_s": 20, "image": "data:image/png;base64,..."}
event: paired
data: {...}
event: connected
data: {...}
O stream manda um qr a cada troca e termina no connected. Linhas : ping a cada 15 s mantêm a conexão aberta. No navegador, EventSource não manda cabeçalhos: faça o stream passar pelo seu servidor, que acrescenta a chave.
Instância já pareada responde 409 already-paired: desconecte antes (POST .../logout).
Estados
state |
Significa | O que fazer |
|---|---|---|
pending_pair |
Criada, nunca pareada (ou pareamento desfeito) | Parear |
connecting |
Conectando ou reconectando | Esperar. Se durar, o celular provavelmente está sem internet |
connected |
Pronta para enviar e receber | — |
disconnected |
Caiu (internet, WhatsApp fora) | Reconecta sozinha. POST .../restart força |
logged_out |
O aparelho foi desconectado no celular | Parear de novo |
banned |
O WhatsApp bloqueou o número | Não há como reverter pelo Recadu |
GET /v1/instances/{id} traz o state gravado e, em live, o estado consultado agora na conexão. Mudanças também chegam por webhook (instance.connected, instance.disconnected...).
Mensagens enviadas enquanto a instância está fora ficam na fila e saem quando ela volta, até 15 minutos; depois falham com expired.
Outras operações
| Rota | Faz |
|---|---|
PATCH /v1/instances/{id} |
Muda name, interactive_mode ou a policy (políticas) |
POST /v1/instances/{id}/restart |
Reconecta ao WhatsApp |
POST /v1/instances/{id}/logout |
Desconecta o aparelho (o número sai do Recadu; precisa parear de novo) |
DELETE /v1/instances/{id} |
Desconecta e remove a instância |
GET /v1/instances/{id}/contacts/{phone} |
Confere se o número tem WhatsApp: {"exists": true, "jid": "...", "phone": "..."} |
POST /v1/instances/{id}/chats/{chat}/presence |
Mostra "digitando" (typing), "gravando" (recording) ou para (paused) |
POST /v1/instances/{id}/chats/{chat}/read |
Marca mensagens recebidas como lidas (wa_message_ids) |
GET /v1/instances/{id}/health |
Saúde do número |
GET /v1/instances/{id}/availability?month=AAAA-MM |
Disponibilidade |
Sandbox
Uma instância sandbox serve para integrar e testar sem celular e sem risco para um número de verdade:
- conecta sozinha ao parear (QR ou código, nada a ler);
- aceita envios de todos os tipos e devolve os status
sent,deliverederead, sem mandar nada ao WhatsApp; - aplica as políticas e dispara os webhooks de verdade, com os mesmos formatos de produção;
- não conta no limite do plano (até 3 por conta).
curl -X POST https://api.recadu.com.br/v1/instances \
-H "Authorization: Bearer $GW_API_KEY" -H "Content-Type: application/json" \
-d '{"name": "teste-integracao", "kind": "sandbox"}'
Para simular o contato respondendo:
# mensagem de texto recebida -> message.received
curl -X POST https://api.recadu.com.br/v1/instances/ins_.../sandbox/inbound \
-H "Authorization: Bearer $GW_API_KEY" -H "Content-Type: application/json" \
-d '{"from": "5537999990000", "text": "Oi, quero fazer um pedido"}'
# clique num botão -> message.interactive_reply
curl -X POST https://api.recadu.com.br/v1/instances/ins_.../sandbox/inbound \
-H "Authorization: Bearer $GW_API_KEY" -H "Content-Type: application/json" \
-d '{"from": "5537999990000", "text": "Confirmar", "reply": {"option_id": "confirmar", "label": "Confirmar", "source": "native_flow"}}'
text é sempre obrigatório (no clique, é o texto que o contato vê). reply.source pode ser native_flow, button, list ou poll. Para responder a uma mensagem específica, mande reply.in_reply_to_wa_message_id com o wa_message_id dela. Para simular uma resposta citando uma mensagem, use quoted_wa_message_id. Mandar "2" em text depois de um menu numerado também vira message.interactive_reply, como no WhatsApp de verdade.
Simular numa instância web responde 409 not-sandbox.