Cobrança e cotações
Operações pagas pedem uma cotação antes. Você conhece o custo máximo, executa com o quoteId e só paga o que foi usado.
Leituras e configurações são gratuitas. Envios, campanhas, aquecimento e IA são pagos e seguem sempre dois passos:
- Cotar em
POST /billing/quotescom a operação e orequestexatos. A resposta traz o custo máximo e umquoteId. - Executar em
POST /rpc/{Operação}com o mesmorequeste"billing": {"quoteId": "..."}.
Sem cotação a operação falha com 428 e reason: BILLING_QUOTE_REQUIRED. O preço é o mesmo do painel; você nunca paga mais do que a cotação mostrou.
Operações pagas
| Operação | Tarifa (kind) |
|---|---|
SendMessage, SendImageMessage, SendVoiceNote, SendVideoMessage, SendDocumentMessage, SendConversationMessage (e o atalho POST /messages/send) | send |
StartCampaign, StartCampaignWithTemplate, ResumeCampaign | campaign |
StartWarmup, ResumeWarmupRun | warmup |
CorrectMessage, SummarizeConversation, SuggestReply, SuggestLeadClassification | ai |
1. Cotar
curl -X POST "https://api.zynzap.com.br/v1/billing/quotes" \
-H "Authorization: Bearer $ZYNZAP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"method": "SendMessage",
"request": {
"session_id": "8c1f7a52-4d1e-4b8a-9a43-2f6f5d0c9e11",
"to_jid": "5511987654321",
"text": "Seu pedido #1234 saiu para entrega."
}
}'| Campo da resposta | Significado |
|---|---|
quoteId | Envie em billing.quoteId ao executar. |
kind | Tarifa aplicada: send, campaign, warmup ou ai. |
maxMicrobrl | Custo máximo em micro-reais (1 real = 1.000.000; 50000 = R$ 0,05). |
coveredMicrobrl | Quanto já está coberto por saldo, franquia do plano e excedente autorizado. |
monthlyOverageMicrobrl | Parte que entra no excedente mensal (cartão), se habilitado. |
dueCents | Valor que falta, em centavos. Maior que zero: a execução vai falhar com 402 até haver saldo. |
coverage | inbox_window (resposta grátis na janela de 24 horas), waived (isenção) ou null. |
expiresAt | A cotação vale 15 minutos. |
paymentMode (opcional) escolhe a origem do dinheiro: budget (padrão: saldo, franquia e excedente da conta) ou individual (a operação é paga à parte).
2. Executar
curl -X POST "https://api.zynzap.com.br/v1/rpc/SendMessage" \
-H "Authorization: Bearer $ZYNZAP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"request": {
"session_id": "8c1f7a52-4d1e-4b8a-9a43-2f6f5d0c9e11",
"to_jid": "5511987654321",
"text": "Seu pedido #1234 saiu para entrega."
},
"billing": {
"quoteId": "0b8f2c1e-3a4d-4e5f-8a9b-1c2d3e4f5a6b"
}
}'A cotação fica presa ao conteúdo: operação, request (texto, mídia, destinatários), números envolvidos e configuração. Mudou qualquer coisa? Peça outra (409 BILLING_QUOTE_MISMATCH). Cada cotação executa uma única vez (veja Idempotência).
Janela grátis de 24 horas no atendimento
Responder pelo atendimento (SendConversationMessage) uma conversa individual em que o cliente escreveu nas últimas 24 horas sai de graça: a cotação volta com coverage: "inbox_window" e custo zero. Ainda assim você precisa cotar e enviar o quoteId (a regra é avaliada na hora). Mensagens que você inicia (SendMessage, campanhas) e conversas em grupo são cobradas normalmente.
curl -X POST "https://api.zynzap.com.br/v1/billing/quotes" \
-H "Authorization: Bearer $ZYNZAP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"method": "SendConversationMessage",
"request": {
"conversation_id": "5f0e1d2c-3b4a-4596-8877-66554433aa11",
"session_id": "8c1f7a52-4d1e-4b8a-9a43-2f6f5d0c9e11",
"message_type": "text",
"text": "Claro! Já verifico para você.",
"idempotency_key": "resposta-0001"
}
}'Quanto é cobrado de verdade
- O custo é reservado na execução e consumido conforme o transporte aceita as mensagens. O que não for usado (falhas antes do envio, campanha cancelada) volta para o saldo.
- Mensagem aceita pelo WhatsApp é cobrada mesmo que nunca seja entregue ou lida: aceitação não garante entrega.
- Em resultado incerto (
OUTCOME_UNCERTAIN), o valor fica reservado até a confirmação; consulte o estado antes de reenviar. - Campanhas cotam o custo máximo da campanha inteira; retomar uma campanha pede nova cotação do restante.
Erros de cobrança
reason | HTTP | O que fazer |
|---|---|---|
BILLING_QUOTE_REQUIRED | 428 | Cote e envie billing.quoteId. |
BILLING_QUOTE_INVALID | 400 | quoteId precisa ser o UUID devolvido pela cotação. |
BILLING_QUOTE_EXPIRED | 409 | Passaram 15 minutos: cote de novo. |
BILLING_QUOTE_MISMATCH | 409 | O request mudou: cote com o corpo final. |
BILLING_IDEMPOTENCY_CONFLICT | 409 | A cotação já foi usada com outro conteúdo. |
BILLING_PAYMENT_REQUIRED | 402 | Saldo insuficiente: compre créditos ou habilite o excedente no painel (Plano e consumo). |
BILLING_METHOD_INVALID | 400 | A operação não é paga (não precisa de cotação). |
Veja o guia Tratar cobrança na sua integração para um fluxo completo, com novas tentativas e checagem de saldo.