Referência da API

Integre WhatsApp ao seu sistema

Crie sessões, autentique com QR e envie mensagens (texto, imagem, áudio, documento e contato) usando a chave wsak_…. Documentação pública, sem precisar estar logado.

Base URLhttps://workerapi.bemmelhor.com.br/api
  • 18 rotas HTTP
  • 5 tipos de mensagem
  • até 60 requisições por minuto

Visão geral

Use esta API a partir do seu backend. Com a chave você gerencia conexões WhatsApp, templates, listas CSV, campanhas (progresso, vistas e respostas), webhooks e mensagens avulsas. O limite de sessões da conta só o admin global define.

1
Sessão + template + CSV

Pareie em /v1/sessions, monte o template e faça upload da lista em /v1/csv.

2
Dispare a campanha

POST /v1/campaigns com workerSessionId (não o UUID), template e CSV.

3
Acompanhe

Progresso em GET /v1/campaigns/:id; destinatários, vistas e respostas em /recipients e /conversations.

Rotas HTTP

  • GET/v1/sessionsListar conexões
  • GET/v1/sessions/quotaQuota de sessões
  • POST/v1/sessionsCriar conexão
  • GET/v1/sessions/:idDetalhe sessão
  • GET/v1/sessions/:id/webhooksWebhooks
  • POST/v1/templates/mediaUpload mídia
  • GET/v1/templatesTemplates
  • POST/v1/templatesCriar template
  • GET/v1/csvListas CSV
  • POST/v1/csvUpload CSV
  • GET/v1/campaignsCampanhas
  • POST/v1/campaignsCriar campanha
  • GET/v1/campaigns/:idProgresso
  • GET/v1/campaigns/:id/recipientsDestinatários
  • GET/v1/campaigns/:id/conversationsConversas
  • GET/v1/campaigns/analyticsAnalytics
  • POST/v1/messagesMensagem avulsa
  • GET/v1/usageConsumo
Exemplo rápido
# 1. Quota
curl -sS "$API_BASE/v1/sessions/quota" -H "Authorization: Bearer $API_KEY"

# 2. Criar sessão
curl -sS -X POST "$API_BASE/v1/sessions" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"label":"API","sessionSuffix":"loja-01"}'

# 3. Polling do QR
curl -sS "$API_BASE/v1/sessions/$SESSION_ID/qrcode" \
  -H "Authorization: Bearer $API_KEY"

# 4. Enviar texto
curl -sS -X POST "$API_BASE/v1/messages" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-1" \
  -d '{"sessionId":"'"$SESSION_ID"'","to":"5511999999999","type":"text","text":"Olá!"}'

Autenticação

Toda chamada leva o header Authorization: Bearer wsak_… Crie a chave em Conta, API no painel: o token completo só aparece uma vez, e cada chave aceita 60 requisições por minuto. A validade vai de 1 dia até 10 anos, ou sem expiração, que só para quando você revogar. Use só em servidores confiáveis, nunca em app ou frontend público.

Header
Authorization: Bearer wsak_SEU_TOKEN
Variáveis
export API_BASE="https://workerapi.bemmelhor.com.br/api"
export API_KEY="wsak_SEU_TOKEN"

Segurança

Nunca use a chave em apps públicos ou frontends. Revogue em caso de vazamento. Limite: 60 requisições por minuto por chave.

Quota de sessões

O campo maxWhatsappSessions é definido só pelo admin global. A API mostra quantos slots restam; a chave não aumenta esse limite.

Quota
{
  "maxWhatsappSessions": 3,
  "whatsappSessionCount": 1,
  "whatsappSessionsRemaining": 2
}

Sessões

Gerencie conexões WhatsApp: criar, listar, editar label, ler QR, reconectar e remover. O limite de sessões vem da conta.

GET/v1/sessions

Listar conexões

Lista todas as conexões da conta e a quota de slots.

  • Use o campo id (UUID) em POST /v1/messages, não o workerSessionId
  • Só envie quando connected e canSend forem true
curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/sessions" \
  -H "Authorization: Bearer $API_KEY"
Resposta
{
  "items": [{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "label": "Atendimento",
  "workerSessionId": "user_xxx_loja",
  "connected": true,
  "canSend": true,
  "phoneNumber": "5511999999999",
  "lifecycle": "open",
  "createdAt": "2026-08-01T12:00:00.000Z",
  "qr": null,
  "passkey": null
}],
  "quota": {
  "maxWhatsappSessions": 3,
  "whatsappSessionCount": 1,
  "whatsappSessionsRemaining": 2
}
}
GET/v1/sessions/quota

