Pular para o conteúdo
WbizTool

API v2 (beta)

Mensagens

Envie uma mensagem agora ou em um horário definido, para um número de telefone, um grupo de WhatsApp, um contato salvo ou um nome de usuário do Telegram. Envie a mesma mensagem para até 1.000 destinatários em uma única requisição, leia o histórico, acompanhe o status de uma mensagem e cancele-a enquanto ela espera.

OperaçãoEndpointPermissão
Enviar uma mensagemPOST /api/v2/messagesmessages:send
Enviar para vários destinatáriosPOST /api/v2/messages/batchmessages:send
Listar mensagensGET /api/v2/messagesmessages:read
Obter uma mensagemGET /api/v2/messages/{id}messages:read
Cancelar uma mensagemDELETE /api/v2/messages/{id}messages:send

Chaves, erros, Idempotency-Key e limites funcionam como descrito na visão geral da API v2. Para saber quando uma mensagem é enviada ou falha sem consultar periodicamente, adicione um endpoint de webhook.

Enviar uma mensagem#

POSThttps://wbiztool.com/api/v2/messages

Corpo: JSON (application/json)

A mensagem entra na fila e a resposta chega antes de ela sair, com HTTP 202 e a Message no status queued (ou scheduled, com um send_at no futuro). Acompanhe-a com Obter uma mensagem ou com um webhook.

curl -X POST https://wbiztool.com/api/v2/messages \
  -H "Authorization: Bearer $WBIZTOOL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1042-ready" \
  -d '{
    "from": 101,
    "to": { "phone": "+919876543210" },
    "text": "Hi Asha, your order #1042 is ready."
  }'

Resposta (202):

{
  "id": 9817263,
  "status": "queued",
  "from": { "id": 101, "phone": "919800000000", "platform": "whatsapp" },
  "to": { "phone": "+919876543210", "contact_id": 991 },
  "text": "Hi Asha, your order #1042 is ready.",
  "media": null,
  "send_at": null,
  "expires_at": null,
  "created_at": "2026-10-18T10:15:02.311Z",
  "sent_at": null,
  "error": null
}

Corpo

toobjectobrigatório

Quem recebe: exatamente um de phone, group, contact_id ou username. Veja Destinatários.

frominteger or nullObrigatório, a menos que o espaço de trabalho tenha um único número conectado

O id do número que envia, obtido em Listar números. Se for omitido, o único número conectado envia: um número de WhatsApp conectado é usado mesmo que uma conta do Telegram também esteja conectada, e uma conta do Telegram só quando nenhum número de WhatsApp está conectado. Um número desconectado é aceito: as mensagens dele esperam até ele se reconectar.

textstringObrigatório, a menos que media seja enviado

A mensagem, com até 3.000 caracteres. Com media, é a legenda e pode ser omitida. A formatação do WhatsApp funciona: *bold*, _italic_, ~strikethrough~. Em JSON, escreva as quebras de linha como \n.

mediaobject or nullopcional

Uma imagem ou um arquivo para enviar. Veja Mídia.

send_atstring or nullopcional

Enviar neste horário em vez de agora: ISO 8601 com o deslocamento, como 2026-10-20T09:30:00+05:30. Precisa estar no futuro. Veja Agendamento e expiração.

expires_atstring or nullopcional

Não enviar depois deste horário: a mensagem passa a expired. ISO 8601 com o deslocamento, no futuro e depois de send_at.

Cabeçalhos

Authorizationheaderobrigatório

Bearer wbz_live_…, uma chave com a permissão messages:send.

Idempotency-Keyheaderopcional

Qualquer string única, para que uma nova tentativa nunca envie uma segunda mensagem. Veja Idempotency-Key.

Erros ao enviar#

