DESARROLLADORES

API de operaciones de la cuenta

Consulta el saldo, solicita reembolsos y retiros, responde a disputas y gestiona las entregas de webhook. Firma cada solicitud como se describe en Autenticación.

  • URL basehttps://www.manuellsolutions.com/api/v3
  • Versión de la API3.0.0

Ver las operaciones

Entorno

Prueba sin mover dinero real.

Pagos reales. Se requiere una clave de producción.

Saldo

Lee tu saldo disponible y retirable.

El saldo de sandbox es virtual. Los pagos de sandbox pasan de inmediato a available_amount, sin esperar a una fecha valor, así que puedes probar los retiros enseguida.

El saldo de producción procede de cobros reales. Un pago espera en pending_settlement_amount hasta su fecha valor y luego pasa a available_amount.

GET/api/v3/balance

Obtener el saldo

Respuesta · 200

Resumen del saldo.

Balance

CampoTipoObligatorioDescripción
currency_codestringObligatorioMoneda base configurada de la plataforma.
USDEURAEDTRY
available_amountstringObligatorioSaldo disponible combinado de los monederos de enlaces de pago, de API y de tienda. Una clave de sandbox lee en su lugar el monedero de API virtual y aislado.
pending_settlement_amountstringObligatorioCobrado pero aún no liquidado (pendiente de fecha valor). Siempre es 0.00 con una clave de sandbox, porque los pagos de sandbox no esperan a una fecha valor.
environmentstringObligatorioEntorno al que pertenecen las cifras (el entorno de la clave de firma).
livesandbox

Respuesta · Ejemplo

{
  "currency_code": "USD",
  "available_amount": "48200.00",
  "pending_settlement_amount": "250.00",
  "environment": "live"
}

Errores posibles

GET/api/v3/balance/withdrawable

Obtener el saldo retirable

Respuesta · 200

Resumen del saldo retirable.

WithdrawableBalance

CampoTipoObligatorioDescripción
currency_codestringObligatorioMoneda base configurada de la plataforma.
USDEURAEDTRY
withdrawable_amountstringObligatorioSaldo disponible combinado de enlaces de pago, API y tienda; POST /withdrawals solo puede descontar del monedero de API y aplica comprobaciones adicionales. Una clave de sandbox lee el monedero de API virtual y aislado.
can_withdrawbooleanObligatorioEl valor es false si algún apartado del monedero es negativo.
environmentstringObligatorioEntorno al que pertenecen las cifras (el entorno de la clave de firma).
livesandbox

Respuesta · Ejemplo

{
  "currency_code": "USD",
  "withdrawable_amount": "48200.00",
  "can_withdraw": true,
  "environment": "live"
}

Errores posibles

Reembolsos

Solicita un reembolso o anulación y haz su seguimiento.

En producción, HTTP 202 significa que se ha recibido la solicitud, no que el reembolso esté hecho. Sigue el resultado mediante los endpoints de estado: requested, luego awaiting_provider_manual, luego completed; o rejected / cancelled.

En sandbox, una solicitud se resuelve de inmediato (completed por defecto). Envía X-CAV-Sandbox-Scenario: rejected para probar un reembolso rechazado.

Las solicitudes de producción se revisan. Sigue la reversión hasta completed, rejected o cancelled. Solo un refund completado envía payment.refunded; sigue un void con GET.

POST/api/v3/refundsRequiere Idempotency-Key

Solicitar un reembolso o una anulación

Parámetros

CampoTipoObligatorioDescripción
X-CAV-Sandbox-Scenariostring · headerOpcionalSolo para claves de sandbox. Elige el resultado simulado: completed (por defecto) o rejected (sin efecto en el monedero virtual). Una clave de producción que envíe esta cabecera, o cualquier clave que envíe otro valor, recibe 422 1000001. La cabecera no forma parte de la cadena firmada, pero sí de la huella de la Idempotency-Key, por lo que reutilizar una clave con otro escenario devuelve 9000010. El escenario aplicado se devuelve en la cabecera de respuesta del mismo nombre.
completedrejected

Cuerpo de la solicitud

CampoTipoObligatorioDescripción
payment_codestringObligatorioCódigo del pago abonado con éxito que se va a revertir.
maxLength 16
operation_typestringObligatoriorefund reembolsa un pago ya definitivo; void anula un cobro con tarjeta que todavía no es definitivo. Ambos abren una solicitud de reversión (estado requested). Un operador la revisa; una vez aprobada, el importe se reserva en tu saldo y el estado es awaiting_provider_manual hasta que se registra la referencia de reembolso del proveedor (completed); de lo contrario, la solicitud termina en rejected o cancelled (se libera la reserva). Este endpoint no contacta con el proveedor.
refundvoid
reasonstringObligatorioPor qué se solicita la reversión.
minLength 3maxLength 500