Consultar quota

Retorna só o resumo de slots. Limite configurado pelo admin global.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/sessions/quota" \
  -H "Authorization: Bearer $API_KEY"
Resposta
{
  "maxWhatsappSessions": 3,
  "whatsappSessionCount": 1,
  "whatsappSessionsRemaining": 2
}
POST/v1/sessions

Criar conexão

Cria a sessão no worker e inicia o pareamento. Resposta 201. Se não houver slot, retorna 409.

Campos

  • labelstringNome amigável (1 a 80 caracteres). Opcional.
  • sessionSuffixstringSufixo do ID no worker. Letras, números, _ e - (1 a 48). Opcional.
curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/sessions" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "label": "Atendimento",
  "sessionSuffix": "loja-01"
}'
Resposta
{
  "session": {
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "label": "Atendimento",
  "workerSessionId": "user_xxx_loja-01",
  "connected": false,
  "canSend": false,
  "phoneNumber": null,
  "lifecycle": "connecting",
  "createdAt": "2026-08-01T12:00:00.000Z",
  "qr": {
    "qr": "2@…",
    "qrDataUrl": "data:image/png;base64,…"
  },
  "passkey": null
},
  "quota": {
    "maxWhatsappSessions": 3,
    "whatsappSessionCount": 2,
    "whatsappSessionsRemaining": 1
  }
}
GET/v1/sessions/:id

Detalhe da conexão

Retorna status, telefone, QR (se pendente), passkey e quota.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/sessions/$SESSION_ID" \
  -H "Authorization: Bearer $API_KEY"
Resposta
{
  "session": {
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "label": "Atendimento",
  "workerSessionId": "user_xxx_loja-01",
  "connected": false,
  "canSend": false,
  "phoneNumber": null,
  "lifecycle": "connecting",
  "createdAt": "2026-08-01T12:00:00.000Z",
  "qr": {
    "qr": "2@…",
    "qrDataUrl": "data:image/png;base64,…"
  },
  "passkey": null
},
  "quota": {
  "maxWhatsappSessions": 3,
  "whatsappSessionCount": 1,
  "whatsappSessionsRemaining": 2
}
}
PATCH/v1/sessions/:id

Editar conexão

Atualiza o label. Não altera maxWhatsappSessions.

Campos

  • labelobrigatóriostring | nullNovo nome, ou null para limpar.
curl
curl -sS -X PATCH "https://workerapi.bemmelhor.com.br/api/v1/sessions/$SESSION_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "label": "Novo nome" }'
Resposta
{
  "session": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "label": "Novo nome",
    "workerSessionId": "user_xxx_loja",
    "connected": true,
    "canSend": true,
    "phoneNumber": "5511999999999",
    "lifecycle": "open",
    "createdAt": "2026-08-01T12:00:00.000Z",
    "qr": null,
    "passkey": null
  },
  "quota": {
  "maxWhatsappSessions": 3,
  "whatsappSessionCount": 1,
  "whatsappSessionsRemaining": 2
}
}
GET/v1/sessions/:id/qrcode

QR code

Retorna a string do QR e a imagem em Base64 para exibir no seu sistema.

  • Faça polling a cada 2 a 5 segundos até connected: true
  • Use qrDataUrl em um <img src="…">
  • Depois de parear, qr e qrDataUrl podem vir null
curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/sessions/$SESSION_ID/qrcode" \
  -H "Authorization: Bearer $API_KEY"
Resposta
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "workerSessionId": "user_xxx_loja-01",
  "qr": "2@…",
  "qrDataUrl": "data:image/png;base64,…"
}
POST/v1/sessions/:id/reconnect

Reconectar

Reabre a conexão. Com fresh: true força novo QR (credenciais antigas removidas quando aplicável).

Campos

  • freshbooleanSe true, força novo pareamento. Opcional (padrão false).
curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/sessions/$SESSION_ID/reconnect" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "fresh": true }'
Resposta
{
  "session": {
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "label": "Atendimento",
  "workerSessionId": "user_xxx_loja-01",
  "connected": false,
  "canSend": false,
  "phoneNumber": null,
  "lifecycle": "connecting",
  "createdAt": "2026-08-01T12:00:00.000Z",
  "qr": {
    "qr": "2@…",
    "qrDataUrl": "data:image/png;base64,…"
  },
  "passkey": null
},
  "quota": {
  "maxWhatsappSessions": 3,
  "whatsappSessionCount": 1,
  "whatsappSessionsRemaining": 2
}
}
DELETE/v1/sessions/:id