HTTPCódigoQuando
400validation_failedUm campo está faltando, tem o tipo errado ou é desconhecido; to não tem nenhum ou tem vários dos seus campos; media tem url e media_id juntos ou nenhum dos dois; expires_at não é depois de send_at
400text_requiredSem text e sem media
400text_too_longtext tem mais de 3.000 caracteres
400invalid_datetimesend_at ou expires_at não está em ISO 8601 com o deslocamento
402no_creditsO espaço de trabalho não tem mais mensagens no plano
403number_not_allowedA chave está limitada a outros números
403account_disabledA conta do proprietário do espaço de trabalho está desativada
422invalid_phoneto.phone não é um número de telefone no formato internacional com +
422invalid_usernameto.username não é um nome de usuário, link ou id tg: do Telegram
422username_needs_telegramto.username com um número de WhatsApp como from
422contact_not_foundNenhum contato com esse to.contact_id
422media_not_foundNenhum arquivo com esse media.media_id
422invalid_media_urlmedia.url não é um link público http(s)
422time_in_pastsend_at ou expires_at já passou
422number_not_foundfrom não é um número deste espaço de trabalho
422from_requiredSem from, e o espaço de trabalho não tem nenhum número conectado ou tem vários
422message_rejectedA mensagem não pôde entrar na fila; message diz por quê
429number_daily_cap_reachedO número enviou 1.000 mensagens nas últimas 24 horas

Um envio recusado não deixa nada para trás: nenhuma mensagem é guardada, então não há nada para cancelar. Os erros que podem acontecer em qualquer requisição (chaves, permissões, limites de requisições, Idempotency-Key) estão na página de erros.

Enviar para vários destinatários#

POSThttps://wbiztool.com/api/v2/messages/batch

Corpo: JSON (application/json)

Envia a mesma mensagem para até 1.000 destinatários. O corpo é o mesmo de Enviar uma mensagem, exceto que to é uma lista de destinatários.

  • Tudo ou nada. Todos os destinatários são verificados antes de qualquer coisa entrar na fila, e a lista inteira precisa caber nas mensagens restantes do plano e no espaço do número que envia para as próximas 24 horas. Se um destinatário estiver errado, nada entra na fila, e field indica qual, como to[3].phone.
  • O mesmo destinatário duas vezes recebe uma única mensagem.
  • A resposta é 202 com data: uma Message por destinatário, na ordem de to.
curl -X POST https://wbiztool.com/api/v2/messages/batch \
  -H "Authorization: Bearer $WBIZTOOL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: opening-hours-2026-10-20" \
  -d '{
    "from": 101,
    "to": [
      { "phone": "+919876543210" },
      { "phone": "+447700900123" },
      { "group": "Bakery staff" }
    ],
    "text": "We open at 10 tomorrow."
  }'

Resposta (202), uma Message por destinatário; a segunda e a terceira são iguais à primeira, com to igual a {"phone": "+447700900123", …} e {"group": "Bakery staff", …}:

{
  "data": [
    {
      "id": 9817264,
      "status": "queued",
      "from": { "id": 101, "phone": "919800000000", "platform": "whatsapp" },
      "to": { "phone": "+919876543210", "contact_id": 991 },
      "text": "We open at 10 tomorrow.",
      "media": null,
      "send_at": null,
      "expires_at": null,
      "created_at": "2026-10-19T16:02:40.118Z",
      "sent_at": null,
      "error": null
    }
  ]
}

Erros ao enviar um lote#

Os mesmos de quando você envia uma mensagem, com a posição do destinatário em field (to[0].phone), e também:

HTTPCódigoQuando
400too_many_recipientsto tem mais de 1.000 entradas
400validation_failedto está vazio ou não é uma lista
402no_creditsA lista não cabe nas mensagens restantes: requested e remaining dizem em quanto
429number_daily_cap_reachedA lista não cabe no espaço do número para as próximas 24 horas: requested e room dizem quantas

Listar mensagens#

GEThttps://wbiztool.com/api/v2/messages

As mensagens do espaço de trabalho dos últimos 90 dias, das mais recentes para as mais antigas, em páginas. Isso inclui as mensagens enviadas pelo painel, por campanhas, lembretes, integrações e pela API v1, não só as da API v2. Uma chave limitada a alguns números vê só as mensagens deles.

Parâmetros de consulta

numberintegeropcional

Só as mensagens deste id de número.

statusstringopcional

Só as mensagens com este status: queued, scheduled, sent, delivered, read, failed, cancelled ou expired.

sincestringopcional

Só as mensagens criadas neste horário ou depois dele (ISO 8601 com o deslocamento).