Cuerpo de la solicitud · Ejemplo

{
  "payment_code": "ab34cdef",
  "operation_type": "refund",
  "reason": "Customer cancelled the order."
}

Respuesta · 202

Reversión solicitada. Se revisa y se envía al proveedor de forma manual. Con una clave de sandbox se devuelve el resultado simulado (environment sandbox); una repetición idempotente también devuelve 202.

Reversal

CampoTipoObligatorioDescripción
idstringObligatorioIdentificador de la solicitud de reversión (UUID).
operationstringObligatorioTipo de operación.
refundvoid
statusstringObligatorioCiclo de vida de la reversión: requested (a la espera de un operador) → awaiting_provider_manual (aprobada; el importe queda reservado hasta que se registra la referencia de reembolso del proveedor) → completed, o rejected / cancelled (se libera la reserva). processing y failed son valores reservados que hoy no se usan en las reversiones de pagos. Con una clave de sandbox, el estado es definitivo al instante: completed (por defecto) o rejected.
requestedprocessingcompletedrejectedfailedawaiting_provider_manualcancelled
amountstringObligatorioImporte total del pago revertido, en la moneda del propio pago (el mismo importe y la misma moneda que el pago y su webhook payment.refunded), como cadena decimal con 2 decimales. El estado requested no significa que se haya movido dinero.
currencystringObligatorioMoneda de amount: el currency_code del pago revertido.
reasonstringObligatorioMotivo que indicaste.
provider_referencestring | nullObligatorioReferencia de reembolso del proveedor, que se rellena cuando se completa el reembolso en el POS real. En sandbox se devuelve una referencia sintética que empieza por SBX- cuando termina la reversión simulada; no es un registro del proveedor.
provider_refunded_atstring · date-time | nullObligatorioCuándo se registró el reembolso del proveedor (UTC). Es null hasta la finalización manual.
created_atstring · date-timeObligatorioHora de la solicitud (UTC).
updated_atstring · date-time | nullObligatorioÚltimo cambio de estado (UTC).
payment_codestring | nullObligatorioCódigo del pago al que pertenece esta reversión (el code devuelto al crear el pago).
environmentstringObligatorioEntorno de la reversión (el entorno de la clave de firma).
livesandbox

Respuesta · Ejemplo

{
  "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
  "operation": "refund",
  "status": "requested",
  "amount": "250.00",
  "currency": "USD",
  "reason": "Customer cancelled the order.",
  "provider_reference": "string",
  "provider_refunded_at": "2026-09-26T09:00:00.000Z",
  "created_at": "2026-09-26T09:00:00.000Z",
  "updated_at": "2026-09-26T09:00:00.000Z",
  "payment_code": "ab34cdef",
  "environment": "live"
}

Errores posibles

GET/api/v3/refunds

Listar reembolsos

Parámetros

CampoTipoObligatorioDescripción
pageinteger · queryOpcionalNúmero de página.
minimum 1
per_pageinteger · queryOpcionalElementos por página.
minimum 1maximum 100
statusstring · queryOpcionalFiltrar por estado.
requestedprocessingawaiting_provider_manualcompletedrejectedfailedcancelled
operation_typestring · queryOpcionalFiltrar por operación.
refundvoid

Respuesta · 200

Reembolsos paginados.

CampoTipoDescripción
dataReversal[]
metaPaginationMeta

Respuesta · Ejemplo