Remover conexão

Remove a sessão. Precisa estar desconectada. Se ainda estiver connected, retorna 409.

curl
curl -sS -X DELETE "https://workerapi.bemmelhor.com.br/api/v1/sessions/$SESSION_ID" \
  -H "Authorization: Bearer $API_KEY"
Resposta
{
  "ok": true,
  "quota": {
    "maxWhatsappSessions": 3,
    "whatsappSessionCount": 1,
    "whatsappSessionsRemaining": 2
  }
}

Webhooks

Registre URLs HTTPS e escolha, por endpoint, quais eventos quer receber. Só o que estiver em events é entregue. Eventos disponíveis: whatsapp.message.received, whatsapp.message.sent, whatsapp.message.delivered, whatsapp.message.read, whatsapp.message.failed, whatsapp.presence.typing, whatsapp.call.received, whatsapp.session.connected e whatsapp.session.disconnected. Máximo de 10 webhooks por sessão, e o secret completo só aparece na criação.

Entrega

O Worker Send faz POST JSON na sua URL com o header X-Webhook-Signature: sha256=<hmac> (HMAC-SHA256 do body com o secret). Eventos: whatsapp.message.received e whatsapp.call.received. Até 3 tentativas com backoff.

GET/v1/sessions/:id/webhooks

Listar webhooks

Lista os webhooks da conexão e o limite por sessão.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/sessions/$SESSION_ID/webhooks" \
  -H "Authorization: Bearer $API_KEY"
Resposta
{
  "items": [{
  "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "whatsappSessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "label": "CRM",
  "url": "https://exemplo.com/hooks/whatsapp",
  "isActive": true,
  "events": ["whatsapp.message.received", "whatsapp.message.read"],
  "secretPreview": "••••a1b2",
  "createdAt": "2026-08-01T12:00:00.000Z",
  "updatedAt": "2026-08-01T12:00:00.000Z"
}],
  "limit": 10,
  "count": 1,
  "remaining": 9
}
POST/v1/sessions/:id/webhooks

Criar webhook

Cadastra uma URL de destino. Resposta 201. O campo secret só vem nesta resposta; guarde-o para validar a assinatura HMAC.

Campos

  • urlobrigatóriourlHTTPS em produção. Hosts privados/localhost são bloqueados.
  • labelstringNome amigável (1 a 80). Opcional.
  • eventsstring[]Eventos assinados. Omitido, assina todos. Pelo menos um é obrigatório quando informado.
  • Máximo 10 webhooks por sessão
  • url e secret não podem ser alterados depois (recrie o webhook se precisar)
  • Cada POST leva X-Webhook-Event com o nome do evento e X-Webhook-Signature com o HMAC do corpo
curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/sessions/$SESSION_ID/webhooks" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://exemplo.com/hooks/whatsapp",
  "label": "CRM",
  "events": ["whatsapp.message.received", "whatsapp.message.read"]
}'
Resposta
{
  "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "whatsappSessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "label": "CRM",
  "url": "https://exemplo.com/hooks/whatsapp",
  "isActive": true,
  "events": ["whatsapp.message.received", "whatsapp.message.read"],
  "secretPreview": "••••a1b2",
  "secret": "a1b2c3d4e5f6…",
  "createdAt": "2026-08-01T12:00:00.000Z",
  "updatedAt": "2026-08-01T12:00:00.000Z"
}
PATCH/v1/sessions/:id/webhooks/:webhookId

Editar webhook

Atualiza label, isActive e a lista de eventos. Não altera url nem secret.

Campos

  • labelstring | nullNovo nome, ou null para limpar.
  • isActivebooleanPausa ou reativa entregas.
  • eventsstring[]Substitui a assinatura inteira. Mande a lista completa que deseja manter.
  • Informe ao menos um campo
curl
curl -sS -X PATCH "https://workerapi.bemmelhor.com.br/api/v1/sessions/$SESSION_ID/webhooks/$WEBHOOK_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "label": "Novo nome",
  "isActive": false,
  "events": ["whatsapp.call.received"]
}'
Resposta
{
  "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "whatsappSessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "label": "CRM",
  "url": "https://exemplo.com/hooks/whatsapp",
  "isActive": true,
  "events": ["whatsapp.message.received", "whatsapp.message.read"],
  "secretPreview": "••••a1b2",
  "createdAt": "2026-08-01T12:00:00.000Z",
  "updatedAt": "2026-08-01T12:00:00.000Z"
}
DELETE/v1/sessions/:id/webhooks/:webhookId

