Documentação completa em um arquivo
Copie ou baixe toda a referência em Markdown e entregue ao seu assistente de código para gerar a integração de uma vez.
Início rápido
Três passos até a primeira cobrança em produção. Todos os valores em centavos, datas em ISO 8601 (UTC).
curl -X GET https://finance.zendry.co/api/public/v1/balance \ -H "Authorization: Bearer gw_sua_chave_aqui"Autenticação
Toda requisição exige sua chave de API no cabeçalho Authorization: Bearer <chave> ou x-api-key: <chave> — os dois formatos são aceitos. Gere e revogue chaves em Integrações.
- Valores monetários sempre em centavos (inteiro). Datas em ISO 8601 (UTC).
- Com IPs permitidos cadastrados em Integrações, chamadas de outros IPs recebem 403.
- A confirmação de pagamentos é por webhook — os GETs servem para reconsulta, não para polling agressivo.
Pix
Criar cobrança Pix
Gera uma cobrança e retorna o código copia e cola. A confirmação do pagamento chega pelo webhook pix.received — não faça polling.
- state: pending → paid (ou expired se vencer sem pagamento).
- external_id não deduplica: duas chamadas iguais criam duas cobranças. Guarde o id retornado.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| amount_cents | inteiro | Sim | Valor em centavos. De 1 a 100000000 (R$ 1 milhão). |
| description | texto | Não | Até 140 caracteres. |
| external_id | texto | Não | Seu identificador. Volta nos webhooks. Não deduplica. |
curl -X POST https://finance.zendry.co/api/public/v1/charges \ -H "Authorization: Bearer gw_sua_chave_aqui" \ -H "Content-Type: application/json" \ -d '{ "amount_cents": 15000, "description": "Pedido #1234", "external_id": "1234"}'{ "id": "3f1c...", "state": "pending", "amount_cents": 15000, "description": "Pedido #1234", "external_id": "1234", "pix_code": "00020126...5303986540515.00...", "created_at": "2026-01-01T12:00:00Z"}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Consultar cobrança
Retorna o estado atual de uma cobrança Pix ou boleto (o mesmo endpoint atende os dois — a resposta segue o formato do tipo da cobrança).
- 404 se o id não existir ou pertencer a outra conta.
curl -X GET https://finance.zendry.co/api/public/v1/charges/:id \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "id": "3f1c...", "state": "paid", "amount_cents": 15000, "description": "Pedido #1234", "external_id": "1234", "pix_code": "00020126...", "created_at": "2026-01-01T12:00:00Z", "paid_at": "2026-01-01T12:04:11Z"}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Enviar Pix (saque)
Debita o saldo disponível e envia um Pix para a chave informada. O valor + tarifa são reservados na hora; o resultado final chega pelo webhook pix.sent.
- state: sending → completed ou failed (aviso via webhook pix.sent; em falha o valor reservado é devolvido ao saldo).
- 409 quando o saldo é insuficiente para valor + tarifa.
- Idempotência: mande o header Idempotency-Key. Repetir a chamada com a MESMA chave devolve o saque já criado, sem duplicar o débito.
- Sem esse header, não repita após um timeout antes de consultar GET /payouts/{id}: o débito pode já ter sido reservado.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| amount_cents | inteiro | Sim | Valor em centavos. De 1 a 100000000. |
| pix_key | texto | Sim | Chave do favorecido. |
| pix_key_type | cpf | cnpj | email | phone | evp | Não | Sem este campo, o tipo é inferido do formato da chave. |
| description | texto | Não | Até 140 caracteres. |
curl -X POST https://finance.zendry.co/api/public/v1/payouts \ -H "Authorization: Bearer gw_sua_chave_aqui" \ -H "Content-Type: application/json" \ -d '{ "amount_cents": 5000, "pix_key": "cliente@email.com", "pix_key_type": "email", "description": "Repasse"}'{ "id": "9ac2...", "state": "sending", "amount_cents": 5000, "fee_cents": 149, "reserved_cents": 5149, "idempotent_id": "b7e1...", "created_at": "2026-01-01T12:00:00Z"}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Consultar saque
Devolve o estado atual de um saque pelo id da criação. Use quando a entrega do webhook pix.sent falhar ou para reconciliar.
- 404 se o id não existir ou pertencer a outra conta. Chave de teste só enxerga saque sandbox.
- failure_reason só vem preenchido em failed, com uma de quatro frases: "Chave Pix inválida.", "Saque cancelado.", a falha simulada do sandbox, ou "Não foi possível concluir a operação. Tente novamente em alguns instantes.". É texto para exibir, não para interpretar. end_to_end_id só em completed.
curl -X GET https://finance.zendry.co/api/public/v1/payouts/{id} \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "id": "9ac2...", "state": "failed", "amount_cents": 5000, "fee_cents": 149, "reserved_cents": 5149, "pix_key": "cliente@email.com", "pix_key_type": "email", "description": "Repasse", "idempotent_id": "b7e1...", "end_to_end_id": null, "failure_reason": "Não foi possível concluir a operação. Tente novamente em alguns instantes.", "created_at": "2026-01-01T12:00:00Z", "completed_at": null, "failed_at": "2026-01-01T12:00:07Z"}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Listar saques
Lista os saques da conta, do mais recente para o mais antigo. Filtre por status para achar o que ainda está em andamento.
- status=sending devolve o que ainda não teve desfecho — é a consulta para conciliar quando o webhook não chegou.
- 422 se o status não for um dos três.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| status | sending | completed | failed | Não | Sem este campo, devolve todos. |
| limit | inteiro | Não | De 1 a 100. Padrão 50. |
curl -X GET https://finance.zendry.co/api/public/v1/payouts \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "payouts": [ { "id": "9ac2...", "state": "sending", "amount_cents": 5000, "fee_cents": 149, "reserved_cents": 5149, "pix_key": "cliente@email.com", "pix_key_type": "email", "description": "Repasse", "idempotent_id": "b7e1...", "end_to_end_id": null, "failure_reason": null, "created_at": "2026-01-01T12:00:00Z", "completed_at": null, "failed_at": null } ]}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Boleto
Criar cobrança por boleto
Emite um boleto para o comprador informado. A confirmação chega pelo webhook boleto.paid (compensação bancária, normalmente D+1).
- Exige cartão habilitado para a conta.
- data_limite é o último dia em que o boleto ainda é aceito após o vencimento.
- pdf_url é a página do boleto, para imprimir ou salvar em PDF.
- Consulte pelo mesmo GET /charges/:id.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| amount_cents | inteiro | Sim | Valor em centavos. |
| due_date | data (AAAA-MM-DD) | Sim | Vencimento do boleto. |
| buyer | objeto | Sim | first_name, last_name, email e taxpayer_id (CPF ou CNPJ). |
| buyer.address | objeto | Não | line1, neighborhood, city, state, postal_code. Opcional inteiro. |
| description | texto | Não | Até 140 caracteres. |
| external_id | texto | Não | Seu identificador. |
curl -X POST https://finance.zendry.co/api/public/v1/charges/boleto \ -H "Authorization: Bearer gw_sua_chave_aqui" \ -H "Content-Type: application/json" \ -d '{ "amount_cents": 15000, "description": "Pedido #1234", "external_id": "1234", "due_date": "2026-01-15", "buyer": { "first_name": "Maria", "last_name": "Souza", "email": "maria@email.com", "taxpayer_id": "12345678900", "address": { "line1": "Av. Paulista, 1000", "neighborhood": "Bela Vista", "city": "São Paulo", "state": "SP", "postal_code": "01310100" } }}'{ "id": "3f1c...", "state": "pending", "amount_cents": 15000, "description": "Pedido #1234", "external_id": "1234", "due_date": "2026-01-15", "deadline_date": "2026-01-17", "typeable_line": "23791.23456 78900.123456 ...", "barcode": "23797890000015000123456...", "pdf_url": "https://finance.zendry.co/boleto/8f1c.../pdf", "created_at": "2026-01-01T12:00:00Z"}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Cartão
Checkout & 3DS — passo a passo
O 3DS da Zendry é inteligente (data-only): na maioria das vendas a autenticação acontece nos bastidores, sem tela — basta enviar os dados do dispositivo do comprador. O desafio no navegador (iframe do banco) só aparece quando o emissor exige, e o Zendry.js cuida dele. O SDK nunca vê o número do cartão nem credenciais.
Comprador
Preenche o cartão na sua página de checkout.
Seu front
Zendry.js coleta o device (idioma, tela, fuso). O cartão não passa pelo SDK.
Seu backend
POST /card_payments com cartão, device, ip_address e user_agent.
Zendry
Autentica com o emissor e responde ao seu servidor.
Emissor
Decide sem tela (data-only) ou pede desafio ao comprador.
200 approved
Data-only: autenticou nos bastidores, sem tela.
201 requires_action
O emissor pediu desafio — Zendry.js conclui no navegador.
402 declined
failure_reason traz o motivo. Ofereça outro cartão.
Webhook card.approved / card.declined
O desfecho oficial. Só libere o pedido aqui — nunca pelo retorno do SDK.
É o mesmo arquivo dos dois lados. O envio não sai do simulador: o desfecho abaixo é escolhido por você. Numa venda real, quem confirma é sempre o webhook.
Carregue o SDK e colete o device
Coloque o script na página de checkout e chame Zendry.threeDS() logo antes de enviar o formulário. Ele devolve um objeto pequeno com idioma, tela e fuso do comprador — nenhum dado de cartão passa pelo SDK. A página inteira está no simulador acima, na aba Código.
<script src="https://api.zendry.co/sdk/v1/zendry.js"></script> const threeds = await Zendry.threeDS();// threeds.device → { language, screen_height, screen_width, time_zone_offset }Crie a venda no seu backend
Sua chave nunca vai ao navegador: quem chama a Zendry é o seu servidor. Repasse o device recebido do front e acrescente o ip_address e o user_agent do comprador — são eles que sustentam a autenticação sem tela.
app.post("/checkout/pagar", async (req, res) => { const r = await fetch("https://finance.zendry.co/api/public/v1/card_payments", { method: "POST", headers: { Authorization: `Bearer ${process.env.ZENDRY_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ amount_cents: req.body.amount_cents, installments: 1, external_id: req.body.pedido_id, buyer: req.body.buyer, card: req.body.card, device: req.body.device, ip_address: req.headers["x-forwarded-for"]?.split(",")[0], user_agent: req.headers["user-agent"], }), }); const venda = await r.json(); switch (venda.status) { case "aprovada": return res.json({ status: "approved", id: venda.id }); case "requires_action": // devolva a action ao front — o Zendry.js conclui o desafio return res.json({ status: "requires_action", action: venda.action, id: venda.id }); default: return res.status(402).json({ status: "declined", motivo: venda.failure_reason }); }});Conclua o desafio quando vier 201 requires_action
O action é opaco: devolva-o ao seu front exatamente como veio e chame Zendry.completeThreeDS. Sem desafio de fato (frictionless), ele resolve em segundos, sem tela.
const desfecho = await Zendry.completeThreeDS(venda.action); if (desfecho.status === "authorized") mostrarSucesso();else if (desfecho.status === "expired") pedirNovaTentativa();else mostrarRecusa(); // isto é UX. O pedido só é liberado depois da confirmação do seu servidor.Confirme o desfecho no servidor
O retorno do SDK é para a tela; a verdade é o webhook (ou o GET /api/public/v1/card_payments/:id). Valide a assinatura HMAC antes de liberar qualquer pedido.
import crypto from "node:crypto"; app.post("/webhooks/zendry", express.raw({ type: "*/*" }), (req, res) => { const assinatura = req.headers["x-zendry-signature"]; const esperado = crypto .createHmac("sha256", process.env.ZENDRY_WEBHOOK_SECRET) .update(req.body) .digest("hex"); if (assinatura !== esperado) return res.status(401).end(); const evento = JSON.parse(req.body.toString()); if (evento.event === "card.approved") liberarPedido(evento.data.external_id); if (evento.event === "card.declined") cancelarPedido(evento.data.external_id); res.status(200).end();});| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| aprovada (200) | mostre o sucesso | Não | Webhook card.approved confirma. Libere o pedido nele. |
| requires_action (201) | chame completeThreeDS | Não | Após o desafio chega card.approved ou card.declined. Sem conclusão em 15 min, a venda expira. |
| recusada (200) | ofereça outro cartão | Não | failure_reason traz o motivo. Webhook card.declined. |
| 422 | corrija a requisição | Não | error_type nomeia a causa (ex.: INVALID_REQUEST com device ausente em postura reforçada). |
- Envie device em TODA venda: aumenta a taxa de aprovação, e contas com postura de risco reforçada recusam a requisição sem ele (422).
- action.session_id é de uso único e expira em 15 minutos — se o comprador não concluir, a venda expira e é recusada.
- Nunca libere o pedido pelo retorno do SDK: só o webhook (ou o GET) é o resultado oficial.
- Não reaproveite o mesmo action em outra tentativa — crie uma nova venda.
No sandbox o cartão é simulado sem 3DS real: qualquer número válido aprova e 4000 0000 0000 0002 recusa (use o console do endpoint Pagamento com cartão). O desafio 3DS de verdade só acontece em produção.
Pagamento com cartão
Cobra um cartão de crédito server-to-server. Exige cartão habilitado para a conta. O número do cartão nunca é armazenado.
- Sandbox (chave gw_test_): a autorização é simulada — qualquer número de cartão válido APROVA e 4000 0000 0000 0002 RECUSA; sem 3DS; o estorno também é simulado.
- 201 + status requires_action: conclua no navegador com Zendry.completeThreeDS(resposta.action) — veja o guia Checkout & 3DS acima. O desfecho oficial chega pelo webhook card.approved / card.declined e pelo GET abaixo.
- Recusa NÃO é erro HTTP: vem 200 com state declined e failure_reason legível.
- Erros de negócio vêm como 422 no formato { error, error_type, error_code, retry } — catálogo na seção Erros & limites.
- Se sua plataforma revende para lojistas (gateway em cadeia), envie ip_address e user_agent do comprador final — os cabeçalhos HTTP trazem o seu servidor, não o comprador.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| amount_cents | inteiro | Sim | Valor em centavos. |
| installments | inteiro | Não | 1 a 12. Padrão 1. |
| buyer | objeto | Sim | name, email e taxpayer_id (CPF, 11 dígitos). |
| card | objeto | Sim | holder_name, number, expiration_month (MM), expiration_year (AAAA) e security_code. |
| billing | objeto | Não | Endereço de cobrança. |
| device | objeto | Não | Dados do dispositivo do comprador coletados pelo Zendry.js (Zendry.threeDS()). Aumenta a aprovação — e contas com postura de risco reforçada EXIGEM este campo. Campos: language, screen_height, screen_width, time_zone_offset (horas, Brasil = -3). |
| ip_address | texto | Não | IP do COMPRADOR. Obrigatório na prática em integração em cadeia. |
| user_agent | texto | Não | User-agent do COMPRADOR. |
| external_id | texto | Não | Seu identificador. |
curl -X POST https://finance.zendry.co/api/public/v1/card_payments \ -H "Authorization: Bearer gw_sua_chave_aqui" \ -H "Content-Type: application/json" \ -d '{ "amount_cents": 15000, "installments": 1, "external_id": "1234", "buyer": { "name": "Maria Souza", "email": "maria@email.com", "taxpayer_id": "12345678900" }, "card": { "holder_name": "MARIA SOUZA", "number": "4111111111111111", "expiration_month": "12", "expiration_year": "2030", "security_code": "123" }, "ip_address": "203.0.113.10", "user_agent": "Mozilla/5.0 ..."}'{ "id": "7d21...", "charge_id": "1b8e...", "state": "approved", "amount_cents": 15000, "installments": 1, "external_id": "1234", "created_at": "2026-01-01T12:00:00Z"}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Consultar transação de cartão
Retorna a transação pelo id devolvido na criação — inclusive para acompanhar o desfecho de um 3DS.
- state: approved | declined | refunded | requires_action.
- nsu: o NSU do comprovante. null quando a venda não chegou à rede (recusa antes da autorização, sandbox).
curl -X GET https://finance.zendry.co/api/public/v1/card_payments/:id \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "id": "7d21...", "charge_id": "1b8e...", "state": "approved", "amount_cents": 15000, "gross_cents": 15000, "fee_cents": 899, "net_cents": 14101, "installments": 1, "external_id": "1234", "failure_reason": null, "nsu": "Z000186-1049...", "refunded_at": null, "created_at": "2026-01-01T12:00:00Z"}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Estornar transação
Estorno total. Disponível apenas para transações aprovadas e dentro de 24 horas da aprovação.
- Após 24h ou em transação não aprovada: 422 com a razão no campo error.
- O evento card.refunded é disparado no webhook de recebimento.
curl -X POST https://finance.zendry.co/api/public/v1/card_payments/:id/refund \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "id": "7d21...", "state": "refunded", "refunded_at": "2026-01-01T18:22:40Z"}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Cripto (USDT)
Converter em USDT e enviar (saque cripto)
Converte o valor em reais para USDT na cotação do momento e envia para a carteira informada. Os reais saem do saldo na hora; o USDT fica bloqueado até a confirmação on-chain, que chega pelo webhook crypto.sent.
- state: requested → completed (webhook crypto.sent, com tx_hash) ou failed (webhook crypto.failed; o USDT volta ao saldo disponível em USDT — a conversão dos reais não é desfeita).
- usdt_amount é o que chega na carteira: o USDT convertido, menos a tarifa de saída em USDT (fee_usdt_minor). applied_rate é a cotação da conversão: reais pagos por USDT convertido (amount_cents ÷ (usdt_amount_minor + fee_usdt_minor), nas unidades de cada moeda). No envio a partir do saldo em USDT não há conversão: applied_rate vem 0.
- 409 quando o saldo em reais é insuficiente. 422 quando a conversão BRL → USDT não está liberada para a conta ou o valor fere um limite de saque.
- Idempotência: mande o header Idempotency-Key. Repetir a chamada com a MESMA chave devolve o saque já criado, sem converter de novo.
- Envio a partir do saldo em USDT: mande usdt_amount_minor em vez de amount_cents. É o caminho para reenviar um saque que falhou (o USDT volta ao saldo, não a reais). amount_cents na resposta vem 0 nesse caso.
- Sandbox: o desfecho é imediato — valor terminado em 99 centavos simula falha, os demais concluem sem tx_hash (o sandbox não vai à rede; identificador de rede nunca é inventado).
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| amount_cents | inteiro | Não | Valor em reais, em centavos. De 1 a 100000000. Valem o mínimo, o máximo e o teto diário de saque da conta. |
| usdt_amount_minor | inteiro | Não | Alternativa a amount_cents: envia USDT que já está no seu saldo (menor unidade, 6 casas), sem converter. Informe um dos dois. |
| wallet | texto | Sim | Endereço da carteira de destino, na rede escolhida. |
| network | trc20 | erc20 | bep20 | polygon | Sim | Rede do envio: TRON (TRC20), Ethereum (ERC20), BNB Smart Chain (BEP20) ou Polygon. |
| description | texto | Não | Até 140 caracteres. |
curl -X POST https://finance.zendry.co/api/public/v1/crypto_payouts \ -H "Authorization: Bearer gw_sua_chave_aqui" \ -H "Content-Type: application/json" \ -d '{ "amount_cents": 50000, "wallet": "TKcXiZ1ovginwWvoCHZwwSPn7ZUhCA7Ndg", "network": "trc20", "description": "Repasse"}'{ "id": "5b7d...", "state": "requested", "amount_cents": 50000, "usdt_amount": 94.754323, "usdt_amount_minor": 94754323, "fee_usdt_minor": 0, "applied_rate": 5.276804, "wallet": "TKcXiZ1ovginwWvoCHZwwSPn7ZUhCA7Ndg", "network": "trc20", "description": "Repasse", "tx_hash": null, "failure_reason": null, "conversion_id": "c0a1...", "created_at": "2026-01-01T12:00:00Z", "completed_at": null, "failed_at": null}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Consultar saque cripto
Devolve o estado atual de um saque USDT pelo id da criação. Use quando a entrega do webhook crypto.sent falhar ou para reconciliar.
- 404 se o id não existir ou pertencer a outra conta. Chave de teste só enxerga saque sandbox.
- tx_hash só vem preenchido em completed; failure_reason só em failed.
curl -X GET https://finance.zendry.co/api/public/v1/crypto_payouts/{id} \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "id": "5b7d...", "state": "completed", "amount_cents": 50000, "usdt_amount": 94.754323, "usdt_amount_minor": 94754323, "fee_usdt_minor": 0, "applied_rate": 5.276804, "wallet": "TKcXiZ1ovginwWvoCHZwwSPn7ZUhCA7Ndg", "network": "trc20", "description": "Repasse", "tx_hash": "7f3a9c...e21b", "failure_reason": null, "conversion_id": "c0a1...", "created_at": "2026-01-01T12:00:00Z", "completed_at": "2026-01-01T12:03:40Z", "failed_at": null}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Listar saques cripto
Lista os saques USDT da conta, do mais recente para o mais antigo. Filtre por status para achar o que ainda está em andamento.
- status=requested devolve o que ainda não teve desfecho — é a consulta para conciliar quando o webhook não chegou.
- 422 se o status não for um dos três.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| status | requested | completed | failed | Não | Sem este campo, devolve todos. |
| limit | inteiro | Não | De 1 a 100. Padrão 50. |
curl -X GET https://finance.zendry.co/api/public/v1/crypto_payouts \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "crypto_payouts": [ { "id": "5b7d...", "state": "requested", "amount_cents": 50000, "usdt_amount": 94.754323, "usdt_amount_minor": 94754323, "fee_usdt_minor": 0, "applied_rate": 5.276804, "wallet": "TKcXiZ1ovginwWvoCHZwwSPn7ZUhCA7Ndg", "network": "trc20", "description": "Repasse", "tx_hash": null, "failure_reason": null, "conversion_id": "c0a1...", "created_at": "2026-01-01T12:00:00Z", "completed_at": null, "failed_at": null } ]}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Disputas
Listar disputas
Disputas (MED e chargeback) da sua conta, das mais recentes para as mais antigas. A abertura chega pelo webhook dispute.opened; use a lista para acompanhar o estado.
- `transaction_identifier` é o mesmo valor da coluna Identificador da sua lista de transações, e `charge_id` é a cobrança — use um dos dois para achar a venda no portal. `transaction_reference` continua existindo para quem já integrou.
- O valor da disputa é sempre o da transação inteira — não existe disputa parcial.
- Enquanto viva, o valor fica retido do saldo disponível; o desfecho chega pelo webhook dispute.closed (outcome won/lost).
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| status | open | closed | exato | Não | open = vivas (open, under_defense, under_review); closed = won e lost; ou um state exato. |
| limit | inteiro | Não | De 1 a 100. Padrão 50. |
curl -X GET https://finance.zendry.co/api/public/v1/disputes \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "disputes": [ { "id": "19ba...", "type": "med", "state": "open", "amount_cents": 15000, "currency": "BRL", "transaction_reference": "469208464", "transaction_identifier": "d6f1849fe1654d83a4049db495f26ee8", "charge_id": "94a9f429-dc23-4b32-861a-351499d91790", "transaction_identifier": "d6f1849fe1654d83a4049db495f26ee8", "charge_id": "94a9f429-dc23-4b32-861a-351499d91790", "reason": "MED REFUND_REQUEST", "opened_at": "2026-01-01T12:00:00Z", "defense_deadline": "2026-01-08T12:00:00Z", "responded_at": null, "closed_at": null } ]}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Consultar disputa
Detalhe completo: dados da disputa, histórico de mensagens (author: seller = você, zendry = nós) e evidências já anexadas.
- 404 se o id não existir ou pertencer a outra conta.
curl -X GET https://finance.zendry.co/api/public/v1/disputes/:id \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "id": "19ba...", "type": "med", "state": "under_defense", "amount_cents": 15000, "currency": "BRL", "transaction_reference": "469208464", "transaction_identifier": "d6f1849fe1654d83a4049db495f26ee8", "charge_id": "94a9f429-dc23-4b32-861a-351499d91790", "reason": "MED REFUND_REQUEST", "opened_at": "2026-01-01T12:00:00Z", "defense_deadline": "2026-01-08T12:00:00Z", "responded_at": "2026-01-02T09:30:00Z", "closed_at": null, "messages": [ { "author": "seller", "text": "Serviço prestado, comprovante anexo.", "created_at": "2026-01-02T09:30:00Z" } ], "evidence": [ { "name": "comprovante-entrega.pdf", "content_type": "application/pdf", "size_bytes": 182044, "created_at": "2026-01-02T09:29:00Z" } ]}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Enviar defesa
Registra a sua defesa por escrito e move a disputa para under_defense. Anexe as evidências antes ou depois — a defesa pode ser complementada enquanto a disputa estiver viva.
- 422 se a disputa já estiver encerrada (won ou lost).
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| text | texto | Sim | A argumentação da defesa. De 5 a 4000 caracteres. |
curl -X POST https://finance.zendry.co/api/public/v1/disputes/:id/defense \ -H "Authorization: Bearer gw_sua_chave_aqui" \ -H "Content-Type: application/json" \ -d '{ "text": "Serviço prestado em 01/01, aceite do cliente no app. Comprovante anexo."}'{ "id": "19ba...", "state": "under_defense"}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Anexar evidência
Envia UM arquivo de evidência (comprovante de entrega, aceite, conversa com o cliente). O corpo é multipart/form-data com o campo `file` — o arquivo em si, não base64. Para vários arquivos, repita a chamada.
- Exemplo: curl -X POST .../disputes/{id}/evidence -H "Authorization: Bearer …" -F "file=@comprovante.pdf"
- 413 acima de 15MB; 415 se o formato não for um dos aceitos; 422 se a disputa já estiver encerrada.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| file | arquivo | Sim | Até 15MB. PDF, imagem (PNG, JPEG, GIF, WEBP, HEIC), documento (DOC, DOCX, ODT, RTF, TXT) ou planilha (XLS, XLSX, ODS, CSV). |
curl -X POST https://finance.zendry.co/api/public/v1/disputes/:id/evidence \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "id": "19ba...", "name": "comprovante-entrega.pdf", "size_bytes": 182044}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Não contestar
Declara que você não vai se defender desta disputa. Ela segue para análise e o desfecho é comunicado pelo webhook dispute.closed.
- Aceita apenas disputas em open ou under_defense (422 nos demais estados).
curl -X POST https://finance.zendry.co/api/public/v1/disputes/:id/accept \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "id": "19ba...", "state": "under_review"}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Consultas
Consultar saldo
Retorna o saldo disponível da conta autenticada.
curl -X GET https://finance.zendry.co/api/public/v1/balance \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "balance_cents": 84851, "currency": "BRL"}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Extrato
Lista as movimentações da conta, das mais recentes para as mais antigas (até 200 itens).
- Limite fixo de 200 itens por chamada — use from/to para paginar por período.
- Para conciliação em tempo real prefira os webhooks; o extrato é a fonte para fechamento e auditoria.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| from | data (AAAA-MM-DD) | Não | Dia inicial, fuso de Brasília. |
| to | data (AAAA-MM-DD) | Não | Dia final, fuso de Brasília. |
| type | texto | Não | Filtra pelo campo "type" das respostas (ex.: pagamento_confirmado). |
curl -X GET https://finance.zendry.co/api/public/v1/statement \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "transactions": [ { "id": "9ac2...", "type": "pagamento_confirmado", "gross_cents": 15000, "fee_cents": 299, "net_cents": 14701, "end_to_end_id": "E18236120202601011204a1b2c3", "description": "Pedido #1234", "counterparty": "Maria Souza", "created_at": "2026-01-01T12:04:11Z" } ]}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Endpoints de webhook
Listar eventos assináveis
Catálogo dos eventos que um endpoint pode assinar, com família e descrição. Use o nome exato no campo events.
- Só entram eventos que já têm emissor — o catálogo cresce sem quebrar assinaturas existentes.
- "*" não aparece na lista, mas é aceito em events: assina todos os eventos, inclusive os futuros.
curl -X GET https://finance.zendry.co/api/public/v1/webhook_events \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "events": [ { "event": "pix.received", "family": "Pix", "description": "Cobrança Pix paga" }, { "event": "pix.sent", "family": "Saque Pix", "description": "Saque Pix concluído" }, { "event": "dispute.opened", "family": "Disputa", "description": "Disputa (MED/chargeback) aberta" } ]}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Listar endpoints
Todos os endpoints da conta, inclusive os espelhos dos canais fixos (managed: true).
- managed: true é o espelho de um canal fixo (recebimento, saque, infração): URL e eventos mudam pela tela Integrações; a API só lê, testa e consulta entregas.
curl -X GET https://finance.zendry.co/api/public/v1/webhook_endpoints \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "endpoints": [ { "id": "e7a1...", "url": "https://sualoja.com/webhooks/saques", "label": "ERP financeiro", "events": ["pix.sent", "crypto.sent", "crypto.failed"], "active": true, "dialect": "en", "managed": false, "consecutive_failures": 0, "last_delivered_at": "2026-09-05T12:04:12Z", "last_failed_at": null, "created_at": "2026-09-05T11:00:00Z", "updated_at": "2026-09-05T11:00:00Z" } ]}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Criar endpoint
Cadastra uma URL e os eventos que ela recebe. O mesmo evento pode ir para várias URLs; cada entrega é assinada com o segredo da conta.
- Até 10 endpoints por conta (os espelhos dos canais fixos não contam) — 422 webhook_endpoint_limit_reached.
- 422 webhook_url_invalid para URL fora da regra; 422 webhook_event_unknown para evento fora do catálogo.
- Teste a URL logo após criar (POST /webhook_endpoints/:id/test).
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| url | texto | Sim | HTTPS com host público (sem IP privado, localhost ou porta fora do padrão). |
| events | lista de texto | Sim | Nomes do catálogo, ou ["*"] para todos. |
| label | texto | Não | Nome de exibição, até 80 caracteres. |
| active | booleano | Não | Padrão true. Inativo não recebe nada. |
| dialect | en | pt | Não | Padrão en. pt entrega os campos no formato legado (só para quem migrou do zendry.com). |
curl -X POST https://finance.zendry.co/api/public/v1/webhook_endpoints \ -H "Authorization: Bearer gw_sua_chave_aqui" \ -H "Content-Type: application/json" \ -d '{ "url": "https://sualoja.com/webhooks/saques", "label": "ERP financeiro", "events": [ "pix.sent", "crypto.sent", "crypto.failed" ]}'{ "id": "e7a1...", "url": "https://sualoja.com/webhooks/saques", "label": "ERP financeiro", "events": ["pix.sent", "crypto.sent", "crypto.failed"], "active": true, "dialect": "en", "managed": false, "consecutive_failures": 0, "last_delivered_at": null, "last_failed_at": null, "created_at": "2026-09-05T11:00:00Z", "updated_at": "2026-09-05T11:00:00Z"}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Consultar, atualizar ou remover endpoint
GET devolve o endpoint; PATCH altera só os campos enviados; DELETE remove (204, sem corpo).
- 404 webhook_endpoint_not_found se o id não existir ou for de outra conta.
- 409 webhook_endpoint_managed em PATCH/DELETE num espelho de canal fixo — altere pela tela Integrações.
- Falhas seguidas ficam em consecutive_failures e last_failed_at; o endpoint não é desativado sozinho — acompanhe e corrija a URL.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| url | texto | Não | Mesma regra da criação. |
| events | lista de texto | Não | Substitui a lista inteira. |
| label | texto | Não | Até 80 caracteres. |
| active | booleano | Não | false pausa as entregas sem apagar o endpoint. |
| dialect | en | pt | Não | Formato dos campos de data. |
curl -X PATCH https://finance.zendry.co/api/public/v1/webhook_endpoints/:id \ -H "Authorization: Bearer gw_sua_chave_aqui" \ -H "Content-Type: application/json" \ -d '{ "events": [ "pix.sent" ], "active": true}'{ "id": "e7a1...", "url": "https://sualoja.com/webhooks/saques", "label": "ERP financeiro", "events": ["pix.sent"], "active": true, "dialect": "en", "managed": false, "consecutive_failures": 0, "last_delivered_at": "2026-09-05T12:04:12Z", "last_failed_at": null, "created_at": "2026-09-05T11:00:00Z", "updated_at": "2026-09-05T12:30:00Z"}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Testar endpoint
Entrega na hora um evento de exemplo, assinado como uma entrega real, com test: true no envelope e o cabeçalho X-Zendry-Test.
- Uma tentativa só, sem repetição; o resultado também fica no histórico de entregas.
- Ignore entregas com test: true no seu processamento de negócio — os ids em data são fictícios.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| event | texto | Sim | Evento do catálogo cujo exemplo será enviado. |
curl -X POST https://finance.zendry.co/api/public/v1/webhook_endpoints/:id/test \ -H "Authorization: Bearer gw_sua_chave_aqui" \ -H "Content-Type: application/json" \ -d '{ "event": "pix.sent"}'{ "result": "delivered", "http_status": 200, "duration_ms": 184, "response": "ok", "error": null}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Entregas de um endpoint
Últimas tentativas de entrega ao endpoint, da mais recente para a mais antiga.
- message_id é o X-Zendry-Webhook-Id daquela mensagem: reentregas e repetições compartilham o valor.
- result: delivered, failed ou no_destination.
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| limit | inteiro | Não | Query string. Padrão 50, máximo 200. |
| event | texto | Não | Query string. Filtra por evento. |
curl -X GET https://finance.zendry.co/api/public/v1/webhook_endpoints/:id/deliveries \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "deliveries": [ { "id": "d41c...", "message_id": "b0d3c1e2-...", "event": "pix.sent", "source_event": "pix.sent", "result": "delivered", "http_status": 200, "duration_ms": 184, "error": null, "attempt": 1, "resent_from": null, "created_at": "2026-09-05T12:04:12Z" } ]}Crie sua conta para executar esta chamada no sandbox, com chave de teste e dados isolados.
Webhooks
Como funcionam
Configure em Integrações os canais fixos — recebimento (cobranças, cartão, assinaturas), saque (pix.sent e demais saídas) e infração (disputas) — ou cadastre endpoints por evento, escolhendo quais eventos cada URL recebe. Enviamos um POST JSON com os cabeçalhos X-Zendry-Event, X-Zendry-Webhook-Id e X-Zendry-Signature: sha256=<hmac>.
{ "id": "b0d3c1e2-...", "event": "pix.received", "sent_at": "2026-01-01T12:04:12Z", "data": { ...campos do evento... }}{ "charge_id": "3f1c...", "external_id": "1234", "amount_cents": 15000, "description": "Pedido #1234", "end_to_end_id": "E1823612...", "environment": "producao", "state": "paid"}const crypto = require("node:crypto"); function assinaturaValida(corpoBruto, cabecalho, segredo) { const esperada = "sha256=" + crypto.createHmac("sha256", segredo).update(corpoBruto).digest("hex"); return ( cabecalho?.length === esperada.length && crypto.timingSafeEqual(Buffer.from(esperada), Buffer.from(cabecalho)) );}// assinaturaValida(rawBody, req.headers["x-zendry-signature"], SEGREDO)- Responda 2xx em até 10 segundos; processe de forma assíncrona se precisar.
- Em falha (rede, timeout ou status ≥ 400) tentamos até 3 vezes, com espera crescente.
- Toda entrega e reentrega fica registrada em Integrações — de lá você reenvia um evento perdido.
- Trate entregas por charge_id/payout_id de forma idempotente: reentregas do mesmo evento podem ocorrer.
Endpoints por evento
Além dos canais fixos, cadastre até 10 URLs e escolha os eventos de cada uma — pela tela Integrações ou pela API (/api/public/v1/webhook_endpoints). O mesmo evento pode ir para mais de uma URL; events: ["*"] assina tudo, inclusive eventos futuros.
- Toda entrega leva X-Zendry-Webhook-Id (o mesmo valor em id, no envelope). Reentregas repetem o valor — use-o para deduplicar.
- Os canais fixos aparecem na lista como espelhos (managed: true): URL e eventos editam-se nos campos fixos; ali você testa e acompanha a saúde.
- O segredo de assinatura é um só por conta: o mesmo HMAC vale para todos os endpoints.
- Falhas seguidas ficam visíveis (consecutive_failures, last_failed_at); nada é desativado automaticamente.
Catálogo de eventos
- pix.receivedCobrança Pix paga (canal de recebimento)
- pix.sentSaque Pix concluído ou falhou (canal de saque)
- boleto.paidBoleto compensado
- card.approvedTransação aprovada (inclusive após 3DS). O campo nsu traz o NSU do comprovante
- card.declinedTransação recusada
- card.refundedTransação estornada
- charge.expiredCobrança expirou sem pagamento
- charge.canceledCobrança cancelada
- dispute.openedContestação (chargeback/MED) aberta — webhook de infração
- dispute.closedContestação encerrada — webhook de infração
- subscription.createdAssinatura criada
- subscription.charge_approvedCobrança recorrente aprovada
- subscription.charge_declinedCobrança recorrente recusada
- subscription.retry_scheduledNova tentativa agendada
- subscription.retries_exhaustedTentativas esgotadas
- subscription.canceledAssinatura cancelada
- subscription.completedAssinatura concluída
- crypto.sentEnvio cripto concluído
- crypto.failedEnvio cripto falhou
- intl.deposit.receivedDepósito internacional recebido
- intl.payout.sentEnvio internacional concluído
Sandbox
Ambiente de testes
Gere uma chave de teste na página Integrações (prefixo gw_test_). Ela usa a mesma URL base e as mesmas rotas, mas opera um ambiente isolado: saldo, extrato e cobranças de teste ficam separados de produção e nenhum dinheiro real circula — o Pix é simulado internamente, sem movimentar dinheiro.
- Cobertura: Pix completo, boleto e cartão (criação, consulta, pagamento/autorização simulados, estorno) — com webhooks e saldo de teste.
- Boleto: emite com números de teste (linha digitável/código de barras fake) e paga pelo mesmo POST /charges/:id.
- Cartão: simulado sem 3DS — qualquer número válido aprova; 4000 0000 0000 0002 recusa; estorno também é simulado.
- Os webhooks são reais (mesma URL e assinatura HMAC), com environment: "sandbox" no payload.
- Identificadores da rede (end_to_end_id, nsu, tx_hash) vêm null no sandbox: nada é inventado.
- Chave de teste não enxerga dados de produção, e vice-versa.
- Saque de teste conclui na hora (webhook pix.sent). Valor terminado em 99 centavos (ex.: 10099) simula falha — o valor volta ao saldo.
Simular pagamento (sandbox)
Marca a cobrança de teste (Pix OU boleto) como paga: lança no saldo sandbox e dispara o webhook real (pix.received ou boleto.paid), com assinatura HMAC. Exclusivo da chave de teste — em produção retorna 403.
- Só funciona com chave gw_test_ e cobrança do ambiente sandbox (senão 403/404).
- Idempotente: cobrança já paga responde com already_paid: true.
- Cobrança expirada não pode ser paga (422).
curl -X POST https://finance.zendry.co/api/public/v1/charges/:id \ -H "Authorization: Bearer gw_sua_chave_aqui"{ "id": "3f1c...", "state": "paid", "paid_at": "2026-01-01T12:04:11Z"}Crie sua conta para simular pagamentos no sandbox com sua chave de teste.
Erros & limites
Envelope padrão
Todo erro sai neste formato. code é o contrato estável — trate por ele, nunca pela mensagem, que existe para o humano que lê o log e pode mudar. retryable diz se repetir a MESMA requisição pode dar certo, e details só aparece quando há o que mostrar (campo inválido, limite e valor enviado).
{ "error": "Amount is above the maximum for this operation", "code": "amount_above_maximum", "retryable": false}| code | HTTP | retryable | error (chave nova) |
|---|---|---|---|
| Autenticação e acesso | |||
| missing_credentials | 401 | false | Credential missing |
| invalid_credentials | 401 | false | Invalid credential |
| ip_not_allowed | 403 | false | IP not allowed for this key |
| Requisição inválida | |||
| invalid_json | 400 | false | Request body is not valid JSON |
| invalid_payload | 422 | false | Invalid payload |
| sandbox_only | 422 | false | Only available in the sandbox environment |
| Limites e valores | |||
| amount_below_minimum | 422 | false | Amount is below the minimum for this operation |
| amount_above_maximum | 422 | false | Amount is above the maximum for this operation |
| daily_limit_exceeded | 422 | false | Daily limit exceeded |
| Saldo e bloqueios | |||
| insufficient_balance | 409 | false | Insufficient balance |
| Recurso e estado | |||
| charge_not_found | 404 | false | Charge not found |
| payout_not_found | 404 | false | Payout not found |
| charge_already_paid | 422 | false | Charge already paid |
| charge_expired | 422 | false | Charge expired |
| charge_finalized | 422 | false | Charge already finalized |
| transaction_not_found | 404 | false | Transaction not found |
| Pagamento | |||
| payment_method_not_enabled | 422 | false | This payment method is not enabled for this account |
| card_declined | 422 | false | The card payment was declined |
| Disputas e arquivos | |||
| dispute_not_found | 404 | false | Dispute not found |
| dispute_closed | 422 | false | Dispute already closed |
| dispute_action_not_allowed | 422 | false | This dispute no longer accepts this action |
| file_missing | 422 | false | Send multipart/form-data with a `file` field |
| file_too_large | 413 | false | File is larger than 15MB |
| file_type_not_allowed | 415 | false | Send a PDF, image, document or spreadsheet |
| Webhooks | |||
| webhook_endpoint_not_found | 404 | false | Webhook endpoint not found |
| webhook_url_invalid | 422 | false | Webhook URL must use https and a public host |
| webhook_event_unknown | 422 | false | Unknown webhook event |
| webhook_endpoint_limit_reached | 422 | false | Maximum number of webhook endpoints reached |
| webhook_endpoint_managed | 409 | false | This endpoint mirrors a fixed channel; edit it in the integration settings |
| Falha nossa | |||
| service_unavailable | 503 | true | The operation could not be completed. Please try again in a few moments. |
| internal_error | 500 | true | The operation could not be completed. Please try again in a few moments. |
- Chaves antigas (contrato legado) seguem recebendo a mensagem em português e o status HTTP de sempre; `code`, `retryable` e `details` entram ao lado, sem quebrar quem já integra.
- Nenhum detalhe interno aparece na resposta. A operação que não pôde ser concluída agora vira `service_unavailable` (503); falha inesperada do nosso lado, `internal_error` (500). As duas dizem "Não foi possível concluir a operação. Tente novamente em alguns instantes.", e o motivo fica no nosso log.
- Antes de repetir um POST que movimenta dinheiro depois de um erro `retryable`, consulte o recurso pelo GET — a API não aceita chave de idempotência do cliente.
Códigos HTTP
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| 400 | formato | Não | Corpo não é JSON válido. |
| 401 | auth | Não | Credencial ausente, inválida ou revogada. |
| 403 | acesso | Não | IP fora da lista de permitidos. |
| 404 | recurso | Não | Recurso inexistente ou de outra conta. |
| 409 | conflito | Não | Saldo insuficiente no saque, ou endpoint que espelha canal fixo. |
| 413 | arquivo | Não | Evidência de disputa acima de 15MB. |
| 415 | arquivo | Não | Evidência de disputa num formato não aceito. |
| 422 | validação | Não | Payload inválido, limite da conta ou regra de negócio. Traz details. |
| 500 | nosso | Não | Falha inesperada do nosso lado; retryable: true. |
| 503 | indisponível | Não | A operação não pôde ser concluída agora; tente de novo em instantes (retryable: true). |
{ "error": "Payload inválido", "details": [ { "path": ["amount_cents"], "message": "Number must be greater than or equal to 1" } ]}Erros de cartão
As rotas de cartão usam um formato próprio no 422 — retry indica se vale tentar novamente a mesma requisição.
{ "error": "Meio de pagamento não habilitado para esta conta", "error_type": "INVALID_REQUEST", "error_code": "payment_method_not_enabled", "retry": false}| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| PAYMENT_DECLINED | retry: false | Não | Pagamento recusado; ofereça outro cartão. |
| INVALID_REQUEST | retry: false | Não | Dado inválido, ou cartão não habilitado para a conta (error_code payment_method_not_enabled). |
| PENDING_CHECK | retry: false | Não | Pagamento em verificação; aguarde o webhook ou consulte o GET antes de repetir. |
| TEMPORARY_ERROR | retry: true | Não | Não foi possível concluir agora; tente novamente em instantes. |
| INTERNAL_ERROR | retry: true | Não | Falha nossa; tente novamente. |
Limites & boas práticas
- Cada conta tem mínimo e máximo por meio (Pix, cartão, boleto e saque), e o saque tem teto diário; o saque em USDT tem máximo e teto diário próprios, em USDT. Fora da faixa a API recusa com amount_below_minimum, amount_above_maximum ou daily_limit_exceeded. A resposta não traz os valores dos limites: eles ficam no painel.
- Idempotência: a API não aceita chave de idempotência do cliente. Em timeout de um POST que movimenta dinheiro (saque, cartão), consulte o extrato/GET antes de repetir.
- Confirmação de pagamento é por webhook; se fizer reconsulta, limite a frequência (ex.: a cada 30s) — tráfego abusivo pode ser bloqueado pelo firewall.