{
  "data": [
    {
      "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
      "operation": "refund",
      "status": "requested",
      "amount": "250.00",
      "currency": "USD",
      "reason": "Customer cancelled the order.",
      "provider_reference": "string",
      "provider_refunded_at": "2026-09-26T09:00:00.000Z",
      "created_at": "2026-09-26T09:00:00.000Z",
      "updated_at": "2026-09-26T09:00:00.000Z",
      "payment_code": "ab34cdef",
      "environment": "live"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 1,
    "total_pages": 1
  }
}

Errores posibles

GET/api/v3/refunds/{id}

Obtener el estado de un reembolso

Parámetros

CampoTipoObligatorioDescripción
idstring · uuid · pathObligatorioEl id de la reversión.

Respuesta · 200

La reversión.

Objeto: Reversal (campos en Solicitar un reembolso o una anulación).

Respuesta · Ejemplo

{
  "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
  "operation": "refund",
  "status": "requested",
  "amount": "250.00",
  "currency": "USD",
  "reason": "Customer cancelled the order.",
  "provider_reference": "string",
  "provider_refunded_at": "2026-09-26T09:00:00.000Z",
  "created_at": "2026-09-26T09:00:00.000Z",
  "updated_at": "2026-09-26T09:00:00.000Z",
  "payment_code": "ab34cdef",
  "environment": "live"
}

Errores posibles

Notificación

Cuando se completa un reembolso, se envía una notificación payment.refunded firmada a la URL de webhook del pago. Las cabeceras, la firma y los reintentos son los mismos que en Webhooks. Un void no envía notificación.

POSTpayment.refunded

Notificación payment.refunded firmada a la URL del comercio

Cuerpo de la solicitud

CampoTipoObligatorioDescripción
event_idstring · uuidObligatorio
event_typestringObligatorio
payment.refunded
environmentstringObligatorio
sandboxlive
occurred_atstring · date-timeObligatorio
refundobjectObligatorio
refund.public_idstring · uuidObligatorio
refund.statusstringObligatorio
completed
refund.amountstringObligatorioImporte positivo como cadena decimal de escala fija con 2 decimales. No se acepta "0.00".
refund.currency_codestringObligatorioCódigo de moneda fiduciaria, limitado a las cuatro monedas admitidas.
USDEURAEDTRY
refund.completed_atstring · date-timeObligatorioEl mismo instante que occurred_at.
paymentobjectObligatorio
payment.public_idstring · uuidObligatorio
payment.codestringObligatorio
minLength 1maxLength 16
payment.merchant_referencestring | nullObligatorio
maxLength 64
orderobjectObligatorio
order.public_idstring · uuidObligatorio

Cuerpo de la solicitud · Ejemplo

{
  "event_id": "B5D4E456-EFC1-4EC2-A613-D64A16E45BD5",
  "event_type": "payment.refunded",
  "environment": "sandbox",
  "occurred_at": "2026-09-28T12:00:00.000Z",
  "refund": {
    "public_id": "A1B2C3D4-E5F6-4789-8ABC-DEF012345678",
    "status": "completed",
    "amount": "100.00",
    "currency_code": "USD",
    "completed_at": "2026-09-28T12:00:00.000Z"
  },
  "payment": {
    "public_id": "11111111-2222-4333-8444-555555555555",
    "code": "ab34cdef",
    "merchant_reference": "SIP-2026-0001"
  },
  "order": {
    "public_id": "66666666-7777-4888-8999-AAAAAAAAAAAA"
  }
}

Retiros

Solicita un retiro de USDT (TRC20) y haz su seguimiento.

En producción, HTTP 201 significa que la solicitud se ha aceptado y el importe queda retenido, no que se haya enviado USDT. Comprueba status y tx_hash y revisa dos veces la dirección: una transferencia en la cadena no se puede deshacer.

Un retiro de sandbox descuenta del saldo virtual y nunca envía nada a la cadena. Sigue las mismas reglas que en producción, incluidos el mínimo, el tope diario y el tipo de conversión. Envía X-CAV-Sandbox-Scenario: rejected para probar un rechazo. En sandbox se acepta la dirección cero de TRON como destino; en producción se rechazan las direcciones de quema con 1000030.

El mínimo y el tope diario los fija Manuell para cada cuenta; por debajo del mínimo la API devuelve 9000019 y por encima del tope, 9000021. En producción, un operador de Manuell envía los USDT y registra tx_hash (sent), o rechaza la solicitud indicando el motivo (rejected) y el importe vuelve a tu saldo.

POST/api/v3/withdrawalsRequiere Idempotency-Key

Solicitar un retiro de USDT

Parámetros

CampoTipoObligatorioDescripción
X-CAV-Sandbox-Scenariostring · headerOpcionalSolo para claves de sandbox. Elige el resultado simulado: sent (por defecto) o rejected (sin efecto en el monedero virtual). Una clave de producción que envíe esta cabecera, o cualquier clave que envíe otro valor, recibe 422 1000001. La cabecera no forma parte de la cadena firmada, pero sí de la huella de la Idempotency-Key, por lo que reutilizar una clave con otro escenario devuelve 9000010. El escenario aplicado se devuelve en la cabecera de respuesta del mismo nombre.
sentrejected

Cuerpo de la solicitud

CampoTipoObligatorioDescripción
amountstringObligatorioImporte que se retendrá del monedero de API, en la moneda base configurada de la plataforma, como cadena decimal con 2 decimales. El mínimo y el tope diario los fija el operador de la plataforma para cada cuenta: un importe inferior al mínimo devuelve 9000019 y uno superior al tope diario devuelve 9000021. Consulta tus límites con tu gestor de cuenta.
addressstringObligatorioTu propia dirección TRON, ya comprobada, para un retiro de USDT TRC20. El ejemplo es un marcador de posición y se rechazará si se envía sin cambios.
maxLength 64
address_acknowledgedbooleanObligatorioDebe ser true: confirmas que la dirección de destino es correcta y que la transferencia no se puede revertir.

Cuerpo de la solicitud · Ejemplo

{
  "amount": "250.00",
  "address": "REPLACE_WITH_YOUR_TRON_ADDRESS",
  "address_acknowledged": true
}

Respuesta · 201

Retiro solicitado. El saldo queda retenido; el envío en la cadena se realiza manualmente. Con una clave de sandbox se devuelve el resultado simulado (environment sandbox); una repetición idempotente también devuelve 201.

Withdrawal

CampoTipoObligatorioDescripción
idstringObligatorioIdentificador de la solicitud de retiro (UUID).
statusstringObligatorioEstado del ciclo de vida del retiro: requested → sent o rejected. El envío en la cadena lo realiza manualmente el operador de la plataforma. Con una clave de sandbox, el estado es definitivo al instante: sent (por defecto) o rejected.
requestedsentrejected
amountstringObligatorioImporte solicitado y retenido del monedero de API, en la moneda base de la plataforma, como cadena decimal con 2 decimales; no es un importe en USDT.
currencystringObligatorioMoneda base en la que se expresa el importe.
assetstringObligatorioActivo del retiro (USDT).
networkstringObligatorioRed del retiro (TRC20).
addressstringObligatorioDirección de destino que indicaste.
usdt_amountstringObligatorioImporte en USDT calculado cuando se acepta la solicitud, como cadena decimal de escala fija con 6 decimales. Este campo por sí solo no confirma una transferencia en la cadena.
tx_hashstring | nullObligatorioHash de la transacción en la cadena, que se rellena tras el envío. En sandbox se devuelve un hash sintético de 64 caracteres para un retiro sent; no se realiza ninguna transferencia en la cadena.
rejection_reasonstring | nullObligatorioMotivo, que se rellena si se rechaza. En sandbox, un retiro rechazado lleva Sandbox scenario: rejected.
requested_atstring · date-timeObligatorioHora de la solicitud (UTC).
processed_atstring · date-time | nullObligatorioCuándo se envió o se rechazó (UTC).
created_atstring · date-timeObligatorioFecha y hora de creación del registro (UTC).
environmentstringObligatorioEntorno del retiro (el entorno de la clave de firma).
livesandbox

Respuesta · Ejemplo

{
  "id": "7F0C2A94-3B1E-4D58-9A6F-1C2D3E4F5A6B",
  "status": "requested",
  "amount": "250.00",
  "currency": "USD",
  "asset": "USDT",
  "network": "TRC20",
  "address": "REPLACE_WITH_YOUR_TRON_ADDRESS",
  "usdt_amount": "249.000000",
  "tx_hash": null,
  "rejection_reason": null,
  "requested_at": "2026-09-26T09:30:00.000Z",
  "processed_at": null,
  "created_at": "2026-09-26T09:30:00.000Z",
  "environment": "live"
}

Errores posibles

GET/api/v3/withdrawals

Listar retiros

Parámetros

CampoTipoObligatorioDescripción
pageinteger · queryOpcionalNúmero de página.
minimum 1
per_pageinteger · queryOpcionalElementos por página.
minimum 1maximum 100
statusstring · queryOpcionalFiltrar por estado.
requestedsentrejected

Respuesta · 200

Retiros paginados.

CampoTipoDescripción
dataWithdrawal[]
metaPaginationMeta

Respuesta · Ejemplo

{
  "data": [
    {
      "id": "7F0C2A94-3B1E-4D58-9A6F-1C2D3E4F5A6B",
      "status": "requested",
      "amount": "250.00",
      "currency": "USD",
      "asset": "USDT",
      "network": "TRC20",
      "address": "REPLACE_WITH_YOUR_TRON_ADDRESS",
      "usdt_amount": "249.000000",
      "tx_hash": null,
      "rejection_reason": null,
      "requested_at": "2026-09-26T09:30:00.000Z",
      "processed_at": null,
      "created_at": "2026-09-26T09:30:00.000Z",
      "environment": "live"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 1,
    "total_pages": 1
  }
}

Errores posibles

GET/api/v3/withdrawals/{id}

Obtener el estado de un retiro

Parámetros

CampoTipoObligatorioDescripción
idstring · uuid · pathObligatorioEl id del retiro.

Respuesta · 200

El retiro.

Objeto: Withdrawal (campos en Solicitar un retiro de USDT).

Respuesta · Ejemplo

{
  "id": "7F0C2A94-3B1E-4D58-9A6F-1C2D3E4F5A6B",
  "status": "requested",
  "amount": "250.00",
  "currency": "USD",
  "asset": "USDT",
  "network": "TRC20",
  "address": "REPLACE_WITH_YOUR_TRON_ADDRESS",
  "usdt_amount": "249.000000",
  "tx_hash": null,
  "rejection_reason": null,
  "requested_at": "2026-09-26T09:30:00.000Z",
  "processed_at": null,
  "created_at": "2026-09-26T09:30:00.000Z",
  "environment": "live"
}

Errores posibles

Disputas

Lista las disputas y envía tus pruebas.

Las disputas vienen de las redes de tarjetas, así que en sandbox creas tú mismo una disputa de prueba con POST /api/v3/sandbox/disputes. Consulta Probar las operaciones de la cuenta.

Manuell registra una disputa cuando el banco se lo notifica. El importe en disputa se descuenta de tu saldo (el saldo puede quedar en negativo y can_withdraw pasa a false) y se restituye si ganas. Envía tus pruebas antes de evidence_due_at; una Idempotency-Key nueva sustituye tu nota anterior mientras la disputa siga abierta.

GET/api/v3/disputes

Listar disputas

Parámetros

CampoTipoObligatorioDescripción
pageinteger · queryOpcionalNúmero de página.
minimum 1
per_pageinteger · queryOpcionalElementos por página.
minimum 1maximum 100
statusstring · queryOpcionalFiltrar por estado.
openunder_reviewwonlost

Respuesta · 200

Disputas paginadas.

CampoTipoDescripción
dataDispute[]
metaPaginationMeta

Dispute

CampoTipoObligatorioDescripción
idstringObligatorioIdentificador de la disputa (UUID).
servicestringObligatorioServicio al que pertenece el pago en disputa: api para un pago creado a través de esta API y link para un enlace de pago.
amountstringObligatorioImporte en disputa (cadena decimal).
currencystringObligatorioMoneda de la disputa.
statusstringObligatorioEstado de la disputa.
openunder_reviewwonlost
reasonstringObligatorioCategoría del motivo de la disputa.
fraudunauthorizedproduct_not_deliveredduplicateamount_mismatchother
reason_notestring | nullObligatorioNota del motivo del banco, literal.
occurred_onstring · dateObligatorioFecha en que se abrió la disputa (YYYY-MM-DD).
evidence_due_atstring · date-time | nullObligatorioFecha límite para enviar pruebas (UTC). Una disputa de sandbox permanece abierta para pruebas durante 7 días tras su creación.
evidence_submitted_atstring · date-time | nullObligatorioCuándo presentó la plataforma la defensa ante el banco.
merchant_evidence_notestring | nullObligatorioLa nota que enviaste.
merchant_evidence_submitted_atstring · date-time | nullObligatorioCuándo enviaste tu nota.
resolved_atstring · date-time | nullObligatorioCuándo se cerró la disputa.
created_atstring · date-timeObligatorioFecha y hora de creación del registro (UTC).
payment_codestring | nullObligatorioCódigo del pago de API al que pertenece la disputa (el code devuelto al crear el pago); null si la disputa no está vinculada a un pago de API.
environmentstringObligatorioEntorno de la disputa (el entorno de la clave de firma).
livesandbox

Respuesta · Ejemplo

{
  "data": [
    {
      "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
      "service": "api",
      "amount": "250.00",
      "currency": "USD",
      "status": "open",
      "reason": "fraud",
      "reason_note": "string",
      "occurred_on": "2026-09-26",
      "evidence_due_at": "2026-09-26T09:00:00.000Z",
      "evidence_submitted_at": "2026-09-26T09:00:00.000Z",
      "merchant_evidence_note": "string",
      "merchant_evidence_submitted_at": "2026-09-26T09:00:00.000Z",
      "resolved_at": "2026-09-26T09:00:00.000Z",
      "created_at": "2026-09-26T09:00:00.000Z",
      "payment_code": "ab34cdef",
      "environment": "live"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 1,
    "total_pages": 1
  }
}

Errores posibles

GET/api/v3/disputes/{id}

Obtener una disputa

Parámetros

CampoTipoObligatorioDescripción
idstring · uuid · pathObligatorioEl id de la disputa.

Respuesta · 200

La disputa.

Objeto: Dispute (campos en Listar disputas).

Respuesta · Ejemplo

{
  "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
  "service": "api",
  "amount": "250.00",
  "currency": "USD",
  "status": "open",
  "reason": "fraud",
  "reason_note": "string",
  "occurred_on": "2026-09-26",
  "evidence_due_at": "2026-09-26T09:00:00.000Z",
  "evidence_submitted_at": "2026-09-26T09:00:00.000Z",
  "merchant_evidence_note": "string",
  "merchant_evidence_submitted_at": "2026-09-26T09:00:00.000Z",
  "resolved_at": "2026-09-26T09:00:00.000Z",
  "created_at": "2026-09-26T09:00:00.000Z",
  "payment_code": "ab34cdef",
  "environment": "live"
}

Errores posibles

POST/api/v3/disputes/{id}/evidenceRequiere Idempotency-Key

Enviar pruebas de la disputa

Parámetros

CampoTipoObligatorioDescripción
idstring · uuid · pathObligatorioEl id de la disputa.

Cuerpo de la solicitud

CampoTipoObligatorioDescripción
notestringObligatorioTu texto de pruebas para la disputa.
minLength 3maxLength 4000

Cuerpo de la solicitud · Ejemplo

{
  "note": "Order 4821 was delivered on 2026-09-25. Carrier reference ABC123."
}

Respuesta · 200

Pruebas registradas; el estado de la disputa no cambia. Una repetición idempotente idéntica devuelve el cuerpo de la respuesta original.

Objeto: Dispute (campos en Listar disputas).

Respuesta · Ejemplo

{
  "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
  "service": "api",
  "amount": "250.00",
  "currency": "USD",
  "status": "open",
  "reason": "fraud",
  "reason_note": "string",
  "occurred_on": "2026-09-26",
  "evidence_due_at": "2026-09-26T09:00:00.000Z",
  "evidence_submitted_at": "2026-09-26T09:00:00.000Z",
  "merchant_evidence_note": "string",
  "merchant_evidence_submitted_at": "2026-09-26T09:00:00.000Z",
  "resolved_at": "2026-09-26T09:00:00.000Z",
  "created_at": "2026-09-26T09:00:00.000Z",
  "payment_code": "ab34cdef",
  "environment": "live"
}

Errores posibles

Gestionar entregas

Inspecciona las entregas de webhook y reintenta las fallidas.

La dirección que recibe las notificaciones se define por entorno en “API Key e Integración”. Los endpoints de abajo listan las entregas y vuelven a poner en cola las fallidas.

GET/api/v3/webhooks/deliveries

Listar entregas de webhook

Parámetros

CampoTipoObligatorioDescripción
pageinteger · queryOpcionalNúmero de página.
minimum 1
per_pageinteger · queryOpcionalElementos por página.
minimum 1maximum 100
statusstring · queryOpcionalFiltrar por estado.
pendingdeliveredfailed

Respuesta · 200

Entregas paginadas.

CampoTipoDescripción
dataWebhookDelivery[]
metaPaginationMeta

WebhookDelivery

CampoTipoDescripción
idstringIdentificador de la entrega (UUID).
eventstringTipo de evento de la entrega: payment.paid, payment.refunded o payment.failed. Un intento fallido no es definitivo; el pago sigue created y puede pagarse después.
statusstringEstado de la entrega.
pendingdeliveredfailed
payment_codestring | nullCódigo del pago relacionado, si existe.
attempt_countintegerNúmero de intentos de entrega hasta ahora.
last_status_codeinteger | nullEstado HTTP del último intento.
last_errorstring | nullError de entrega sin procesar heredado; usa last_error_code y last_error_message.
last_error_codestring | nullCódigo de error de entrega estable y legible por máquina.
invalid_webhook_targetwebhook_target_private_networkwebhook_environment_invalidwebhook_signing_unavailablewebhook_response_unsuccessfulwebhook_egress_proxy_unreachablewebhook_unreachablewebhook_delivery_failed
last_error_messagestring | nullMensaje de error de entrega breve y legible, seleccionado mediante Accept-Language.
next_attempt_atstring · date-time | nullCuándo está programado el siguiente reintento (UTC).
delivered_atstring · date-time | nullCuándo se entregó (UTC).
created_atstring · date-timeFecha y hora de creación del registro (UTC).

Respuesta · Ejemplo

{
  "data": [
    {
      "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
      "event": "payment.paid",
      "status": "pending",
      "payment_code": null,
      "attempt_count": 1,
      "last_status_code": null,
      "last_error": null,
      "last_error_code": null,
      "last_error_message": null,
      "next_attempt_at": null,
      "delivered_at": null,
      "created_at": "2026-09-26T09:00:00.000Z"
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 20,
    "total": 1,
    "total_pages": 1
  }
}

Errores posibles

GET/api/v3/webhooks/deliveries/{id}

Obtener una entrega de webhook

Parámetros

CampoTipoObligatorioDescripción
idstring · uuid · pathObligatorioEl id de la entrega.

Respuesta · 200

La entrega, incluidos la URL y el payload.

WebhookDeliveryDetail

CampoTipoDescripción
idstringIdentificador de la entrega (UUID).
eventstringTipo de evento de la entrega: payment.paid, payment.refunded o payment.failed. Un intento fallido no es definitivo; el pago sigue created y puede pagarse después.
statusstringEstado de la entrega.
pendingdeliveredfailed
payment_codestring | nullCódigo del pago relacionado, si existe.
attempt_countintegerNúmero de intentos de entrega hasta ahora.
last_status_codeinteger | nullEstado HTTP del último intento.
last_errorstring | nullError de entrega sin procesar heredado; usa last_error_code y last_error_message.
last_error_codestring | nullCódigo de error de entrega estable y legible por máquina.
invalid_webhook_targetwebhook_target_private_networkwebhook_environment_invalidwebhook_signing_unavailablewebhook_response_unsuccessfulwebhook_egress_proxy_unreachablewebhook_unreachablewebhook_delivery_failed
last_error_messagestring | nullMensaje de error de entrega breve y legible, seleccionado mediante Accept-Language.
next_attempt_atstring · date-time | nullCuándo está programado el siguiente reintento (UTC).
delivered_atstring · date-time | nullCuándo se entregó (UTC).
created_atstring · date-timeFecha y hora de creación del registro (UTC).
urlstringTu URL de webhook para esta entrega.
payloadobject | nullEl cuerpo JSON que se envió.

Respuesta · Ejemplo

{
  "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
  "event": "payment.paid",
  "status": "pending",
  "payment_code": null,
  "attempt_count": 1,
  "last_status_code": null,
  "last_error": null,
  "last_error_code": null,
  "last_error_message": null,
  "next_attempt_at": null,
  "delivered_at": null,
  "created_at": "2026-09-26T09:00:00.000Z",
  "url": "string",
  "payload": null
}

Errores posibles

POST/api/v3/webhooks/deliveries/{id}/retryRequiere Idempotency-Key

Reintentar una entrega fallida

Parámetros

CampoTipoObligatorioDescripción
idstring · uuid · pathObligatorioEl id de la entrega.

Respuesta · 200

Entrega fallida vuelta a encolar. Una repetición idempotente idéntica devuelve la respuesta original de encolado sin un nuevo reintento.

Objeto: WebhookDeliveryDetail (campos en Obtener una entrega de webhook).

Respuesta · Ejemplo

{
  "id": "9B2E6F3A-0C1D-4E5F-8A7B-000000000001",
  "event": "payment.paid",
  "status": "pending",
  "payment_code": null,
  "attempt_count": 1,
  "last_status_code": null,
  "last_error": null,
  "last_error_code": null,
  "last_error_message": null,
  "next_attempt_at": null,
  "delivered_at": null,
  "created_at": "2026-09-26T09:00:00.000Z",
  "url": "string",
  "payload": null
}

Errores posibles

Errores de entrega

last_error es un campo heredado; usa last_error_code en integraciones nuevas.

CampoDescripción
invalid_webhook_targetEl destino del webhook no es válido.
webhook_target_private_networkEl destino del webhook se resuelve a una red privada.
webhook_environment_invalidEl entorno del webhook no es válido.
webhook_signing_unavailableNo se pudo firmar el webhook.
webhook_response_unsuccessfulEl destino devolvió una respuesta que no es 2xx.
webhook_egress_proxy_unreachableNo se puede acceder al proxy de salida de la entrega.
webhook_unreachableNo se puede acceder al destino del webhook.
webhook_delivery_failedLa entrega del webhook falló.

Estado del servicio y mantenimiento

Algunos servicios pueden ponerse en mantenimiento de forma temporal. Solo se ven afectadas las operaciones nuevas; esta sección explica qué se detiene, qué sigue funcionando y cómo consultar el estado.

GET/api/v3/service-statusPúblico

Obtener el estado del servicio

Respuesta · 200

Servicios en mantenimiento (la lista puede estar vacía).

CampoTipoObligatorioDescripción
dataServiceStatusItem[]ObligatorioServicios que están en mantenimiento ahora mismo; una lista vacía significa que no hay ninguno.

ServiceStatusItem

CampoTipoObligatorioDescripción
servicestringObligatorioCódigo del servicio: api_collection (pagos creados a través de la API y sus páginas de pago), withdrawals (solicitudes de retiro) o uno de link_collection, storefront, usdt_sales y balance_load (otros servicios de la plataforma).
api_collectionlink_collectionwithdrawalsstorefrontusdt_salesbalance_load
untilstring · date-time | nullObligatorioHora estimada de regreso (UTC, ISO-8601), o null. Es solo una estimación: el mantenimiento no termina por sí solo y, una vez pasada esa hora, el campo es null.
notestring | nullObligatorioMensaje corto en texto plano del operador de la plataforma, o null.
maxLength 240

Respuesta · Ejemplo

{
  "data": [
    {
      "service": "api_collection",
      "until": "2026-10-01T12:00:00Z",
      "note": "Planned maintenance."
    }
  ]
}

Otras respuestas

  • 429Se superó el límite de solicitudes.

Errores posibles

Paginación

Los endpoints de listado aceptan page (por defecto 1) y per_page (por defecto 20, máximo 100) y devuelven data y meta.

PaginationMeta

CampoTipoObligatorioDescripción
pageintegerObligatorioNúmero de página (empieza en 1).
per_pageintegerObligatorioElementos por página (1–100).
totalintegerObligatorioTotal de registros coincidentes.
total_pagesintegerObligatorioceil(total / per_page).

Probar las operaciones de la cuenta

El saldo, los reembolsos, los retiros y las disputas funcionan en sandbox con los mismos endpoints, cuerpos y códigos de error que en producción.

  • Los pagos de sandbox pasan de inmediato a available_amount, sin esperar a una fecha valor.
  • Las solicitudes de reembolso y de retiro se resuelven de inmediato. La cabecera X-CAV-Sandbox-Scenario elige el resultado.
  • Las disputas vienen del banco, así que en sandbox creas una con POST /api/v3/sandbox/disputes.

Revisa las pruebas de reembolsos, retiros y disputas en “Operaciones Sandbox”.

Elegir el resultado

Las solicitudes de reembolso y de retiro usan los mismos endpoints y cuerpos que en producción. Para elegir el resultado, añade la cabecera opcional X-CAV-Sandbox-Scenario. No forma parte de la firma. Con una clave de producción la cabecera se rechaza con 422 (1000001), de modo que una prueba nunca pueda convertirse en una solicitud real.

X-CAV-Sandbox-Scenario

X-CAV-Sandbox-Scenario: rejected
EndpointValores de la cabeceraPor defectoEfecto
POST /api/v3/refundscompleted rejectedcompletedcompleted finaliza el reembolso y descuenta del saldo virtual; rejected registra el rechazo y no cambia nada.
POST /api/v3/withdrawalssent rejectedsentsent descuenta del saldo virtual y rellena tx_hash con un valor provisional; rejected libera el importe.
POST /api/v3/sandbox/disputesopen won lostopenSe indica en el cuerpo de la solicitud, no en una cabecera. open, won o lost.

Disputa de prueba

Las disputas proceden de las redes de tarjetas y no se pueden iniciar desde tu lado en producción. Es el único endpoint exclusivo de sandbox: crea una disputa de prueba para un pago de sandbox ya cobrado y devuelve el mismo objeto Dispute que en producción.

POST/api/v3/sandbox/disputesRequiere Idempotency-Key

Crear una disputa de sandbox para un pago de sandbox pagado

Cuerpo de la solicitud

CampoTipoObligatorioDescripción
payment_codestringObligatorioSustitúyelo por el código de un pago abonado creado con tu propia clave de sandbox.
maxLength 16
scenariostringOpcionalResultado que se registrará: open (por defecto) sigue abierta para pruebas; won y lost ya están resueltas.
openwonlost
reasonstringObligatorioCategoría del motivo de la disputa; los mismos valores que Dispute.reason.
fraudunauthorizedproduct_not_deliveredduplicateamount_mismatchother

Cuerpo de la solicitud · Ejemplo

{
  "payment_code": "ab34cdef",
  "scenario": "open",
  "reason": "fraud"
}

Respuesta · 201

Disputa registrada; una repetición idempotente devuelve la misma disputa.

Objeto: Dispute (campos en Listar disputas).

Respuesta · Ejemplo

{
  "id": "B5D4E456-EFC1-4EC2-A613-D64A16E45BD5",
  "service": "api",
  "amount": "250.00",
  "currency": "USD",
  "status": "open",
  "reason": "fraud",
  "reason_note": null,
  "occurred_on": "2026-09-30",
  "evidence_due_at": "2026-10-07T09:00:00.000Z",
  "evidence_submitted_at": null,
  "merchant_evidence_note": null,
  "merchant_evidence_submitted_at": null,
  "resolved_at": null,
  "created_at": "2026-09-30T09:00:00.000Z",
  "payment_code": "ab34cdef",
  "environment": "sandbox"
}

Errores posibles

Habla con tu gestor de cuenta sobre el terminal de producción y la prueba final de extremo a extremo. Contacto