Remover webhook

Remove o webhook da conexão.

curl
curl -sS -X DELETE "https://workerapi.bemmelhor.com.br/api/v1/sessions/$SESSION_ID/webhooks/$WEBHOOK_ID" \
  -H "Authorization: Bearer $API_KEY"
Resposta
{ "ok": true }

Um único endpoint POST /v1/messages. O campo type define o formato (text, image, audio, document, contact). Cada envio bem sucedido consome 1 unidade do plano. O header Idempotency-Key (opcional, até 128 caracteres) evita cobrança dupla em retries.

POST/v1/messagestext

Texto

Mensagem de texto (até 4096 caracteres).

Campos

  • sessionIdobrigatóriouuidID da conexão (GET /v1/sessions).
  • toobrigatóriostringTelefone com DDI, só dígitos.
  • typeobrigatório"text"Tipo da mensagem.
  • textobrigatóriostringConteúdo (máx. 4096).
  • Header opcional Idempotency-Key (até 128 caracteres)
  • Retry com a mesma chave devolve duplicate: true sem nova cobrança
curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/messages" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Idempotency-Key: pedido-12345" \
  -H "Content-Type: application/json" \
  -d '{
  "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "to": "5511999999999",
  "type": "text",
  "text": "Olá! Seu pedido foi confirmado."
}'
Resposta
{
  "ok": true,
  "duplicate": false,
  "messageId": "3EB0XXXXXXXXXXXX",
  "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "usage": {
    "used": 121,
    "limit": 5000,
    "remaining": 4879
  }
}
POST/v1/messagesimage

Imagem

Envia imagem por URL HTTPS. caption é opcional.

Campos

  • sessionIdobrigatóriouuidID da conexão.
  • toobrigatóriostringTelefone com DDI, só dígitos.
  • typeobrigatório"image"Tipo da mensagem.
  • mediaUrlobrigatóriourlURL HTTPS acessível pelo backend.
  • mimeTypestringEx.: image/jpeg, image/png, image/webp.
  • captionstringLegenda (máx. 1024). Opcional.
curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/messages" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "to": "5511999999999",
  "type": "image",
  "mediaUrl": "https://exemplo.com/foto.jpg",
  "mimeType": "image/jpeg",
  "caption": "Legenda opcional"
}'
Resposta
{
  "ok": true,
  "duplicate": false,
  "messageId": "3EB0XXXXXXXXXXXX",
  "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "usage": {
    "used": 121,
    "limit": 5000,
    "remaining": 4879
  }
}
POST/v1/messagesaudio

Áudio

Envia áudio por URL HTTPS (ogg, mp3, etc.).

Campos

  • sessionIdobrigatóriouuidID da conexão.
  • toobrigatóriostringTelefone com DDI, só dígitos.
  • typeobrigatório"audio"Tipo da mensagem.
  • mediaUrlobrigatóriourlURL HTTPS acessível pelo backend.
  • mimeTypestringEx.: audio/ogg, audio/mpeg.
curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/messages" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "to": "5511999999999",
  "type": "audio",
  "mediaUrl": "https://exemplo.com/audio.ogg",
  "mimeType": "audio/ogg"
}'
Resposta
{
  "ok": true,
  "duplicate": false,
  "messageId": "3EB0XXXXXXXXXXXX",
  "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "usage": {
    "used": 121,
    "limit": 5000,
    "remaining": 4879
  }
}
POST/v1/messagesdocument

Documento

Envia arquivo (PDF etc.). filename é obrigatório.

Campos

  • sessionIdobrigatóriouuidID da conexão.
  • toobrigatóriostringTelefone com DDI, só dígitos.
  • typeobrigatório"document"Tipo da mensagem.
  • mediaUrlobrigatóriourlURL HTTPS acessível pelo backend.
  • filenameobrigatóriostringNome exibido no WhatsApp.
  • mimeTypestringEx.: application/pdf.
  • captionstringLegenda opcional.
curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/messages" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "to": "5511999999999",
  "type": "document",
  "mediaUrl": "https://exemplo.com/contrato.pdf",
  "mimeType": "application/pdf",
  "filename": "contrato.pdf",
  "caption": "Segue o PDF"
}'
Resposta
{
  "ok": true,
  "duplicate": false,
  "messageId": "3EB0XXXXXXXXXXXX",
  "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "usage": {
    "used": 121,
    "limit": 5000,
    "remaining": 4879
  }
}
POST/v1/messagescontact

Contato (vCard)

Envia um cartão de contato. displayName e phone são obrigatórios.