untilstringopcional

Só as mensagens criadas antes deste horário (ISO 8601 com o deslocamento).

limitintegeropcional

Mensagens por página, de 1 a 100 (padrão 25).

cursorstringopcional

O next_cursor da última página, com os mesmos filtros.

Os filtros se combinam. Em uma query string, escreva o + de um deslocamento como %2B (um + simples chega como espaço, que também é lido como +), ou use Z.

curl -G https://wbiztool.com/api/v2/messages \
  -H "Authorization: Bearer $WBIZTOOL_API_KEY" \
  --data-urlencode "status=failed" \
  --data-urlencode "since=2026-10-01T00:00:00+05:30" \
  --data-urlencode "limit=100"

A resposta é {"data": [Message, …], "next_cursor": "…" or null}.

Erros ao listar#

HTTPCódigoQuando
400validation_failednumber não é um id de número, status não é um dos status ou limit não está entre 1 e 100
400invalid_datetimesince ou until não está em ISO 8601 com o deslocamento
400invalid_cursorO cursor está danificado ou foi criado com outros filtros

Obter uma mensagem#

GEThttps://wbiztool.com/api/v2/messages/{id}

Uma mensagem e o status atual dela.

curl https://wbiztool.com/api/v2/messages/9817263 \
  -H "Authorization: Bearer $WBIZTOOL_API_KEY"

Resposta (200), uma mensagem que foi entregue:

{
  "id": 9817263,
  "status": "delivered",
  "from": { "id": 101, "phone": "919800000000", "platform": "whatsapp" },
  "to": { "phone": "+919876543210", "contact_id": 991 },
  "text": "Hi Asha, your order #1042 is ready.",
  "media": null,
  "send_at": null,
  "expires_at": null,
  "created_at": "2026-10-18T10:15:02.311Z",
  "sent_at": "2026-10-18T10:15:09.870Z",
  "error": null
}

Uma mensagem que não existe, pertence a outro espaço de trabalho ou (para uma chave limitada a alguns números) foi enviada de outro número responde 404 message_not_found.

Cancelar uma mensagem#

DELETEhttps://wbiztool.com/api/v2/messages/{id}

Cancela uma mensagem que ainda está em espera (queued ou scheduled), seja quem for que a criou. A resposta é 200 com a Message, agora no status cancelled. Um endpoint de webhook recebe message.cancelled.

Uma mensagem que já saiu não pode ser recolhida. Uma mensagem que o número que envia está pegando naquele exato momento ainda pode sair, então verifique o status dela depois, se isso for importante.

curl -X DELETE https://wbiztool.com/api/v2/messages/9817263 \
  -H "Authorization: Bearer $WBIZTOOL_API_KEY"

Erros ao cancelar#

HTTPCódigoQuando
404message_not_foundNenhuma mensagem assim para esta chave
409not_cancellableEla não está mais em espera; status no erro diz como ela está agora, como sent

O objeto Message#

Todas as operações desta página respondem com objetos Message, e os eventos de webhook trazem um em data.message.

CampoTipoDescrição
idintegerO id da mensagem. Use-o para obter ou cancelar a mensagem.
statusstringOnde ela está agora. Veja Status.
fromobjectO número que envia: id, phone (os dígitos com o código do país, sem +) e platform (whatsapp ou telegram).
toobjectO destinatário: phone (com +), group ou username, e contact_id, o contato salvo para o qual ela foi. Um número de telefone ou grupo que recebe uma mensagem pela primeira vez é salvo como contato. (contact_id só é null em uma mensagem de teste para um número que não está salvo.)
textstringO texto ou a legenda; "" quando não há nenhum.
mediaobject or nulltype (image ou file), url e file_name (null para imagens). A url pode ser um link que funciona por tempo limitado; não a guarde.
send_atstring or nullO horário para o qual ela está agendada, ou null para "agora".
expires_atstring or nullO horário depois do qual ela não é enviada, ou null.
created_atstringQuando ela foi criada.
sent_atstring or nullQuando ela saiu, depois que sai (sent, delivered ou read).
errorobject or nullEm uma mensagem failed ou expired, message diz por quê, como File exceeds WhatsApp size limit (16MB max). null nos outros casos.

