Desarrolladores

La documentación completa en un archivo

Copia o descarga toda la referencia en Markdown y entrégala a tu asistente de código para generar la integración de una vez.

Inicio rápido

finance.zendry.co

Tres pasos hasta el primer cobro en producción. Todos los valores en centavos, fechas en ISO 8601 (UTC).

1 · Clave
Abre tu cuenta
Se muestra una única vez al crearla. Restringe por IP si puedes.
2 · Prueba
GET /balance
Confirma que la credencial y la IP están liberadas.
3 · Webhook
URLs de recepción y retiro
La confirmación de pago llega por evento, no por polling.
Primera llamada
200
curl -X GET https://finance.zendry.co/api/public/v1/balance \  -H "Authorization: Bearer gw_sua_chave_aqui"

Autenticación

Toda solicitud exige tu clave de API en el encabezado Authorization: Bearer <clave> o x-api-key: <clave> — se aceptan ambos formatos. Genera y revoca claves en Integraciones.

  • Valores monetarios siempre en centavos (entero). Fechas en ISO 8601 (UTC).
  • Con IPs permitidas registradas en Integraciones, las llamadas desde otras IPs reciben 403.
  • La confirmación de pagos es por webhook — los GET sirven para reconsulta, no para polling agresivo.

Pix

POST
/api/public/v1/charges

Crear cobro Pix

Genera un cobro y devuelve el código copia-y-pega de Pix. La confirmación del pago llega por el webhook pix.received — no hagas polling.

  • state: pending → paid, o expired si vence sin pago.
  • external_id no deduplica: dos llamadas iguales crean dos cobros. Guarda el id devuelto.
Parámetros
CampoTipoObligatorioDescripción
amount_centsentero
Sí
Valor en centavos. De 1 a 100000000 (R$ 1 millón).
descriptiontextoNoHasta 140 caracteres.
external_idtextoNoTu identificador. Vuelve en los webhooks. No deduplica.
Solicitud
finance.zendry.co
curl -X POST https://finance.zendry.co/api/public/v1/charges \  -H "Authorization: Bearer gw_tu_clave_aqui" \  -H "Content-Type: application/json" \  -d '{  "amount_cents": 15000,  "description": "Pedido #1234",  "external_id": "1234"}'
Respuesta
200
{  "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"}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

GET
/api/public/v1/charges/:id

Consultar cobro

Devuelve el estado actual de un cobro Pix o boleto (el mismo endpoint atiende ambos — la respuesta sigue el formato del tipo de cobro).

  • 404 si el id no existe o pertenece a otra cuenta.
Solicitud
finance.zendry.co
curl -X GET https://finance.zendry.co/api/public/v1/charges/:id \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "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"}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

POST
/api/public/v1/payouts

Enviar Pix (retiro)

Debita el saldo disponible y envía un Pix a la clave indicada. El valor + tarifa se reservan al instante; el resultado final llega por el webhook pix.sent.

  • state: sending → completed o failed — aviso por el webhook pix.sent; en falla el valor reservado vuelve al saldo.
  • 409 cuando el saldo no alcanza para valor + tarifa.
  • Idempotencia: envía el header Idempotency-Key. Repetir la llamada con la MISMA clave devuelve el retiro ya creado, sin duplicar el débito.
  • Sin ese header, no repitas tras un timeout antes de consultar GET /payouts/{id}: el débito puede ya estar reservado.
Parámetros
CampoTipoObligatorioDescripción
amount_centsentero
Sí
Valor en centavos. De 1 a 100000000.
pix_keytexto
Sí
Clave Pix del beneficiario.
pix_key_typecpf | cnpj | email | phone | evpNoSin este campo, el tipo se infiere del formato de la clave.
descriptiontextoNoHasta 140 caracteres.
Solicitud
finance.zendry.co
curl -X POST https://finance.zendry.co/api/public/v1/payouts \  -H "Authorization: Bearer gw_tu_clave_aqui" \  -H "Content-Type: application/json" \  -d '{  "amount_cents": 5000,  "pix_key": "cliente@email.com",  "pix_key_type": "email",  "description": "Transferencia"}'
Respuesta
200
{  "id": "9ac2...",  "state": "sending",  "amount_cents": 5000,  "fee_cents": 149,  "reserved_cents": 5149,  "idempotent_id": "b7e1...",  "created_at": "2026-01-01T12:00:00Z"}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

GET
/api/public/v1/payouts/{id}

Consultar retiro

Devuelve el estado actual de un retiro por el id de la creación. Úsalo cuando falle la entrega del webhook pix.sent o para conciliar.

  • 404 si el id no existe o pertenece a otra cuenta. La clave de prueba solo ve retiros de sandbox.
  • failure_reason solo viene en failed, con una de cuatro frases en portugués: "Chave Pix inválida.", "Saque cancelado.", la falla simulada del sandbox, o "Não foi possível concluir a operação. Tente novamente em alguns instantes.". Es texto para mostrar, no para interpretar. end_to_end_id solo en completed.
Solicitud
finance.zendry.co
curl -X GET https://finance.zendry.co/api/public/v1/payouts/{id} \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "id": "9ac2...",  "state": "failed",  "amount_cents": 5000,  "fee_cents": 149,  "reserved_cents": 5149,  "pix_key": "cliente@email.com",  "pix_key_type": "email",  "description": "Transferencia",  "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"}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

GET
/api/public/v1/payouts

Listar retiros