Campos

  • sessionIdobrigatóriouuidID da conexão.
  • toobrigatóriostringDestinatário (DDI, só dígitos).
  • typeobrigatório"contact"Tipo da mensagem.
  • contact.displayNameobrigatóriostringNome no cartão.
  • contact.phoneobrigatóriostringTelefone do contato.
  • contact.firstNamestringOpcional.
  • contact.lastNamestringOpcional.
  • contact.orgstringOpcional.
  • contact.emailstringOpcional.
  • contact.titlestringOpcional.
  • contact.photoUrlurlFoto HTTPS opcional.
curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/messages" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "to": "5511999999999",
  "type": "contact",
  "contact": {
    "displayName": "João Silva",
    "phone": "5511888888888",
    "firstName": "João",
    "lastName": "Silva",
    "org": "Empresa Ltda",
    "email": "joao@empresa.com",
    "title": "Gerente",
    "photoUrl": "https://exemplo.com/foto-contato.jpg"
  }
}'
Resposta
{
  "ok": true,
  "duplicate": false,
  "messageId": "3EB0XXXXXXXXXXXX",
  "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "usage": {
    "used": 121,
    "limit": 5000,
    "remaining": 4879
  }
}

Templates

Monte o conteúdo da campanha com steps (TEXT, IMAGE, AUDIO, DOCUMENT, CONTACT). Variáveis: {{nome_var}}.

POST/v1/templates/media

Upload de mídia

Multipart field file. Query opcional kind=image|audio|document|video.

  • Use curl -F "file=@./foto.jpg"
  • O id retornado vira mediaId no step
curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/templates/media" \
  -H "Authorization: Bearer $API_KEY"
GET/v1/templates

Listar templates

Lista templates da conta.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/templates" \
  -H "Authorization: Bearer $API_KEY"
POST/v1/templates

Criar template

Cria template com steps (1 a 20).

Campos

  • nameobrigatóriostringNome (máx. 120).
  • stepsarraySteps TEXT/IMAGE/AUDIO/DOCUMENT/CONTACT.
curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/templates" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Boas-vindas",
  "steps": [
    { "type": "TEXT", "body": "Olá {{nome}}! Pedido {{pedido}}." },
    { "type": "IMAGE", "mediaId": "UUID_DA_MIDIA", "caption": "Comprovante" }
  ]
}'
GET/v1/templates/:id

Detalhe do template

Retorna steps e variableKeys.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/templates/$TEMPLATE_ID" \
  -H "Authorization: Bearer $API_KEY"
PATCH/v1/templates/:id

Editar template

Atualiza name e/ou steps.

curl
curl -sS -X PATCH "https://workerapi.bemmelhor.com.br/api/v1/templates/$TEMPLATE_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Novo nome" }'
DELETE/v1/templates/:id

Remover template

Remove o template da conta.

curl
curl -sS -X DELETE "https://workerapi.bemmelhor.com.br/api/v1/templates/$TEMPLATE_ID" \
  -H "Authorization: Bearer $API_KEY"

CSV / listas

Upload da planilha de destinatários usada em POST /v1/campaigns.

GET/v1/csv

Listar uploads

Lista CSVs/XLSX salvos.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/csv" \
  -H "Authorization: Bearer $API_KEY"
POST/v1/csv/inspect

Inspecionar arquivo

Lê abas/headers sem salvar. Multipart file.

curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/csv/inspect" \
  -H "Authorization: Bearer $API_KEY"
POST/v1/csv

Upload de lista

Multipart file. Campo sheet opcional (XLSX).

  • Máx. 2 MB
  • Anote o id retornado como csvUploadId
curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/csv" \
  -H "Authorization: Bearer $API_KEY"
GET/v1/csv/:id/preview

Preview

Headers e até 30 linhas.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/csv/$CSV_ID/preview" \
  -H "Authorization: Bearer $API_KEY"
GET/v1/csv/:id

Detalhe

Metadados e linhas do upload.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/csv/$CSV_ID" \
  -H "Authorization: Bearer $API_KEY"
PATCH/v1/csv/:id

Editar linhas

Atualiza o conteúdo da lista.

curl
curl -sS -X PATCH "https://workerapi.bemmelhor.com.br/api/v1/csv/$CSV_ID" \
  -H "Authorization: Bearer $API_KEY"
DELETE/v1/csv/:id

Remover lista

Remove o upload.

curl
curl -sS -X DELETE "https://workerapi.bemmelhor.com.br/api/v1/csv/$CSV_ID" \
  -H "Authorization: Bearer $API_KEY"

