-
Notifications
You must be signed in to change notification settings - Fork 2
API e Webhooks
Guia completo para consumir a API REST e os endpoints de Webhook do Zyra.
No .env:
WA_API_ENABLED=true
WA_API_HOST=0.0.0.0
WA_API_PORT=3000
# opcional (recomendado em produção)
WA_API_KEY=sua-chave
# obrigatório para /webhooks/connections e /connections/:id/webhook/start
WA_WEBHOOK_SHARED_SECRET=segredo-hmac
# obrigatório para cadastro/entrega de webhooks de saída
# (lista CSV exata de URLs permitidas)
WA_WEBHOOK_ALLOWED_TARGETS=https://meu-sistema.com/webhook,https://hooks.exemplo.com/zyraBase URL local (exemplo): http://localhost:3000
- Rotas REST:
Authorization: Bearer <WA_API_KEY>quandoWA_API_KEYestiver configurada. - Exceção:
POST /webhooks/connectionsusa autenticação HMAC própria (não usa Bearer). - Dashboard (
/e/dashboard) é servido sem Bearer.
- Erros seguem formato:
{ "error": "mensagem" }- Sucesso retorna JSON do recurso, exceto endpoints
204 No Content.
-
created: criada, sem socket ativo. -
connecting: conectando. -
qr: aguardando leitura do QR. -
open: conectada/autenticada. -
closed: desconectada. -
error: falha de conexão.
Cria uma instância sem conectar.
Body:
{ "connectionId": "minha-sessao", "label": "Bot Suporte" }Respostas:
-
201: conexão criada. -
400:connectionId é obrigatório. -
409:connectionId já existe.
Lista conexões (runtime + fallback managed).
Respostas:
-
200: array de conexões.
Detalha uma conexão.
Respostas:
-
200: conexão encontrada. -
404:conexão não encontrada.
Atualiza label.
Body:
{ "label": "Novo nome" }Para limpar:
{ "label": null }Respostas:
-
200: conexão atualizada. -
404:conexão não encontrada.
Remove conexão.
Respostas:
-
204: removida. -
404:conexão não encontrada.
Alias: POST /connections/:id/start.
Inicia conexão/socket.
Respostas:
-
200: conexão emconnecting. -
404:conexão não encontrada. -
409:operação indisponível neste processo (WA_BOOTSTRAP_CONNECTIONS_ENABLED=false).
Desconecta.
Respostas:
-
200: status atualizado. -
404:conexão não encontrada. -
409: manager indisponível.
Alias: POST /connections/:id/reconnect.
Respostas:
-
200: status atualizado (normalmenteconnecting). -
404:conexão não encontrada. -
409: manager indisponível.
Resumo operacional (inclui visão admin).
Respostas:
-
200: status resumido. -
404:conexão não encontrada.
Retorna QR atual.
Respostas:
-
200:{ connectionId, qrCode, qrCodeAt }. -
404:conexão não encontradaouQR code não disponível.
Inicia pareamento remoto.
Respostas:
-
202: estado inicial (pending/qr_ready). -
409: manager indisponível.
Cancela pareamento remoto.
Respostas:
-
200: estado final do pairing. -
404:conexão não encontrada. -
409: manager indisponível.
Consulta estado do pairing.
Respostas:
-
200: incluistatus,qrCode,qrUpdatedAt,qrExpiresAt. -
404:conexão não encontrada. -
409: manager indisponível.
Cria/atualiza conexão e despacha comando start via webhook assinado interno.
Body:
{ "label": "Bot Principal" }Respostas:
-
200: comando aceito. -
502: falha ao acionar webhook de conexão. -
503:WA_WEBHOOK_SHARED_SECRETnão configurado.
Pré-condição: conexão deve estar open.
Body text:
{ "type": "text", "to": "5511999999999@s.whatsapp.net", "text": "Olá" }Body image|video|audio|document:
{
"type": "document",
"to": "5511999999999@s.whatsapp.net",
"url": "https://exemplo.com/arquivo.pdf",
"fileName": "arquivo.pdf",
"mimetype": "application/pdf"
}Respostas:
-
200: resposta bruta dosendMessage(Baileys). -
400: payload inválido/campos obrigatórios. -
404:conexão não encontrada. -
409: instância não conectada ou socket indisponível. -
500: falha ao enviar.
Pré-condição: conexão open.
Respostas:
-
200: mapa de grupos retornado porgroupFetchAllParticipating. -
404:conexão não encontrada. -
409: instância não conectada ou socket indisponível. -
500: falha ao buscar grupos.
Antes de criar webhooks, configure WA_WEBHOOK_ALLOWED_TARGETS com os destinos autorizados.
Sem isso, a API retorna erro: nenhum destino autorizado configurado. defina WA_WEBHOOK_ALLOWED_TARGETS.
Cria webhook de uma conexão.
Body:
{
"url": "https://meu-sistema.com/webhook",
"eventsFilter": ["messages", "connection.update"],
"secret": "segredo-opcional"
}eventsFilter aceita:
*- eventos diretos:
connection.update,messages.upsert,messages.update,messages.delete,message-receipt.update,messages.reaction,groups.upsert,groups.update,group-participants.update - grupos:
connection,messages,groups
Respostas:
-
201: webhook criado. -
400: body inválido,urlinválida,eventsFiltervazio ou URL não permitida. -
500: falha ao criar.
Lista webhooks da conexão.
Respostas:
-
200: array de webhooks.
Respostas:
-
200: webhook. -
404:webhook não encontrado.
Body parcial:
{
"url": "https://novo-endpoint.com/hook",
"eventsFilter": ["messages.upsert"],
"active": true,
"secret": null
}Respostas:
-
200: webhook atualizado. -
400: body/url inválido(a). -
404:webhook não encontrado.
Respostas:
-
204: removido. -
404:webhook não encontrado.
Lista histórico de entregas.
Respostas:
-
200: array de entregas. -
404:webhook não encontrado.
Força nova tentativa de entrega.
Respostas:
-
200: entrega atualizada. -
404: webhook ou entrega não encontrada. -
500: falha ao retentar.
Mesmo contrato dos webhooks por conexão, mas para todas as conexões:
GET /webhooksPOST /webhooksGET /webhooks/:webhookIdPATCH /webhooks/:webhookIdDELETE /webhooks/:webhookIdGET /webhooks/:webhookId/deliveriesPOST /webhooks/:webhookId/deliveries/:deliveryId/retry
Formato:
{
"event": "messages.upsert",
"connectionId": "minha-sessao",
"timestamp": 1780000000000,
"data": {}
}Headers de entrega:
content-type: application/jsonx-webhook-event: <nome-do-evento>x-webhook-delivery: <id-da-entrega>-
x-webhook-signature: sha256=<hmac>quandosecretfoi configurado no webhook.
Status de entrega persistido:
pendingdeliveredfaileddead_letter
Endpoint:
POST /webhooks/connections
Headers obrigatórios:
content-type: application/jsonx-zyra-timestampx-zyra-signaturex-zyra-delivery-id
Regra da assinatura:
- HMAC SHA-256 sobre
"<timestamp>.<rawBody>"usandoWA_WEBHOOK_SHARED_SECRET. - Aceita
x-zyra-signaturecom ou sem prefixosha256=.
Payload:
{
"event": "connection.command",
"version": "2026-05-27",
"command_id": "uuid",
"sent_at": "2026-05-30T16:00:00.000Z",
"connection": { "id": "minha-sessao", "display_name": "Bot X" },
"action": { "type": "start", "reason": "dashboard.qr" },
"options": { "force": false },
"metadata": { "source": "sistema-externo" }
}Ações válidas (action.type):
registerstartreconnectdisconnectpauseresumedelete_softdelete_hardsync_statuspairing_startpairing_cancel
Resposta de sucesso:
{
"ok": true,
"command_id": "uuid",
"connection_id": "minha-sessao",
"accepted": true,
"action": "start",
"current_state": "connecting",
"desired_state": "running"
}Regras importantes:
- Idempotência por
command_id(duplicado pode retornarduplicate: true). -
delete_hardexigeoptions.force=true. - Sem
WA_WEBHOOK_HARD_DELETE_TOKEN, também exige headerx-zyra-hard-delete-confirm=true. - Com
WA_WEBHOOK_HARD_DELETE_TOKEN, exigex-zyra-hard-delete-tokenigual ao token configurado.
Erros comuns:
-
400: payload/event/fields inválidos. -
401: headers de auth ausentes, timestamp inválido/fora da janela, assinatura inválida. -
405: método diferente dePOST. -
413: payload acima do limite. -
415: content-type inválido. -
422: ação inválida ou regra de hard delete não atendida. -
500: erro interno ao processar comando.
Retorna perfil e capacidades do processo:
-
profile:full,connections-only,api-webhook,stateless -
capabilities,api,webhook,process
Liveness simples do processo.
Resposta:
-
200:{ ok: true, live: true, now, uptime_sec }
Readiness (MySQL/Redis/control-plane).
Respostas:
-
200: pronto. -
503: dependência não pronta.
Resumo por conexão + contadores agregados (open, connecting, paused, error).
POST /connectionsPOST /connections/:id/connect- Poll em
GET /connections/:id/qraté vir200comqrCode - Poll em
GET /connections/:id/statusatéstatus=open POST /connections/:id/messages/send
BASE="http://localhost:3000"
TOKEN="sua-chave"
ID="sessao-demo"
curl -s -X POST "$BASE/connections" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"connectionId\":\"$ID\"}" | jq
curl -s -X POST "$BASE/connections/$ID/connect" \
-H "Authorization: Bearer $TOKEN" | jq
curl -s "$BASE/connections/$ID/qr" \
-H "Authorization: Bearer $TOKEN" | jqZyra Wiki • Última atualização: 17/05/2026
Home | Configuração | Comandos | Banco-de-Dados | Produção | Troubleshooting