Um Webhook é uma forma de a Zouti enviar notificações automáticas em tempo real para um sistema externo sempre que algo acontece na sua conta — uma venda, um pagamento, uma assinatura, um carrinho abandonado, etc. Em vez de você consultar a Zouti manualmente, a Zouti faz uma requisição HTTP POST para a URL que você configurar, com os dados do evento no corpo. Serve para integrar a Zouti com CRMs, ERPs, áreas de membros, ferramentas de automação e qualquer sistema próprio
1. No painel, acesse o menu Integrações

2. Localize o card Webhooks (categoria "Plataforma externa") e clique em Acessar

3. Clique em Criar Webhook
4. Preencha os campos:
- Nome do Webhook — um nome para você identificar a integração
- URL — o endereço de destino. O prefixo https:// é adicionado automaticamente
(somente HTTPS é aceito)
- Seleção de produtos (opcional) — se nenhum produto for selecionado, o webhook
dispara para todos os produtos da conta; se selecionar produtos específicos, só
dispara para eles
- Seleção de eventos — marque quais eventos devem disparar o webhook
5. Clique em Criar Webhook para finalizar
6. Gerencie os webhooks pela listagem (nome, URL, status Ativo/Inativo, data de criação,
editar, testar e excluir)
Os eventos abaixo são exatamente os que aparecem para o cliente na tela de criação/edição
do webhook, na ordem em que são exibidos. O "Evento técnico" é o valor enviado no
cabeçalho x-zouti-event-type e que identifica o evento na integração.
Pedidos:
Evento (como aparece no painel) | Evento técnico | Objeto enviado | Cliente iniciou o checkout mas não concluiu o pagamento |
Carrinho abandonado |
| AbandonedCart | Cliente iniciou o checkout mas não concluiu o pagamento |
Pedido criado | |
| Um novo pedido é registrado |
Pedido atualizado |
|
| Um pedido existente sofre alteração |
Pedido pago | |
| O pagamento do pedido é confirmado |
Pedido estornado |
|
| O pedido é reembolsado (status |
Pedido em chargeback | |
| Há uma contestação/chargeback (status |
Pedido cancelado |
|
| O pedido é cancelado |
Pedido não pago | | | O pedido não foi pago (ex.: PIX/boleto expirado) |
Pagamentos (PIX e Boleto):
Evento (como aparece no painel) | Evento técnico | Objeto enviado | Cliente iniciou o checkout mas não concluiu o pagamento |
Pix criado |
|
| Um pagamento via PIX é gerado (aguardando pagamento) — inclui |
Boleto criado | |
| Um boleto é gerado (aguardando pagamento) — inclui |
Assinaturas:
Evento (como aparece no painel) | Evento técnico | Objeto enviado | Cliente iniciou o checkout mas não concluiu o pagamento |
Assinatura criada |
|
| Nova assinatura registrada (status |
Assinatura ativada | |
| Assinatura ativada (status |
Assinatura renovada |
|
| Assinatura renovada com sucesso |
Assinatura cancelada |
|
| Assinatura cancelada (status |
Assinatura atrasada | |
| A renovação da assinatura está atrasada |
Parcelamento Inteligente:
Evento (como aparece no painel) | Evento técnico | Objeto enviado | Cliente iniciou o checkout mas não concluiu o pagamento |
Parcelamento inteligente pago | |
| Uma parcela do parcelamento inteligente é paga |
Parcelamento inteligente atrasado |
|
| Uma parcela está atrasada (cobrança falhou) |
Cobranças:
Evento (como aparece no painel) | Evento técnico | Objeto enviado | Cliente iniciou o checkout mas não concluiu o pagamento |
Cobrança Pendente |
|
| Uma cobrança está aguardando pagamento |
Cobrança Aprovada |
|
| Uma cobrança é confirmada |
Cobrança Reembolsada |
|
| Uma cobrança é reembolsada |
Cobrança Contestada |
|
| Uma cobrança é contestada pelo cliente |
Cobrança Expirada |
|
| Uma cobrança expira sem pagamento |
Cobrança Recusada |
|
| Uma cobrança é recusada |
Solicitações de reembolso?
Evento (como aparece no painel) | Evento técnico | Objeto enviado | Cliente iniciou o checkout mas não concluiu o pagamento |
Solicitação de reembolso criada |
|
| O cliente solicita um reembolso |
Solicitação de reembolso aprovada | |
| A solicitação de reembolso é aprovada |
Solicitação de reembolso recusada | |
| A solicitação de reembolso é recusada |
Observação de status
Order.status: AWAITING_PAYMENT, PAID, UNPAID, REFUNDED, DISPUTED, CANCELED
Payment.status: PENDING, PAID, REFUNDED, PARTIALLY_REFUNDED, DISPUTED, UNPAID, DECLINED
Subscription.status: INCOMPLETE, ACTIVE, CANCELED, TRIAL, PAST_DUE
Métodos de pagamento: Cartão de crédito CREDIT_CARD), PIX PIX), Boleto BOLETO)
RefundRequest.status: PENDING, APPROVED, REFUSED
Diferença entre ORDER_* e PAYMENT_*
o Pedido Order) é a compra do ponto de vista comercial (itens, cliente, valor total); a Cobrança Payment) é a transação financeira em si. Um mesmo pedido pode ter mais de uma cobrança (ex.: pagamento dividido / split payment, ou uma nova tentativa de cobrança). Use os eventos PAYMENT_* quando precisar acompanhar o fluxo financeiro transação a transação; use ORDER_* quando o foco for o pedido/venda
Um carrinho abandonado é gerado quando um cliente inicia o checkout, não conclui o
pagamento e a sessão de checkout expira. Nesse momento a Zouti dispara o evento
ABANDONED_CART_CREATED (objeto AbandonedCart).
Quando o evento é (e não é) disparado:
O carrinho abandonado só é criado — e o webhook só dispara — se:
A sessão de checkout expirou sem o pagamento ter sido concluído; e
O cliente informou um e-mail durante o checkout.
O evento NÃO é disparado quando:
O checkout não capturou o e-mail do cliente (sem e-mail não há como criar o carrinho/remarketing);
Já existe um pedido pago para o mesmo e-mail + oferta nas últimas 24 horas (o cliente já comprou);
Já existe um carrinho abandonado ativo para o mesmo e-mail + oferta (evita duplicatas).
Etapas do carrinho( Step):
Step | Significado |
| Cliente preencheu apenas os dados pessoais |
| Cliente avançou até a etapa de frete/entrega (produto físico) |
| Cliente chegou à etapa de pagamento |
| Cliente gerou um PIX e não pagou (aguardando pagamento) |
| O pagamento do cliente foi recusado |
Observação técnica: na busca/filtragem, PAYMENT e AWAITING_PAYMENT são tratados como o mesmo grupo de "etapa de pagamento".
O payload completo de exemplo do objeto AbandonedCart está no apêndice técnico.
A plataforma tem a função Testar Webhook, que envia um disparo de exemplo sem criar dados reais:
1. Na listagem de webhooks, clique em Testar Webhook
2. Escolha qual webhook deseja testar
3. Escolha o evento a simular (só aparecem os eventos configurados naquele webhook)
4. Clique em Enviar webhook teste. O disparo de teste é assinado com o mesmo segredo do webhook, ou seja, seu servidor valida exatamente como uma entrega real.
O disparo de teste é assinado com o mesmo segredo do webhook, ou seja, seu servidor valida exatamente como uma entrega real. Cada tipo de evento envia um exemplo do objeto correspondente (Pedido, Cobrança, Assinatura, etc.).
Inativação automática e reativação
Um webhook é inativado automaticamente após 10 falhas consecutivas de conexão.
O motivo fica registrado como CONSECUTIVE_FAILURES.
Quando isso acontece, um ícone de alerta aparece na listagem com a explicação.
O cliente pode reativar manualmente o webhook depois de corrigir o destino.
Webhooks também podem ser ativados/inativados manualmente pelo switch da listagem.
Webhook inativado não recebe disparos.
Política de retentativa (retry)
Apenas respostas HTTP 2xx são consideradas sucesso.
O servidor de destino deve responder em até 30 segundos (timeout).
Em caso de falha, a Zouti retenta automaticamente com backoff exponencial(intervalo crescente entre tentativas, com no máximo ~12h entre uma e outra).
As retentativas continuam por até 4 dias após o evento original. Depois disso a entrega é descartada.
Cabeçalhos enviados em cada disparo:
content-type: application/json
user-agent: Zouti-Webhook/1.0
x-zouti-webhook-id: web_xxx
x-zouti-webhook-delivery-id: webd_xxx
x-zouti-object-id: ord_xxx (ID do objeto — pedido, assinatura, etc.)
x-zouti-object-name: Order (tipo do objeto: Order | Subscription | AbandonedCart | Payment | SmartInstallment | RefundRequest)
x-zouti-event-id: evt_xxx
x-zouti-event-type: ORDER_PAID (o evento técnico da tabela acima)
x-zouti-signature: t=1717000000000,v1=<hmac_sha256>Nos eventos de Cobrança PAYMENT_*), x-zouti-object-name é Payment e x-zouti-object-id é o ID da cobrança pmt_xxx).
Verificação de assinatura:
Cada disparo vem assinado por HMAC-SHA256 usando o segredo do webhook. O formato é:
[
t=<timestamp_em_ms>,v1=<hash_hex>
Onde `v1` é o HMAC-SHA256 do **corpo bruto** (raw body) da requisição usando o segredo
como chave. Exemplo de verificação em Node.js:
javascript
const crypto = require('crypto');
function verifyWebhookSignature(rawBody, signatureHeader, secret) {
const [tPart, v1Part] = signatureHeader.split(',');
const receivedHash = v1Part.split('=')[1];
const expectedHash = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(receivedHash),
Buffer.from(expectedHash),
);
}> Dica: valide sempre o corpo bruto (antes de qualquer parse/JSON),caso contrário o hash não confere. O segredo pode ser rotacionado pelo painel; após arotação há um período de carência em que a assinatura antiga ainda é aceita.
Valores monetários:
Todos os valores vêm em centavos (ex.: amount: 9790) e também com a versão em reais
no campo correspondente *_in_brl (ex.: amount_in_brl: 97.90).
Exceção — objeto Cobrança Payment): neste objeto os valores do nível raiz amount, fee, interest_amount, interest_transfer_amount, discount_amount, amount_paid, amount_refunded) vêm **apenas em centavos**, sem o companheiro *_in_brl. A versão em reais aparece somente **dentro de line_items[].amount_in_brl**. O objeto Payment também **não** traz um campo net_amount no nível raiz.
Exemplos de payload (corpo enviado):
Estes são exatamente os payloads usados na função "Testar Webhook" — representam o formato real de cada tipo de objeto. Campos podem variar conforme o método de pagamento e o tipo de produto.
Pedido Order)** — eventos ORDER_*, PIX_CREATED, BOLETO_CREATED:
```json
{
"id": "ord_eloz1kotrd7jtghi5oa3vl",
"account_id": "acc_grlw5o8dp8rv2drenaio84",
"status": "PAID",
"payment_type": "UNIQUE",
"customer_id": "cus_8h2k1l0trd7jtghi5oa3vl",
"provider": "ZOUTI",
"order_session_id": "os_3n9x1k0trd7jtghi5oa3vl",
"checkout_id": "chk_5k2j1h0trd7jtghi5oa3vl",
"is_split_payment": false,
"amount_subtotal": 11970,
"amount_subtotal_in_brl": 119.7,
"amount_total": 11970,
"amount_total_in_brl": 119.7,
"currency": "BRL",
"paid_at": "2024-12-16T19:50:17.044Z",
"items": [
{
"amount": 11970,
"amount_in_brl": 119.7,
"full_amount": 11970,
"full_amount_in_brl": 119.7,
"description": "Curso completo de Desenvolvimento Web Full Stack",
"image_url": "https://zouti-core-media-public.s3.amazonaws.com/media/accounts/acc_grlw5o8dp8rv2drenaio84/products/images/icon.jpg",
"name": "Curso de Desenvolvimento Web",
"product_id": "prod_eji9ptlqrlqk35etn3zfyi",
"quantity": 1,
"type": "SKU"
}
],
"customer": {
"document": "12345678909",
"email": "[email protected]",
"name": "Maria Silva",
"phone": "5511987654321"
},
"payment": {
"method": "CREDIT_CARD",
"status": "PAID",
"amount": 11970,
"amount_in_brl": 119.7,
"fee": 390,
"fee_in_brl": 3.9,
"net_amount": 11100,
"net_amount_in_brl": 111.0,
"interest_amount": 970,
"interest_amount_in_brl": 9.7,
"interest_transfer_amount": 480,
"interest_transfer_amount_in_brl": 4.8,
"discount_amount": 500,
"discount_amount_in_brl": 5.0,
"amount_refunded": 0,
"installments": 12
},
"utm_data": {
"utm_campaign": "black_friday_2024",
"utm_source": "google",
"utm_medium": "cpc",
"utm_content": "banner_promocional",
"utm_term": "curso programacao"
},
"shipping_address": {
"id": "adr_2n8x1k0trd7jtghi5oa3vl",
"line1": "Av. Paulista, 1578",
"line2": "Apto 502",
"line3": "Bloco B",
"neighborhood": "Bela Vista",
"city": "São Paulo",
"state": "SP",
"country": "Brasil",
"postal_code": "01310200"
},
"created_at": "2024-12-16T19:50:17.044Z",
"updated_at": "2024-12-16T19:50:17.044Z"
}Detalhes do objeto Order:
is_split_payment está sempre presente; quando true, o objeto também traz
split_payments[] com o rateio.
Em *PIX_CREATED** o payment traz "pix": { "code": "00020126..." } e o pedido fica com status: "AWAITING_PAYMENT". Em *BOLETO_CREATED**, traz "boleto": { "number": "34191..." }.
shipping_address só vem em produto físico.
O objeto customer do pedido traz name, email, phone e document (**não** traz instagram).
Cobrança Payment)** — eventos PAYMENT_PENDING, PAYMENT_PAID, PAYMENT_REFUNDED, PAYMENT_DISPUTED, PAYMENT_UNPAID, PAYMENT_DECLINED:
```json
{
"id": "pmt_eloz1kotrd7jtghi5oa3vl",
"status": "PAID",
"method": "CREDIT_CARD",
"decline_reason": "Não autorizado pelo emissor",
"failure_reason": "GENERIC_DECLINE",
"installments": 12,
"order_id": "ord_eloz1kotrd7jtghi5oa3vl",
"subscription_id": "sub_2n8x1k0trd7jtghi5oa3vl",
"smart_installment_id": "smi_9f3x1k0trd7jtghi5oa3vl",
"account_id": "acc_grlw5o8dp8rv2drenaio84",
"interest_transfer_amount": 480,
"amount": 11970,
"interest_amount": 970,
"fee": 390,
"discount_amount": 500,
"amount_paid": 11970,
"amount_refunded": 11970,
"refund_id": "ref_7k2j1h0trd7jtghi5oa3vl",
"metadata": {
"invoices": [
{
"invoice_id": "inv_a1b2c3d4",
"credential_type": "ENOTAS",
"credential_id": "cred_xyz789"
}
]
},
"customer": {
"name": "Maria Silva",
"email": "[email protected]",
"document": "12345678909",
"phone": "5511987654321"
},
"splits": [
{
"id": "spl_1a2b3c4d",
"percentage": "20.00",
"amount": 2394,
"amount_refunded": 2394,
"invoice_mode": "PARTNER",
"invited_account_id": "acc_partner7k2j1h0trd7jt"
}
],
"shipping_address": {
"line1": "Av. Paulista, 1578",
"line2": "Apto 502",
"line3": "Bloco B",
"neighborhood": "Bela Vista",
"city": "São Paulo",
"state": "SP",
"country": "Brasil",
"postal_code": "01310200"
},
"line_items": [
{
"name": "Curso de Desenvolvimento Web",
"description": "Curso completo de Desenvolvimento Web Full Stack",
"type": "SKU",
"quantity": 1,
"product_id": "prod_eji9ptlqrlqk35etn3zfyi",
"amount": 11970,
"amount_in_brl": 119.7,
"image": "https://zouti-core-media-public.s3.amazonaws.com/media/.../icon.jpg"
}
],
"created_at": "2024-12-16T19:50:17.044Z",
"updated_at": "2024-12-16T19:50:17.044Z",
"paid_at": "2024-12-16T19:50:17.044Z",
"unpaid_at": "2024-12-16T20:10:00.000Z",
"refunded_at": "2024-12-17T10:00:00.000Z"
}O objeto Payment mantém a mesma estrutura em todos os eventos PAYMENT_*; muda o status e alguns campos de data/valor:
Evento | | Campos que mudam |
|
|
|
|
|
|
|
| inclui |
|
| |
|
|
|
|
| chargeback aberto para a cobrança |
Detalhes do objeto Payment:
O exemplo acima está com todos os campos preenchidos. Na prática, os campos condicionais só aparecem no contexto certo: decline_reasonfailure_reason em recusa; subscription_id em cobrança de assinatura; smart_installment_id em parcela de parcelamento inteligente; refund_id e refunded_at em estorno; paid_atunpaid_at conforme o pagamento foi confirmado ou expirou.
splits traz o rateio de coprodução quando existe.
shipping_address só vem em produto físico.
Os valores são em centavos; a versão em reais aparece só em line_items[].amount_in_brl (veja "Valores monetários" acima).
O objeto Payment não expõe dados internos de gateway/roteamento (ex.: adquirente, subconta, dados do cartão).
Assinatura Subscription)** — eventos SUBSCRIPTION_*:
```json
{
"id": "sub_2n8x1k0trd7jtghi5oa3vl",
"account_id": "acc_grlw5o8dp8rv2drenaio84",
"order_id": "ord_eloz1kotrd7jtghi5oa3vl",
"status": "ACTIVE",
"customer": {
"id": "cus_8h2k1l0trd7jtghi5oa3vl",
"name": "João Silva",
"email": "[email protected]",
"document": "11122233344",
"phone": "5511988776655"
},
"plan": {
"id": "prod_offer_plan_9f3x1k0trd7jt",
"name": "Anual",
"amount": 119700,
"currency": "BRL",
"interval": "YEARLY",
"max_cycles": 12
},
"payment_method": "CREDIT_CARD",
"current_period_start": "2025-05-01T00:00:00.000Z",
"current_period_end": "2026-05-01T00:00:00.000Z",
"next_payment_date": "2026-05-01T00:00:00.000Z",
"installments": 12,
"line_items": [
{
"name": "Assinatura Anual",
"description": "Plano anual do curso",
"type": "SKU",
"quantity": 1,
"product_id": "prod_eji9ptlqrlqk35etn3zfyi",
"amount": 119700,
"amount_in_brl": 1197.0
}
],
"cancel_at_period_end": false,
"billing_cycle_count": 1,
"created_at": "2025-05-01T00:00:00.000Z",
"updated_at": "2025-05-01T00:00:00.000Z"
}Detalhes do objeto Subscription:
line_items[] está sempre presente.
O plan traz id, name, amount, currency, interval (e, quando aplicável, max_cyclestrial). Não há amount_in_brl dentro de plan. O plan.id tem o prefixo prod_offer_plan_....
current_period_end, next_payment_date, canceled_at e installments só aparecem quando fazem sentido para o status da assinatura.
Carrinho abandonado AbandonedCart)** — evento ABANDONED_CART_CREATED:
```json
{
"id": "ab_c_5k2j1h0trd7jtghi5oa3vl",
"step": "PAYMENT",
"total_amount": 14990,
"total_amount_in_brl": 149.9,
"order_session_id": "os_3n9x1k0trd7jtghi5oa3vl",
"url": "https://pay.zouti.com.br/infoproduct_cart_token/ab_c_5k2j1h0trd7jtghi5oa3vl",
"ip_address": "179.108.44.10",
"currency": "BRL",
"customer": {
"name": "Lucas Oliveira",
"email": "[email protected]",
"document": "98765432100",
"phone": "5511999887766",
"instagram": "lucas.oliveira"
},
"metadata": {
"theme": "ZOUTI",
"payment_method": "CREDIT_CARD",
"checkout_type": "INFOPRODUCT"
},
"items": [
{
"type": "SKU",
"product_id": "prod_eji9ptlqrlqk35etn3zfyi",
"variant_id": "var_1a2b3c4d5e",
"name": "Curso de Desenvolvimento Web",
"description": "Curso completo de Desenvolvimento Web",
"amount": 14990,
"amount_in_brl": 149.9,
"quantity": 1,
"image_url": "https://zouti-core-media-public.s3.amazonaws.com/media/.../icon.jpg"
}
],
"utm_data": {
"source": "facebook",
"medium": "social",
"campaign": "remarketing_junho",
"content": "story_01",
"term": "curso web"
},
"account_id": "acc_grlw5o8dp8rv2drenaio84",
"checkout_id": "chk_5k2j1h0trd7jtghi5oa3vl",
"created_at": "2025-05-12T19:30:41.459Z",
"updated_at": "2025-05-12T19:30:41.459Z"
}Detalhes do objeto AbandonedCart:
O id tem o prefixo ab_c_....
Atenção às chaves de UTM: neste objeto o utm_data usa source, medium,
campaign, content, term (**sem** o prefixo utm_). Já no objeto Order as chaves são utm_source, utm_medium, etc.
ip_address, checkout_id e utm_data só aparecem quando disponíveis.
metadata.payment_method só existe se o cliente chegou a escolher um método.
O step indica em que etapa o cliente parou: PERSONAL_DATA, SHIPPING, PAYMENT, AWAITING_PAYMENT ou REFUSED.
Parcelamento inteligente SmartInstallment)** — eventos SMART_INSTALLMENT_*:
```json
{
"id": "smi_9f3x1k0trd7jtghi5oa3vl",
"status": "PAID",
"method": "CREDIT_CARD",
"order_id": "ord_eloz1kotrd7jtghi5oa3vl",
"account_id": "acc_grlw5o8dp8rv2drenaio84",
"order_session_id": "os_3n9x1k0trd7jtghi5oa3vl",
"amount": 9975,
"amount_in_brl": 99.75,
"installment_number": 1,
"total_installments": 12,
"payment_id": "pmt_eloz1kotrd7jtghi5oa3vl",
"due_date": "2025-01-15T00:00:00.000Z",
"currency": "BRL",
"interest_amount": 0,
"interest_amount_in_brl": 0,
"discount_amount": 0,
"discount_amount_in_brl": 0,
"paid_at": "2025-01-10T10:30:00.000Z",
"card": {
"brand": "VISA",
"first_digits": "411111",
"last_digits": "1111",
"holder_name": "João Silva"
},
"customer": {
"id": "cus_8h2k1l0trd7jtghi5oa3vl",
"name": "João Silva",
"email": "[email protected]",
"document": "11122233344",
"phone": "5511988776655"
},
"products": [
{
"name": "Curso de Desenvolvimento Web",
"amount": 9975,
"amount_in_brl": 99.75,
"quantity": 1,
"product_id": "prod_eji9ptlqrlqk35etn3zfyi"
}
],
"created_at": "2025-01-01T00:00:00.000Z",
"updated_at": "2025-01-01T00:00:00.000Z"
}Detalhes do objeto SmartInstallment:
O id tem o prefixo smi_....
products[] está sempre presente.
card inclui first_digits além de last_digits; só aparece em cartão. Para outros métodos podem vir pixboleto.
paid_at fica vazio no evento SMART_INSTALLMENT_LATE_RENEWAL.
Solicitação de reembolso RefundRequest)** — eventos REFUND_REQUEST_*:
```json
{
"id": "rrq_5k2j1h0trd7jtghi5oa3vl",
"account_id": "acc_grlw5o8dp8rv2drenaio84",
"order_id": "ord_eloz1kotrd7jtghi5oa3vl",
"payment_id": "pmt_eloz1kotrd7jtghi5oa3vl",
"status": "APPROVED",
"reason": "Não recebi o produto",
"amount": 9790,
"accepted_at": "2025-05-01T01:00:00.000Z",
"created_at": "2025-05-01T00:00:00.000Z",
"updated_at": "2025-05-01T01:00:00.000Z",
"customer": {
"id": "cus_8h2k1l0trd7jtghi5oa3vl",
"name": "Maria Silva",
"email": "[email protected]",
"document": "12345678909",
"phone": "5511987654321",
"timezone": "America/Sao_Paulo"
},
"order": {
"id": "ord_eloz1kotrd7jtghi5oa3vl",
"status": "PAID",
"amount_subtotal": 9790,
"amount_total": 9790,
"currency": "BRL",
"paid_at": "2025-04-20T14:00:00.000Z",
"created_at": "2025-04-20T13:55:00.000Z",
"updated_at": "2025-04-20T14:00:00.000Z"
},
"payment": {
"id": "pmt_eloz1kotrd7jtghi5oa3vl",
"status": "PAID",
"method": "CREDIT_CARD",
"amount": 9790,
"amount_paid": 9790,
"amount_refunded": 0,
"interest_amount": 0,
"fee": 290,
"installments": 1,
"paid_at": "2025-04-20T14:00:00.000Z"
},
"card": {
"id": "card_5k2j1h0trd7jtghi5oa3vl",
"brand": "VISA",
"last_digits": "1111",
"holder_name": "Maria Silva",
"type": "CREDIT",
"category": "STANDARD",
"country": "BR"
},
"products": [
{
"product_id": "prod_eji9ptlqrlqk35etn3zfyi",
"name": "Curso de Desenvolvimento Web",
"description": "Curso completo de Desenvolvimento Web Full Stack",
"quantity": 1,
"unit_price": 9790,
"sub_total": 9790,
"image_url": "https://zouti-core-media-public.s3.amazonaws.com/media/.../icon.jpg"
}
]
}
Detalhes do objeto RefundRequest:
O id tem o prefixo rrq_....
products[] está sempre presente.
accepted_at aparece em REFUND_REQUEST_APPROVED; rejection_reason e failure_reason em REFUND_REQUEST_REFUSED. Campos sem valor são omitidos do corpo.
cardpixboleto aparecem conforme o método de pagamento original.
A URL do webhook deve usar HTTPS (o https:// é adicionado automaticamente).
Se nenhum produto for selecionado, o webhook vale para todos os produtos da conta.
Cada webhook pode ter vários eventos associados ao mesmo tempo.
É possível ter mais de um webhook para a mesma URL, cada um com eventos diferentes.
Apenas respostas HTTP 2xx são consideradas sucesso; o destino deve responder em até 30 segundos.
Em caso de falha de conexão/timeout/4xx, há retentativa automática com backoff exponencial.
Após 10 falhas consecutivas de entrega, o webhook é inativado automaticamente(motivo CONSECUTIVE_FAILURES) e precisa ser reativado manualmente.
O cliente pode ativar/inativar manualmente pelo switch da listagem; webhook inativado não recebe disparos
Limitações conhecidas:
Somente URLs com protocolo HTTPS são suportadas.
Não há reenvio manual de disparos que falharam (apenas a política de retentativa interna).
Webhooks inativados por falhas consecutivas precisam ser reativados manualmente.
Não é possível visualizar o histórico completo de disparos de um webhook pela interface.
Posso criar mais de um webhook para a mesma URL? Sim, cada um com eventos diferentes.
O que acontece se meu servidor estiver fora do ar? A Zouti retenta por até 4 dias. Após 10 falhas consecutivas, o webhook é inativado automaticamente e precisa ser reativado manualmente.
Como sei se está funcionando? Use a função **Testar Webhook** para enviar um disparo de teste.
Qual a diferença entre os eventos de Pedido e de Cobrança? O Pedido Order) representa a venda; a Cobrança Payment) representa a transação financeira. Um pedido pode ter mais de uma cobrança (ex.: pagamento dividido). Use PAYMENT_* para acompanhar o fluxo financeiro transação a transação.
O https:// é obrigatório? Sim — e é adicionado automaticamente, não precisa digitar.