Campanhas

Criar disparos, acompanhar progresso, vistas (SEEN), respostas (REPLIED), conversas e analytics. Use workerSessionId (não o UUID) ao criar.

Progresso, vistas e respostas

progressPercent e contadores no detalhe da campanha. Vistas = SEEN (READ/PLAYED). Respostas = inbound + hasReplied. Filtre recipients com engagement=replied|seen|engaged.

GET/v1/campaigns

Listar campanhas

Lista recente de campanhas da conta.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/campaigns" \
  -H "Authorization: Bearer $API_KEY"
GET/v1/campaigns/analytics

Analytics

Métricas agregadas: sent, delivered, seen, replied e taxas. Query days ou from/to.

  • Ex.: ?days=30
curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/campaigns/analytics" \
  -H "Authorization: Bearer $API_KEY"
POST/v1/campaigns

Criar e iniciar

Cria a campanha a partir de template + CSV + sessão. startMode: now | scheduled | distributed.

Campos

  • workerSessionIdobrigatóriostringID do worker da conexão usada no disparo.
  • templateIdobrigatóriouuidTemplate.
  • csvUploadIdobrigatóriouuidLista CSV.
  • delayMsobrigatórionumberIntervalo mínimo 1000 ms.
  • phoneColumnobrigatóriostringColuna do telefone no CSV.
  • Não use o UUID id da sessão; use workerSessionId
  • Progresso: poll GET /v1/campaigns/:id
curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/campaigns" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Campanha agosto",
  "templateId": "UUID_TEMPLATE",
  "csvUploadId": "UUID_CSV",
  "workerSessionId": "user_xxx_loja",
  "delayMs": 3000,
  "phoneColumn": "telefone",
  "variableMapping": { "nome": "nome", "pedido": "pedido_id" },
  "startMode": "now"
}'
GET/v1/campaigns/:id

Detalhe e progresso

Status, contadores, progressPercent, pendingRecipients, estimatedRemainingMs e senderSessions.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID" \
  -H "Authorization: Bearer $API_KEY"
Resposta
{
  "id": "UUID_CAMPANHA",
  "name": "Campanha agosto",
  "status": "RUNNING",
  "totalRecipients": 1000,
  "sentCount": 420,
  "errorCount": 3,
  "skippedCount": 1,
  "progressPercent": 42.4,
  "pendingRecipients": 576,
  "estimatedRemainingMs": 1728000
}
POST/v1/campaigns/:id/launch

Disparar

Tira a campanha do rascunho e enfileira os envios. Use quando ela foi criada sem startAt.

curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID/launch" \
  -H "Authorization: Bearer $API_KEY"
POST/v1/campaigns/:id/pause

Pausar

Interrompe o disparo. Os pendentes ficam na fila até você retomar.

curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID/pause" \
  -H "Authorization: Bearer $API_KEY"
POST/v1/campaigns/:id/resume

Retomar

Retoma campanha pausada.

curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID/resume" \
  -H "Authorization: Bearer $API_KEY"
POST/v1/campaigns/:id/cancel

Cancelar

Cancela a campanha.

curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID/cancel" \
  -H "Authorization: Bearer $API_KEY"
POST/v1/campaigns/:id/prune-pending

Descartar pendentes

Remove da fila os destinatários que ainda não receberam. Use antes de encerrar uma campanha que não vale mais a pena continuar.

curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID/prune-pending" \
  -H "Authorization: Bearer $API_KEY"
POST/v1/campaigns/:id/retry-failed

Reprocessar falhas

Recoloca na fila os destinatários com erro. Cada reenvio consome uma unidade do plano.

curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID/retry-failed" \
  -H "Authorization: Bearer $API_KEY"
DELETE/v1/campaigns/:id

Remover

Apaga a campanha.

curl
curl -sS -X DELETE "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID" \
  -H "Authorization: Bearer $API_KEY"
GET/v1/campaigns/:id/recipients

Destinatários

Lista paginada com status, deliveryStatus, hasReplied, lastReplyAt, lastSeenAt. Query: status, engagement, sort, page, limit.

  • engagement=replied|seen|engaged
curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID/recipients" \
  -H "Authorization: Bearer $API_KEY"
Resposta
{
  "items": [
    {
      "id": "UUID_RECIPIENT",
      "phone": "5511999999999",
      "status": "SENT",
      "deliveryStatus": "READ",
      "hasReplied": true,
      "lastReplyAt": "2026-08-01T13:00:00.000Z",
      "lastSeenAt": "2026-08-01T12:50:00.000Z",
      "previewText": "Olá João!…"
    }
  ],
  "total": 1000,
  "page": 1,
  "limit": 50
}
GET/v1/campaigns/:id/conversations