Status#

StatusSignificado
queuedEsperando para sair.
scheduledEsperando o seu send_at.
sentEnviada do seu número (um tique no WhatsApp).
deliveredEntregue no celular do destinatário (dois tiques).
readLida pelo destinatário (tiques azuis).
failedNão pôde ser enviada; error.message diz por quê.
cancelledCancelada antes de sair: com Cancelar uma mensagem, pelo painel ou porque o número ou a campanha dela foi removido.
expiredNão enviada antes do seu expires_at.

queued e scheduled podem ser canceladas. sent ainda pode passar a delivered e depois a read. failed, cancelled, expired e read são finais. Os webhooks informam sent, failed, cancelled e expired; para ver delivered e read, obtenha a mensagem.

Destinatários#

to aceita exatamente um destes campos:

CampoExemploQuem recebe
phone{"phone": "+919876543210"}Um número de telefone no formato internacional com + (E.164). Espaços e hifens são permitidos.
group{"group": "Bakery staff"}Um grupo de WhatsApp do qual o número que envia participa, pelo nome exato (até 200 caracteres).
contact_id{"contact_id": 991}Um contato salvo no espaço de trabalho, pelo id (o contact_id de uma mensagem anterior, por exemplo). Ela vai para o número ou o grupo desse contato.
username{"username": "@asha_bakes"}Um usuário do Telegram: @name, um link t.me/name, ou tg: e um id de usuário. Só a partir de uma conta do Telegram, então informe uma como from (ou tenha exatamente uma conectada).

Envios para grupos e pelo Telegram exigem que o número que envia esteja nesse grupo ou consiga alcançar esse usuário; os problemas aí aparecem como uma mensagem failed, não como um erro na hora do envio.

Mídia#

media envia uma imagem ou um arquivo, com text como legenda. Informe exatamente um de url ou media_id:

media.urlstringurl ou media_id

Um link público http ou https para o arquivo, com até 1.000 caracteres. Links para endereços privados ou locais são recusados com invalid_media_url.

media.media_idintegerurl ou media_id

Um arquivo do Diretório de mídia do espaço de trabalho, obtido em Enviar um arquivo. Envie um arquivo uma vez e mande-o quantas vezes quiser.

media.typestringopcional

image ou file. Se for omitido, um link que termina em .jpg, .jpeg, .png, .gif ou .webp é enviado como imagem e todo o resto como arquivo; um media_id usa o tipo com que o arquivo foi enviado.

media.file_namestringopcional

Para um file: o nome que o destinatário vê, como invoice-1042.pdf (até 100 caracteres). Se for omitido, o nome vem do link ou do arquivo enviado. A extensão decide como o arquivo é enviado, então inclua uma. Ignorado para imagens.

{
  "to": { "phone": "+919876543210" },
  "text": "Your invoice for order #1042",
  "media": { "url": "https://example.com/invoices/1042.pdf", "type": "file", "file_name": "invoice-1042.pdf" }
}

O arquivo é baixado quando a mensagem é enviada, não quando você chama a API, então um link quebrado ou um arquivo grande demais aparece como uma mensagem failed, com o motivo em error.message. As regras de tamanho e tipo são as da v1: veja Enviar imagens e arquivos.

Agendamento e expiração#

  • send_at agenda a mensagem. Ela fica scheduled até lá e pode ser cancelada até sair. Escreva o horário com o deslocamento, então 2026-10-20T09:30:00+05:30 significa 09:30 na Índia. Para mensagens que se repetem, use lembretes.
  • expires_at é um prazo: se a mensagem não tiver saído até lá (o número estava desconectado, por exemplo), ela passa a expired em vez de sair atrasada. Use-o para códigos de uso único, horários de entrega e ofertas. Uma tarefa em segundo plano a marca como expirada pelo menos 30 segundos depois do prazo, então não conte com prazos menores que um minuto.
  • Os dois precisam estar no futuro, e expires_at precisa ser depois de send_at.

Relacionados#

  • Webhooks: receba message.sent e message.failed em vez de consultar periodicamente.
  • Mídia: envie arquivos para mandar por media_id.
  • Números: o id a usar como from.
  • Erros