Lista los retiros de la cuenta, del más reciente al más antiguo. Filtra por estado para encontrar los que siguen en curso.

  • status=sending devuelve lo que aún no tiene desenlace — es la consulta para conciliar cuando el webhook no llegó.
  • 422 si el estado no es uno de los tres.
Parámetros
CampoTipoObligatorioDescripción
statussending | completed | failedNoSin este campo, devuelve todos.
limitenteroNoDe 1 a 100. Predeterminado 50.
Solicitud
finance.zendry.co
curl -X GET https://finance.zendry.co/api/public/v1/payouts \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "payouts": [    {      "id": "9ac2...",      "state": "sending",      "amount_cents": 5000,      "fee_cents": 149,      "reserved_cents": 5149,      "pix_key": "cliente@email.com",      "pix_key_type": "email",      "description": "Transferencia",      "idempotent_id": "b7e1...",      "end_to_end_id": null,      "failure_reason": null,      "created_at": "2026-01-01T12:00:00Z",      "completed_at": null,      "failed_at": null    }  ]}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

Boleto

POST
/api/public/v1/charges/boleto

Crear cobro por boleto

Emite un boleto (comprobante bancario brasileño) para el comprador indicado. La confirmación llega por el webhook boleto.paid (compensación bancaria, normalmente D+1).

  • Exige tarjeta habilitada para la cuenta.
  • data_limite es el último día en que el boleto sigue siendo aceptado tras el vencimiento. linha_digitavel es la línea digitable; codigo_barras el código de barras.
  • pdf_url es la página del boleto, para imprimir o guardar en PDF.
  • Consúltalo por el mismo GET /charges/:id.
Parámetros
CampoTipoObligatorioDescripción
amount_centsentero
Sí
Valor en centavos.
due_datefecha (AAAA-MM-DD)
Sí
Vencimiento del boleto.
buyerobjeto
Sí
first_name, last_name, email y taxpayer_id (CPF o CNPJ).
buyer.addressobjetoNoline1, neighborhood, city, state, postal_code. Opcional como un todo.
descriptiontextoNoHasta 140 caracteres.
external_idtextoNoTu identificador.
Solicitud
finance.zendry.co
curl -X POST https://finance.zendry.co/api/public/v1/charges/boleto \  -H "Authorization: Bearer gw_tu_clave_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"    }  }}'
Respuesta
200
{  "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"}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

Tarjeta

Checkout & 3DS — paso a paso

Zendry.js

El 3DS de Zendry es inteligente (data-only): en la mayoría de las ventas la autenticación ocurre tras bambalinas, sin pantalla — basta enviar los datos del dispositivo del comprador. El desafío en el navegador (iframe del banco) solo aparece cuando el emisor lo exige, y Zendry.js se encarga de él. El SDK nunca ve el número de la tarjeta ni credenciales.

Cómo circula el dato
  1. Comprador

    Rellena la tarjeta en tu página de checkout.

  2. Tu front

    Zendry.js recoge el device (idioma, pantalla, huso). La tarjeta no pasa por el SDK.

  3. Tu backend

    POST /card_payments con tarjeta, device, ip_address y user_agent.

  4. Zendry

    Autentica con el emisor y responde a tu servidor.

  5. Emisor

    Decide sin pantalla (data-only) o pide desafío al comprador.

Respuesta a tu servidor

200 approved

Data-only: autenticó tras bambalinas, sin pantalla.

201 requires_action

El emisor pidió desafío — Zendry.js lo concluye en el navegador.

402 declined

failure_reason trae el motivo. Ofrece otra tarjeta.

Webhook card.approved / card.declined

El desenlace oficial. Libera el pedido solo aquí — nunca por el retorno del SDK.

Simulador da página de checkout
simulação

É 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.

1

Carga el SDK y recoge el device

Pon el script en la página de checkout y llama Zendry.threeDS() justo antes de enviar el formulario. Devuelve un objeto pequeño con idioma, pantalla y huso del comprador — ningún dato de tarjeta pasa por el SDK. La página entera está en el simulador de arriba, en la pestaña Código.

En tu página de checkout
<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 }
2

Crea la venta en tu backend

Tu clave nunca va al navegador: quien llama a Zendry es tu servidor. Reenvía el device recibido del front y agrega el ip_address y el user_agent del comprador — son ellos los que sostienen la autenticación sin pantalla.