Conversas

Threads com reply/seen por destinatário.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID/conversations" \
  -H "Authorization: Bearer $API_KEY"
GET/v1/campaigns/:id/conversations/:recipientId/messages

Mensagens da conversa

Histórico inbound/outbound do destinatário.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID/conversations/$RECIPIENT_ID/messages" \
  -H "Authorization: Bearer $API_KEY"
POST/v1/campaigns/:id/conversations/:recipientId/messages

Responder manualmente

Envia texto na thread da campanha.

curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID/conversations/$RECIPIENT_ID/messages" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "text": "Obrigado pelo retorno!" }'
GET/v1/campaigns/notifications/summary

Resumo de alertas

Resumo de eventos REPLIED/SEEN da conta.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/campaigns/notifications/summary" \
  -H "Authorization: Bearer $API_KEY"
GET/v1/campaigns/notifications/events

Feed de eventos

Lista eventos. Query: campaignId, eventType, page, limit.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/campaigns/notifications/events" \
  -H "Authorization: Bearer $API_KEY"
GET/v1/campaigns/:id/notification-settings

Settings de alerta

Templates de notificação reply/seen. PATCH para atualizar.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID/notification-settings" \
  -H "Authorization: Bearer $API_KEY"
PATCH/v1/campaigns/:id/notification-settings

Editar settings de alerta

Define o texto do aviso de resposta e do aviso de leitura. Mande null em um deles para voltar ao texto padrão.

  • Cada template aceita até 1024 caracteres.
curl
curl -sS -X PATCH "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID/notification-settings" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "replyTemplate": "{{contato}} respondeu na campanha {{campanha}}",
  "seenTemplate": null
}'
GET/v1/campaigns/:id/notification-subscriptions

Assinaturas de alerta

Lista quem recebe os avisos desta campanha.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID/notification-subscriptions" \
  -H "Authorization: Bearer $API_KEY"
POST/v1/campaigns/:id/notification-subscriptions

Criar assinatura

Adiciona um número que passa a receber os avisos da campanha.

Campos

  • phoneobrigatóriostringNúmero com DDI, 8 a 32 caracteres.
  • notifyOnReplybooleanAvisar quando o contato responder. Padrão true.
  • notifyOnSeenbooleanAvisar quando o contato ler. Padrão true.
  • Pelo menos um dos dois avisos precisa ficar ligado.
  • Um número repetido na mesma campanha devolve 409.
curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID/notification-subscriptions" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "phone": "5511999999999",
  "notifyOnReply": true,
  "notifyOnSeen": true
}'
PATCH/v1/campaigns/:id/notification-subscriptions/:subId

Editar assinatura

Altera os eventos que aquele número recebe ou desativa a assinatura.

curl
curl -sS -X PATCH "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID/notification-subscriptions/$SUB_ID" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "notifyOnSeen": true,
  "isActive": true
}'
DELETE/v1/campaigns/:id/notification-subscriptions/:subId

Remover assinatura

O número deixa de receber os avisos.

curl
curl -sS -X DELETE "https://workerapi.bemmelhor.com.br/api/v1/campaigns/$CAMPAIGN_ID/notification-subscriptions/$SUB_ID" \
  -H "Authorization: Bearer $API_KEY"

Canal oficial (Gupshup)

Os números oficiais conectados à Gupshup ficam disponíveis pela mesma chave wsak_, com envio de sessão, template aprovado, histórico e webhooks próprios. O que a tela faz, a API faz. Números ligados direto na Cloud API da Meta já entregam os mesmos eventos official.* nos seus webhooks, mas ainda são configurados só pelo painel: as rotas /v1 abaixo cobrem a Gupshup.

GET/v1/official-numbers

Listar números oficiais

Números da Gupshup ligados à conta, com o estado da credencial.

  • canSend falso significa credencial recusada pela Gupshup; revalide no painel
curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/official-numbers" \
  -H "Authorization: Bearer $API_KEY"
Resposta
{
  "items": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "label": "Comercial",
      "appName": "workersend",
      "phoneNumber": "5511988887777",
      "status": "ACTIVE",
      "canSend": true,
      "lastValidatedAt": "2026-09-04T12:00:00.000Z",
      "createdAt": "2026-08-20T10:00:00.000Z"
    }
  ],
  "count": 1
}
GET/v1/official-numbers/:id/account

Dados da WABA

Perfil comercial, recado, foto e dados da conta WhatsApp Business, como a Gupshup devolve.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/official-numbers/$SESSION_ID/account" \
  -H "Authorization: Bearer $API_KEY"
GET/v1/official-numbers/:id/templates

Templates na Gupshup

Templates do app, direto da Gupshup. Query templateStatus filtra por APPROVED, PENDING ou REJECTED.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/official-numbers/$SESSION_ID/templates" \
  -H "Authorization: Bearer $API_KEY"
POST/v1/official-numbers/:id/template-links

Sincronizar template local

Cria na Gupshup a versão oficial de um template do Worker Send, trocando {{variavel}} por {{1}}, {{2}} na ordem em que aparecem.

  • A aprovação é da Meta e costuma sair em até 24 horas
curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/official-numbers/$SESSION_ID/template-links" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "templateId": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
  "category": "MARKETING",
  "languageCode": "pt_BR"
}'
POST/v1/official-numbers/:id/messages

Mensagem de sessão

Texto ou mídia dentro da janela de 24 horas contada do último contato do cliente. Fora dela, a Meta exige template.

Campos

  • destinationobrigatóriostringTelefone com DDI.
  • typeobrigatórioenumtext, image, video, audio, document, sticker ou location.
  • textstringObrigatório quando type é text.
  • urlurlObrigatório para mídia. Precisa ser pública.
  • filenamestringObrigatório para document.
  • captionstringLegenda de imagem e vídeo.
  • latitudenumberCom longitude, obrigatório para location.
curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/official-numbers/$SESSION_ID/messages" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "destination": "5511999999999",
  "type": "text",
  "text": "Recebemos seu pedido, já estamos separando."
}'
POST/v1/official-numbers/:id/template-messages

Enviar template aprovado

Dispara um template já aprovado, com os parâmetros na ordem do corpo. Funciona fora da janela de 24 horas.

Campos

  • destinationobrigatóriostringTelefone com DDI.
  • templateIdobrigatóriostringId do template na Gupshup, não o id local.
  • paramsstring[]Valores de {{1}}, {{2}}… na ordem do corpo.
  • headerMessageobjectCabeçalho de mídia, quando o template tem header de imagem ou documento.
curl
curl -sS -X POST "https://workerapi.bemmelhor.com.br/api/v1/official-numbers/$SESSION_ID/template-messages" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "destination": "5511999999999",
  "templateId": "4dacef15-6c04-12db-b393-6190ac567eff",
  "params": ["João", "10432"]
}'
GET/v1/official-numbers/:id/messages

Histórico de envios

Últimos envios pelo número, com o status devolvido pelos callbacks.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/official-numbers/$SESSION_ID/messages" \
  -H "Authorization: Bearer $API_KEY"
GET/v1/official-numbers/:id/webhooks

Webhooks do número oficial

Mesma estrutura dos demais webhooks, com os eventos official.*. POST cria, PATCH edita a assinatura, DELETE remove.

  • Eventos: official.message.received, official.message.sent, official.message.delivered, official.message.read, official.message.failed, official.template.status, official.account.status e official.billing.event
  • O callback da Gupshup aponta uma vez para o Worker Send, e a distribuição para os seus endpoints sai daqui
curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/official-numbers/$SESSION_ID/webhooks" \
  -H "Authorization: Bearer $API_KEY"

Consumo

Acompanhe o uso de envios do ciclo atual do plano.

GET/v1/usage

Consultar consumo

Envios usados, limite, restantes e período do plano.

curl
curl -sS -X GET "https://workerapi.bemmelhor.com.br/api/v1/usage" \
  -H "Authorization: Bearer $API_KEY"
Resposta
{
  "periodStart": "2026-08-01T00:00:00.000Z",
  "periodEnd": "2026-09-01T00:00:00.000Z",
  "periodLabel": "ago/2026",
  "used": 120,
  "limit": 5000,
  "remaining": 4880,
  "unlimited": false
}

Códigos de erro

Todo erro volta em JSON com statusCode, message e error. Em falha de validação vem também issues, com o caminho de cada campo recusado.

401Token inválido, expirado ou revogado
403Conta inativa
400Validação, falha no envio ou quota de mensagens
409Limite de sessões, sessão não pronta ou ainda conectada ao remover
429Mais de 60 requisições por minuto na mesma chave

Pronto para integrar?

Gere sua chave e comece a enviar

Crie um token em Conta, API e use os endpoints desta página.