Tu endpoint /checkout/pagar
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 venta = await r.json();   switch (venta.status) {    case "aprovada":      return res.json({ status: "approved", id: venta.id });    case "requires_action":      // devuelve la action al front — Zendry.js concluye el desafío      return res.json({ status: "requires_action", action: venta.action, id: venta.id });    default:      return res.status(402).json({ status: "declined", motivo: venta.failure_reason });  }});
3

Concluye el desafío cuando llegue 201 requires_action

La action es opaca: devuélvela a tu front exactamente como llegó y llama Zendry.completeThreeDS. Sin desafío real (frictionless), se resuelve en segundos, sin pantalla.

En el navegador
201
const desenlace = await Zendry.completeThreeDS(venta.action); if (desenlace.status === "authorized") mostrarExito();else if (desenlace.status === "expired") pedirNuevoIntento();else mostrarRechazo(); // esto es UX. El pedido solo se libera tras la confirmación de tu servidor.
4

Confirma el desenlace en el servidor

El retorno del SDK es para la pantalla; la verdad es el webhook (o el GET /api/public/v1/card_payments/:id). Valida la firma HMAC antes de liberar cualquier pedido.

Recibiendo card.approved
import crypto from "node:crypto"; app.post("/webhooks/zendry", express.raw({ type: "*/*" }), (req, res) => {  const firma = req.headers["x-zendry-signature"];  const esperado = crypto    .createHmac("sha256", process.env.ZENDRY_WEBHOOK_SECRET)    .update(req.body)    .digest("hex");   if (firma !== 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();});
Desenlaces
CampoTipoObligatorioDescripción
aprovada (200)muestra el éxitoNoEl webhook card.approved confirma. Libera el pedido ahí.
requires_action (201)llama completeThreeDSNoTras el desafío llega card.approved o card.declined. Sin conclusión en 15 min, la venta expira.
recusada (200)ofrece otra tarjetaNofailure_reason trae el motivo. Webhook card.declined.
422corrige la solicitudNoerror_type nombra la causa (ej.: INVALID_REQUEST con device ausente en postura reforzada).
  • Envía device en TODA venta: aumenta la tasa de aprobación, y las cuentas con postura de riesgo reforzada rechazan la solicitud sin él (422).
  • action.session_id es de un solo uso y expira en 15 minutos — si el comprador no concluye, la venta expira y es rechazada.
  • Nunca liberes el pedido por el retorno del SDK: solo el webhook (o el GET) es el resultado oficial.
  • No reutilices la misma action en otro intento — crea una venta nueva.
Probar

En el sandbox la tarjeta se simula sin 3DS real: cualquier número válido aprueba y 4000 0000 0000 0002 rechaza (usa la consola del endpoint Pago con tarjeta). El desafío 3DS de verdad solo ocurre en producción.

POST
/api/public/v1/card_payments

Pago con tarjeta

Cobra una tarjeta de crédito server-to-server. Exige tarjeta habilitada para la cuenta. El número de la tarjeta nunca se almacena.

  • Sandbox (clave gw_test_): la autorización es simulada — cualquier número de tarjeta válido APRUEBA y 4000 0000 0000 0002 RECHAZA; sin 3DS; el reembolso también es simulado.
  • 201 + status requires_action: concluye en el navegador con Zendry.completeThreeDS(respuesta.action) — mira la guía Checkout & 3DS arriba. El desenlace oficial llega por el webhook card.approved / card.declined y por el GET de abajo.
  • Un rechazo NO es error HTTP: llega 200 con state declined y failure_reason legible.
  • Los errores de negocio llegan como 422 en el formato { error, error_type, error_code, retry } — catálogo en la sección Errores y límites.
  • Si tu plataforma revende a comercios (gateway en cadena), envía ip_address y user_agent del comprador final — los encabezados HTTP traen tu servidor, no al comprador.
Parámetros
CampoTipoObligatorioDescripción
amount_centsentero
Sí
Valor en centavos.
installmentsenteroNo1 a 12. Predeterminado 1.
buyerobjeto
Sí
name, email y taxpayer_id (CPF, 11 dígitos).
cardobjeto
Sí
holder_name, number, expiration_month (MM), expiration_year (AAAA) y security_code.
billingobjetoNoDirección de facturación.
deviceobjetoNoDatos del dispositivo del comprador recogidos por Zendry.js (Zendry.threeDS()). Aumenta la aprobación — y las cuentas con postura de riesgo reforzada EXIGEN este campo. Campos: language, screen_height, screen_width, time_zone_offset (horas, Brasil = -3).
ip_addresstextoNoIP del COMPRADOR. Obligatorio en la práctica en integraciones en cadena.
user_agenttextoNoUser-agent del COMPRADOR.
external_idtextoNoTu identificador.
Solicitud
finance.zendry.co
curl -X POST https://finance.zendry.co/api/public/v1/card_payments \  -H "Authorization: Bearer gw_tu_clave_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 ..."}'
Respuesta — aprobada o rechazada
200
{  "id": "7d21...",  "charge_id": "1b8e...",  "state": "approved",  "amount_cents": 15000,  "installments": 1,  "external_id": "1234",  "created_at": "2026-01-01T12:00:00Z"}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

GET
/api/public/v1/card_payments/:id

Consultar transacción de tarjeta

Devuelve la transacción por el id entregado en la creación — incluso para seguir el desenlace de un 3DS.

  • state: approved | declined | refunded | requires_action.
  • nsu: el NSU del comprobante. null cuando la venta no llegó a la red (rechazo antes de la autorización, sandbox).
Solicitud
finance.zendry.co
curl -X GET https://finance.zendry.co/api/public/v1/card_payments/:id \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "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"}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

POST
/api/public/v1/card_payments/:id/refund

Reembolsar transacción

Reembolso total. Disponible solo para transacciones aprobadas y dentro de las 24 horas de la aprobación.

  • Tras 24h o en una transacción no aprobada: 422 con la razón en el campo error.
  • El evento card.refunded se dispara en el webhook de recepción.
Solicitud
finance.zendry.co
curl -X POST https://finance.zendry.co/api/public/v1/card_payments/:id/refund \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "id": "7d21...",  "state": "refunded",  "refunded_at": "2026-01-01T18:22:40Z"}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

Cripto (USDT)

POST
/api/public/v1/crypto_payouts

Convertir a USDT y enviar (retiro cripto)

Convierte el valor en reales a USDT a la cotización del momento y lo envía a la billetera indicada. Los reales salen del saldo al instante; el USDT queda bloqueado hasta la confirmación on-chain, que llega por el webhook crypto.sent.

  • state: requested → completed (webhook crypto.sent, con tx_hash) o failed (webhook crypto.failed; el USDT vuelve al saldo disponible en USDT — la conversión de los reales no se deshace).
  • usdt_amount es lo que llega a la billetera: el USDT convertido, menos la tarifa de salida en USDT (fee_usdt_minor). applied_rate es la cotización de la conversión: reales pagados por USDT convertido (amount_cents ÷ (usdt_amount_minor + fee_usdt_minor), en las unidades de cada moneda). En el envío desde el saldo en USDT no hay conversión: applied_rate viene 0.
  • 409 cuando el saldo en reales es insuficiente. 422 cuando la conversión BRL → USDT no está habilitada para la cuenta o el valor rompe un límite de retiro.
  • Idempotencia: envía el header Idempotency-Key. Repetir la llamada con la MISMA clave devuelve el retiro ya creado, sin convertir de nuevo.
  • Envío desde el saldo en USDT: manda usdt_amount_minor en lugar de amount_cents. Es el camino para reenviar un retiro fallido (el USDT vuelve al saldo, no a reales). amount_cents en la respuesta viene 0 en ese caso.
  • Sandbox: el desenlace es inmediato — un valor terminado en 99 centavos simula falla, los demás concluyen sin tx_hash (el sandbox no llega a la red; un identificador de red nunca se inventa).
Parámetros
CampoTipoObligatorioDescripción
amount_centsinteiroNoValor en reales, en centavos. De 1 a 100000000. Aplican el mínimo, el máximo y el tope diario de retiro de la cuenta.
usdt_amount_minorinteiroNoAlternativa a amount_cents: envía USDT que ya está en tu saldo (unidad mínima, 6 decimales) sin convertir. Informa solo uno de los dos.
wallettexto
Sí
Dirección de la billetera de destino, en la red elegida.
networktrc20 | erc20 | bep20 | polygon
Sí
Red del envío: TRON (TRC20), Ethereum (ERC20), BNB Smart Chain (BEP20) o Polygon.
descriptiontextoNoHasta 140 caracteres.
Solicitud
finance.zendry.co
curl -X POST https://finance.zendry.co/api/public/v1/crypto_payouts \  -H "Authorization: Bearer gw_tu_clave_aqui" \  -H "Content-Type: application/json" \  -d '{  "amount_cents": 50000,  "wallet": "TKcXiZ1ovginwWvoCHZwwSPn7ZUhCA7Ndg",  "network": "trc20",  "description": "Repasse"}'
Respuesta
200
{  "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}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

GET
/api/public/v1/crypto_payouts/{id}

Consultar retiro cripto

Devuelve el estado actual de un retiro USDT por el id de la creación. Úsalo cuando la entrega del webhook crypto.sent falló o para conciliar.

  • 404 si el id no existe o pertenece a otra cuenta. La clave de prueba solo ve retiros sandbox.
  • tx_hash solo viene en completed; failure_reason solo en failed.
Solicitud
finance.zendry.co
curl -X GET https://finance.zendry.co/api/public/v1/crypto_payouts/{id} \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "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}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

GET
/api/public/v1/crypto_payouts

Listar retiros cripto

Lista los retiros USDT de la cuenta, del más reciente al más antiguo. Filtra por status para encontrar lo que sigue en curso.

  • status=requested devuelve lo que aún no tiene desenlace — es la consulta para conciliar cuando el webhook no llegó.
  • 422 si el estado no es uno de los tres.
Parámetros
CampoTipoObligatorioDescripción
statusrequested | completed | failedNoSin este campo, devuelve todos.
limitinteiroNoDe 1 a 100. Por defecto 50.
Solicitud
finance.zendry.co
curl -X GET https://finance.zendry.co/api/public/v1/crypto_payouts \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "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    }  ]}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

Disputas

GET
/api/public/v1/disputes

Listar disputas

Disputas (MED y chargeback) de tu cuenta, de las más recientes a las más antiguas. La apertura llega por el webhook dispute.opened; usa la lista para seguir el estado.

  • El valor de la disputa es siempre el de la transacción entera — no existe disputa parcial.
  • Mientras está viva, el valor queda retenido del saldo disponible; el desenlace llega por el webhook dispute.closed (outcome won/lost).
Parámetros
CampoTipoObligatorioDescripción
statusopen | closed | exactoNoopen = vivas (open, under_defense, under_review); closed = won y lost; o un state exacto.
limitenteroNoDe 1 a 100. Predeterminado 50.
Solicitud
finance.zendry.co
curl -X GET https://finance.zendry.co/api/public/v1/disputes \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "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    }  ]}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

GET
/api/public/v1/disputes/:id

Consultar disputa

Detalle completo: datos de la disputa, historial de mensajes (author: seller = tú, zendry = nosotros) y evidencias ya adjuntadas.

  • 404 si el id no existe o pertenece a otra cuenta.
Solicitud
finance.zendry.co
curl -X GET https://finance.zendry.co/api/public/v1/disputes/:id \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "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": "Servicio prestado, comprobante adjunto.", "created_at": "2026-01-02T09:30:00Z" }  ],  "evidence": [    { "name": "comprobante-entrega.pdf", "content_type": "application/pdf", "size_bytes": 182044, "created_at": "2026-01-02T09:29:00Z" }  ]}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

POST
/api/public/v1/disputes/:id/defense

Enviar defensa

Registra tu defensa por escrito y mueve la disputa a under_defense. Adjunta las evidencias antes o después — la defensa puede complementarse mientras la disputa esté viva.

  • 422 si la disputa ya está cerrada (won o lost).
Parámetros
CampoTipoObligatorioDescripción
texttexto
Sí
La argumentación de la defensa. De 5 a 4000 caracteres.
Solicitud
finance.zendry.co
curl -X POST https://finance.zendry.co/api/public/v1/disputes/:id/defense \  -H "Authorization: Bearer gw_tu_clave_aqui" \  -H "Content-Type: application/json" \  -d '{  "text": "Servicio prestado el 01/01, aceptación del cliente en la app. Comprobante adjunto."}'
Respuesta
200
{  "id": "19ba...",  "state": "under_defense"}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

POST
/api/public/v1/disputes/:id/evidence

Adjuntar evidencia

Envía UN archivo de evidencia (comprobante de entrega, aceptación, conversación con el cliente). El cuerpo es multipart/form-data con el campo `file` — el archivo en sí, no base64. Para varios archivos, repite la llamada.

  • Ejemplo: curl -X POST .../disputes/{id}/evidence -H "Authorization: Bearer …" -F "file=@comprobante.pdf"
  • 413 por encima de 15MB; 415 si el formato no es uno de los aceptados; 422 si la disputa ya está cerrada.
Form-data
CampoTipoObligatorioDescripción
filearchivo
Sí
Hasta 15MB. PDF, imagen (PNG, JPEG, GIF, WEBP, HEIC), documento (DOC, DOCX, ODT, RTF, TXT) u hoja de cálculo (XLS, XLSX, ODS, CSV).
Solicitud
finance.zendry.co
curl -X POST https://finance.zendry.co/api/public/v1/disputes/:id/evidence \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "id": "19ba...",  "name": "comprobante-entrega.pdf",  "size_bytes": 182044}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

POST
/api/public/v1/disputes/:id/accept

No contestar

Declara que no vas a defenderte de esta disputa. Sigue a análisis y el desenlace se comunica por el webhook dispute.closed.

  • Acepta solo disputas en open o under_defense (422 en los demás estados).
Solicitud
finance.zendry.co
curl -X POST https://finance.zendry.co/api/public/v1/disputes/:id/accept \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "id": "19ba...",  "state": "under_review"}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

Consultas

GET
/api/public/v1/balance

Consultar saldo

Devuelve el saldo disponible de la cuenta autenticada.

Solicitud
finance.zendry.co
curl -X GET https://finance.zendry.co/api/public/v1/balance \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "balance_cents": 84851,  "currency": "BRL"}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

GET
/api/public/v1/statement

Extracto

Lista los movimientos de la cuenta, de los más recientes a los más antiguos (hasta 200 ítems).

  • Límite fijo de 200 ítems por llamada — pagina por período con from/to.
  • Para conciliación en tiempo real prefiere los webhooks; el extracto es la fuente para cierre y auditoría.
Parámetros de query
CampoTipoObligatorioDescripción
fromfecha (AAAA-MM-DD)NoDía inicial, huso de Brasilia.
tofecha (AAAA-MM-DD)NoDía final, huso de Brasilia.
typetextoNoFiltra por el campo "type" de las respuestas (ej.: pagamento_confirmado).
Solicitud
finance.zendry.co
curl -X GET https://finance.zendry.co/api/public/v1/statement \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "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"    }  ]}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

Endpoints de webhook

GET
/api/public/v1/webhook_events

Listar eventos suscribibles

Catálogo de los eventos que un endpoint puede suscribir, con familia y descripción. Usa el nombre exacto en el campo events.

  • Solo entran eventos que ya tienen emisor — el catálogo crece sin romper suscripciones existentes.
  • "*" no aparece en la lista, pero se acepta en events: suscribe todos los eventos, incluso los futuros.
Solicitud
finance.zendry.co
curl -X GET https://finance.zendry.co/api/public/v1/webhook_events \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "events": [    { "event": "pix.received", "family": "Pix", "description": "Cobro Pix pagado" },    { "event": "pix.sent", "family": "Retiro Pix", "description": "Retiro Pix completado" },    { "event": "dispute.opened", "family": "Disputa", "description": "Disputa (MED/chargeback) abierta" }  ]}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

GET
/api/public/v1/webhook_endpoints

Listar endpoints

Todos los endpoints de la cuenta, incluidos los espejos de los canales fijos (managed: true).

  • managed: true es el espejo de un canal fijo (recepción, retiro, infracción): URL y eventos cambian en la pantalla Integraciones; la API solo lee, prueba y consulta entregas.
Solicitud
finance.zendry.co
curl -X GET https://finance.zendry.co/api/public/v1/webhook_endpoints \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "endpoints": [    {      "id": "e7a1...",      "url": "https://tutienda.com/webhooks/retiros",      "label": "ERP financiero",      "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"    }  ]}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

POST
/api/public/v1/webhook_endpoints

Crear endpoint

Registra una URL y los eventos que recibe. El mismo evento puede ir a varias URLs; cada entrega se firma con el secreto de la cuenta.

  • Hasta 10 endpoints por cuenta (los espejos de los canales fijos no cuentan) — 422 webhook_endpoint_limit_reached.
  • 422 webhook_url_invalid para una URL fuera de la regla; 422 webhook_event_unknown para un evento fuera del catálogo.
  • Prueba la URL apenas la crees (POST /webhook_endpoints/:id/test).
Parámetros
CampoTipoObligatorioDescripción
urltexto
Sí
HTTPS con host público (sin IP privada, localhost ni puerto fuera del estándar).
eventslista de texto
Sí
Nombres del catálogo, o ["*"] para todos.
labeltextoNoNombre visible, hasta 80 caracteres.
activebooleanoNoPor defecto true. Inactivo no recibe nada.
dialecten | ptNoPor defecto en. pt entrega los campos en el formato legado (solo para quien migró de zendry.com).
Solicitud
finance.zendry.co
curl -X POST https://finance.zendry.co/api/public/v1/webhook_endpoints \  -H "Authorization: Bearer gw_tu_clave_aqui" \  -H "Content-Type: application/json" \  -d '{  "url": "https://tutienda.com/webhooks/retiros",  "label": "ERP financiero",  "events": [    "pix.sent",    "crypto.sent",    "crypto.failed"  ]}'
Respuesta
201 Created
{  "id": "e7a1...",  "url": "https://tutienda.com/webhooks/retiros",  "label": "ERP financiero",  "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"}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

PATCH
/api/public/v1/webhook_endpoints/:id

Consultar, actualizar o eliminar endpoint

GET devuelve el endpoint; PATCH cambia solo los campos enviados; DELETE lo elimina (204, sin cuerpo).

  • 404 webhook_endpoint_not_found si el id no existe o es de otra cuenta.
  • 409 webhook_endpoint_managed en PATCH/DELETE de un espejo de canal fijo — cámbialo en la pantalla Integraciones.
  • Las fallas seguidas quedan en consecutive_failures y last_failed_at; el endpoint nunca se desactiva solo — síguelo y corrige la URL.
Parámetros
CampoTipoObligatorioDescripción
urltextoNoMisma regla que en la creación.
eventslista de textoNoReemplaza la lista completa.
labeltextoNoHasta 80 caracteres.
activebooleanoNofalse pausa las entregas sin borrar el endpoint.
dialecten | ptNoFormato de los campos de data.
Solicitud
finance.zendry.co
curl -X PATCH https://finance.zendry.co/api/public/v1/webhook_endpoints/:id \  -H "Authorization: Bearer gw_tu_clave_aqui" \  -H "Content-Type: application/json" \  -d '{  "events": [    "pix.sent"  ],  "active": true}'
Respuesta
200
{  "id": "e7a1...",  "url": "https://tutienda.com/webhooks/retiros",  "label": "ERP financiero",  "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"}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

POST
/api/public/v1/webhook_endpoints/:id/test

Probar endpoint

Entrega al instante un evento de ejemplo, firmado como una entrega real, con test: true en el sobre y el encabezado X-Zendry-Test.

  • Un solo intento, sin reintentos; el resultado también queda en el historial de entregas.
  • Ignora las entregas con test: true en tu procesamiento de negocio — los ids en data son ficticios.
Parámetros
CampoTipoObligatorioDescripción
eventtexto
Sí
Evento del catálogo cuyo ejemplo se enviará.
Solicitud
finance.zendry.co
curl -X POST https://finance.zendry.co/api/public/v1/webhook_endpoints/:id/test \  -H "Authorization: Bearer gw_tu_clave_aqui" \  -H "Content-Type: application/json" \  -d '{  "event": "pix.sent"}'
Respuesta
200
{  "result": "delivered",  "http_status": 200,  "duration_ms": 184,  "response": "ok",  "error": null}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

GET
/api/public/v1/webhook_endpoints/:id/deliveries

Entregas de un endpoint

Últimos intentos de entrega al endpoint, del más reciente al más antiguo.

  • message_id es el X-Zendry-Webhook-Id de ese mensaje: reentregas y reintentos comparten el valor.
  • result: delivered, failed o no_destination.
Parámetros
CampoTipoObligatorioDescripción
limitenteroNoQuery string. Por defecto 50, máximo 200.
eventtextoNoQuery string. Filtra por evento.
Solicitud
finance.zendry.co
curl -X GET https://finance.zendry.co/api/public/v1/webhook_endpoints/:id/deliveries \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "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"    }  ]}
Probar

Crea tu cuenta para ejecutar esta llamada en el sandbox, con clave de prueba y datos aislados.

Webhooks

Cómo funcionan

Configura en Integraciones los canales fijos — recepción (cobros, tarjeta, suscripciones), retiro (pix.sent y demás salidas) e infracción (disputas) — o registra endpoints por evento, eligiendo qué eventos recibe cada URL. Enviamos un POST JSON con los encabezados X-Zendry-Event, X-Zendry-Webhook-Id y X-Zendry-Signature: sha256=<hmac>.

Sobre (envelope)
{  "id": "b0d3c1e2-...",  "event": "pix.received",  "sent_at": "2026-01-01T12:04:12Z",  "data": { ...campos del evento... }}
Ejemplos de data
{  "charge_id": "3f1c...",  "external_id": "1234",  "amount_cents": 15000,  "description": "Pedido #1234",  "end_to_end_id": "E1823612...",  "environment": "producao",  "state": "paid"}
Verificando la firma (HMAC-SHA256 sobre el cuerpo crudo)
const crypto = require("node:crypto"); function firmaValida(cuerpoCrudo, encabezado, secreto) {  const esperada =    "sha256=" + crypto.createHmac("sha256", secreto).update(cuerpoCrudo).digest("hex");  return (    encabezado?.length === esperada.length &&    crypto.timingSafeEqual(Buffer.from(esperada), Buffer.from(encabezado))  );}// firmaValida(rawBody, req.headers["x-zendry-signature"], SECRETO)
  • Responde 2xx en hasta 10 segundos; procesa de forma asíncrona si hace falta.
  • En falla (red, timeout o status ≥ 400) reintentamos hasta 3 veces, con espera creciente.
  • Toda entrega y reentrega queda registrada en Integraciones — desde ahí reenvías un evento perdido.
  • Trata las entregas por charge_id/payout_id de forma idempotente: pueden ocurrir reentregas del mismo evento.

Endpoints por evento

Además de los canales fijos, registra hasta 10 URLs y elige los eventos de cada una — en la pantalla Integraciones o por la API (/api/public/v1/webhook_endpoints). El mismo evento puede ir a varias URLs; events: ["*"] suscribe todo, incluso los eventos futuros.

  • Toda entrega lleva X-Zendry-Webhook-Id (el mismo valor en id, dentro del sobre). Las reentregas repiten el valor — úsalo para deduplicar.
  • Los canales fijos aparecen en la lista como espejos (managed: true): URL y eventos se editan en los campos fijos; ahí los pruebas y sigues su salud.
  • El secreto de firma es uno solo por cuenta: el mismo HMAC vale para todos los endpoints.
  • Las fallas seguidas quedan visibles (consecutive_failures, last_failed_at); nada se desactiva automáticamente.

Catálogo de eventos

21 eventos
Pix
  • pix.receivedCobro Pix pagado (canal de recepción)
  • pix.sentRetiro Pix completado o fallido (canal de retiro)
Boleto
  • boleto.paidBoleto compensado
Tarjeta
  • card.approvedTransacción aprobada (incluso tras 3DS). El campo nsu trae el NSU del comprobante
  • card.declinedTransacción rechazada
  • card.refundedTransacción reembolsada
Cobro
  • charge.expiredCobro expiró sin pago
  • charge.canceledCobro cancelado
Disputas
  • dispute.openedDisputa (chargeback/MED) abierta — webhook de infracción
  • dispute.closedDisputa cerrada — webhook de infracción
Suscripciones
  • subscription.createdSuscripción creada
  • subscription.charge_approvedCobro recurrente aprobado
  • subscription.charge_declinedCobro recurrente rechazado
  • subscription.retry_scheduledNuevo intento agendado
  • subscription.retries_exhaustedIntentos agotados
  • subscription.canceledSuscripción cancelada
  • subscription.completedSuscripción completada
Cripto e Internacional
  • crypto.sentEnvío cripto completado
  • crypto.failedEnvío cripto falló
  • intl.deposit.receivedDepósito internacional recibido
  • intl.payout.sentEnvío internacional completado

Sandbox

Ambiente de pruebas

Genera una clave de prueba en la página Integraciones (prefijo gw_test_). Usa la misma URL base y las mismas rutas, pero opera un ambiente aislado: saldo, extracto y cobros de prueba quedan separados de producción y no circula dinero real — el Pix se simula internamente, sin mover dinero.

  • Cobertura: Pix completo, boleto y tarjeta (creación, consulta, pago/autorización simulados, reembolso) — con webhooks y saldo de prueba.
  • Boleto: emite con números de prueba (línea digitable/código de barras falsos) y se paga por el mismo POST /charges/:id.
  • Tarjeta: simulada sin 3DS — cualquier número válido aprueba; 4000 0000 0000 0002 rechaza; el reembolso también es simulado.
  • Los webhooks son reales (misma URL y firma HMAC), con environment: "sandbox" en el payload.
  • Los identificadores de la red (end_to_end_id, nsu, tx_hash) vienen null en el sandbox: nada se inventa.
  • La clave de prueba no ve datos de producción, y viceversa.
  • El retiro de prueba concluye al instante (webhook pix.sent). Un valor terminado en 99 centavos (ej.: 10099) simula falla — el valor vuelve al saldo.
POST
/api/public/v1/charges/:id

Simular pago (sandbox)

Marca el cobro de prueba (Pix O boleto) como pagado: lo asienta en el saldo sandbox y dispara el webhook real (pix.received o boleto.paid), con firma HMAC. Exclusivo de la clave de prueba — en producción devuelve 403.

  • Solo funciona con clave gw_test_ y cobro del ambiente sandbox (si no, 403/404).
  • Idempotente: un cobro ya pagado responde con already_paid: true.
  • Un cobro expirado no puede pagarse (422).
Solicitud
finance.zendry.co
curl -X POST https://finance.zendry.co/api/public/v1/charges/:id \  -H "Authorization: Bearer gw_tu_clave_aqui"
Respuesta
200
{  "id": "3f1c...",  "state": "paid",  "paid_at": "2026-01-01T12:04:11Z"}
Probar

Crea tu cuenta para simular pagos en el sandbox con tu clave de prueba.

Errores y límites

Envelope estándar

Todo error sale en este formato. code es el contrato estable — decide por él, nunca por el mensaje, que existe para el humano que lee el log y puede cambiar. retryable dice si repetir la MISMA solicitud puede funcionar, y details solo aparece cuando hay algo que mostrar (el campo inválido, el límite y el importe enviado).

Formato
422
{  "error": "Amount is above the maximum for this operation",  "code": "amount_above_maximum",  "retryable": false}
Catálogo de códigos
codeHTTPretryableerror (clave nueva)
Autenticación y acceso
missing_credentials
401
falseCredential missing
invalid_credentials
401
falseInvalid credential
ip_not_allowed
403
falseIP not allowed for this key
Solicitud inválida
invalid_json
400422 en la clave heredada
falseRequest body is not valid JSON
invalid_payload
422
falseInvalid payload
sandbox_only
422
falseOnly available in the sandbox environment
Límites e importes
amount_below_minimum
422
falseAmount is below the minimum for this operation
amount_above_maximum
422
falseAmount is above the maximum for this operation
daily_limit_exceeded
422
falseDaily limit exceeded
Saldo y bloqueos
insufficient_balance
409
falseInsufficient balance
Recurso y estado
charge_not_found
404
falseCharge not found
payout_not_found
404
falsePayout not found
charge_already_paid
422
falseCharge already paid
charge_expired
422
falseCharge expired
charge_finalized
422
falseCharge already finalized
transaction_not_found
404
falseTransaction not found
Pago
payment_method_not_enabled
422
falseThis payment method is not enabled for this account
card_declined
422
falseThe card payment was declined
Disputas y archivos
dispute_not_found
404
falseDispute not found
dispute_closed
422
falseDispute already closed
dispute_action_not_allowed
422
falseThis dispute no longer accepts this action
file_missing
422
falseSend multipart/form-data with a `file` field
file_too_large
413
falseFile is larger than 15MB
file_type_not_allowed
415
falseSend a PDF, image, document or spreadsheet
Webhooks
webhook_endpoint_not_found
404
falseWebhook endpoint not found
webhook_url_invalid
422
falseWebhook URL must use https and a public host
webhook_event_unknown
422
falseUnknown webhook event
webhook_endpoint_limit_reached
422
falseMaximum number of webhook endpoints reached
webhook_endpoint_managed
409
falseThis endpoint mirrors a fixed channel; edit it in the integration settings
Falla nuestra
service_unavailable
503422 en la clave heredada
true
The operation could not be completed. Please try again in a few moments.
internal_error
500422 en la clave heredada
true
The operation could not be completed. Please try again in a few moments.
  • Las claves antiguas (contrato heredado) siguen recibiendo el mensaje en portugués y el status HTTP de siempre; `code`, `retryable` y `details` entran al lado, sin romper a quien ya integra.
  • Ningún detalle interno aparece en la respuesta. La operación que no se pudo completar ahora se convierte en `service_unavailable` (503); la falla inesperada de nuestro lado, en `internal_error` (500). El motivo queda en nuestro log.
  • Antes de repetir un POST que mueve dinero tras un error `retryable`, consulta el recurso con GET — la API no acepta clave de idempotencia del cliente.

Códigos HTTP

Status
CampoTipoObligatorioDescripción
400formatoNoEl cuerpo no es JSON válido.
401authNoCredencial ausente, inválida o revocada.
403accesoNoIP fuera de la lista permitida.
404recursoNoRecurso inexistente o de otra cuenta.
409conflictoNoSaldo insuficiente en el retiro, o endpoint que refleja un canal fijo.
413archivoNoEvidencia de disputa mayor a 15MB.
415archivoNoEvidencia de disputa en un formato no aceptado.
422validaciónNoPayload inválido, límite de la cuenta o regla de negocio. Trae details.
500nuestroNoFalla inesperada de nuestro lado; retryable: true.
503no disponibleNoLa operación no se pudo completar ahora; reintente en instantes (retryable: true).
422 — payload inválido
422
{  "error": "Payload inválido",  "details": [    { "path": ["amount_cents"], "message": "Number must be greater than or equal to 1" }  ]}

Errores de tarjeta

Las rutas de tarjeta usan un formato propio en el 422 — retry indica si vale la pena reintentar la misma solicitud.

Formato
422
{  "error": "Meio de pagamento não habilitado para esta conta",  "error_type": "INVALID_REQUEST",  "error_code": "payment_method_not_enabled",  "retry": false}
error_type
CampoTipoObligatorioDescripción
PAYMENT_DECLINEDretry: falseNoPago rechazado; ofrece otra tarjeta.
INVALID_REQUESTretry: falseNoDato inválido, o tarjeta no habilitada para la cuenta (error_code payment_method_not_enabled).
PENDING_CHECKretry: falseNoPago en verificación; espera el webhook o consulta el GET antes de repetir.
TEMPORARY_ERRORretry: trueNoNo se pudo completar ahora; intenta de nuevo en instantes.
INTERNAL_ERRORretry: trueNoFalla nuestra; intenta de nuevo.

Límites y buenas prácticas

Valor por operación
Definido por cuenta
Mínimo y máximo por medio; 100.000.000 centavos es el tope absoluto del payload.
Tarjeta
1 a 12 cuotas
Reembolso total hasta 24h de la aprobación.
Textos
140 caracteres
description y external_id.
Extracto
200 ítems por llamada
Pagina con from/to.
  • Cada cuenta tiene mínimo y máximo por medio (Pix, tarjeta, boleto y retiro), y el retiro tiene tope diario; el retiro en USDT tiene máximo y tope diario propios, en USDT. Fuera del rango la API rechaza con amount_below_minimum, amount_above_maximum o daily_limit_exceeded. La respuesta no trae los valores de los límites: están en el panel.
  • Idempotencia: la API no acepta clave de idempotencia del cliente. En un timeout de un POST que mueve dinero (retiro, tarjeta), consulta el extracto/GET antes de repetir.
  • La confirmación de pago es por webhook; si reconsultas, limita la frecuencia (ej.: cada 30s) — el tráfico abusivo puede ser bloqueado por el firewall.