Ir al contenido

Refunds

Un Refund permite devolver al comprador la totalidad o parte del importe de una Transacción correcta. El reembolso se realiza mediante el mismo método de pago que el pago original: no se puede reembolsar por otro canal.

Puede realizar varios reembolsos parciales sobre una misma transacción, siempre que el total reembolsado no supere el importe original.

Plazos de reembolso del operador

Los plazos de devolución de los fondos dependen del operador: Mobile Money (Airtel, Moov): 24–72 h. Tarjeta bancaria: 3–10 días hábiles según el banco emisor. PayPal: de instantáneo a 24 h. Sangho envía un webhook refund.succeeded en cuanto el operador lo confirma.

Ciclo de vida

pending→processing→succeeded / failed / cancelled / expired
EstadoSignificado
pendingReembolso creado, a la espera de procesamiento.
processingTransmitido al operador, en curso de procesamiento.
succeededFondos devueltos al comprador.
failedFallo del reembolso en el operador. Los fondos no se cargan.
cancelledReembolso cancelado antes de su procesamiento (mediante /cancel/).
expiredPlazo de procesamiento superado: los fondos se devuelven a su saldo.

Endpoints

MéthodeEndpointDescription
POST/refunds/Crear un reembolso
GET/refunds/Listar los reembolsos
GET/refunds/{id}/Recuperar un reembolso
POST/refunds/{id}/cancel/Cancelar un reembolso pending

Esquema del objeto

ResponseObjeto Refund
json
{
  "id": "refd_xxxxxxxxxxxx",
  "object": "refund",
  "transaction": "trans_3Nx8mLKZ2eZvKYlo28m",
  "amount": 5000,
  "currency": "XAF",
  "status": "succeeded",
  "reason": "customer_request",
  "description": "Remboursement partiel — article indisponible",
  "failure_reason": null,
  "payment_method_type": "mobile_money",
  "refunded_at": "2026-03-16T09:00:00Z",
  "metadata": {
    "ticket": "SUPPORT-00412"
  },
  "livemode": true,
  "created_at": "2026-03-15T14:30:00Z",
  "updated_at": "2026-03-16T09:00:00Z"
}

Crear un reembolso

Inicia un reembolso para una transacción existente. La transacción debe estar en estado completed. Un reembolso parcial no modifica el estado de la transacción original: solo un reembolso total pasa la transacción a refunded.

POSTCuerpo de la solicitud
transactionRequis
stringtrans_...ex :trans_3Nx8mLKZ2eZvKYlo28m

ID de la Transacción que se va a reembolsar. La transacción debe estar en estado completed.

Una transacción en estado pending, failed o disputed no se puede reembolsar. Para cancelar un pago aún no procesado, utilice POST /payment-intents/{id}/cancel/.

amountOptionnel
integercentimes

Importe que se va a reembolsar, en céntimos. Si se omite, reembolsa la totalidad del importe reembolsable de la transacción.

En savoir plus

El importe no puede superar transaction.amount - importes_ya_reembolsados. Puede acumular varios reembolsos parciales. Ejemplo: transacción de 15 000 XAF → reembolso de 5 000 y, después, se acepta un segundo de 3 000 (quedan: 7 000).

reasonOptionnel
string

Motivo del reembolso. Se utiliza para los informes internos y el cumplimiento normativo.

En savoir plus

Valores aceptados: duplicate (pago duplicado), fraudulent (transacción fraudulenta), customer_request (solicitud del cliente), product_issue (problema con el producto), service_not_rendered (servicio no prestado). El motivo se incluye en el webhook refund.succeeded.

descriptionOptionnel
string

Nota interna sobre el reembolso. No es visible para el comprador.

En savoir plus

Ideal para hacer referencia a un ticket de soporte, a una decisión interna o a una comunicación con el cliente.

metadataOptionnel
object

Datos libres asociados al reembolso. Se devuelven en el webhook refund.succeeded.

Utilice siempre una Idempotency-Key

Una doble llamada sin Idempotency-Key crea dos reembolsos distintos. Con una clave idéntica, Sangho devuelve el reembolso existente sin crear uno nuevo. Utilice un UUID único por cada intento de reembolso.

Crear un reembolso

bash
curl -X POST https://api.sangho.ga/v1/refunds/ \
  -H "Authorization: Bearer sk_prod_xxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: refund-trans_xxx-$(date +%s)" \
  -d '{
    "transaction": "trans_3Nx8mLKZ2eZvKYlo28m",
    "amount": 5000,
    "reason": "customer_request",
    "description": "Remboursement partiel — article indisponible",
    "metadata": { "ticket": "SUPPORT-00412" }
  }'
Response201 Created — Reembolso iniciado
El reembolso se crea en estado processing. El webhook refund.succeeded confirmará la devolución de los fondos.
json
{
  "id": "refd_xxxxxxxxxxxx",
  "object": "refund",
  "transaction": "trans_3Nx8mLKZ2eZvKYlo28m",
  "amount": 5000,
  "currency": "XAF",
  "status": "processing",
  "reason": "customer_request",
  "description": "Remboursement partiel — article indisponible",
  "failure_reason": null,
  "metadata": { "ticket": "SUPPORT-00412" },
  "created_at": "2026-03-15T14:30:00Z",
  "updated_at": "2026-03-15T14:30:00Z"
}
Response400 — Importe excedente
El importe solicitado supera lo reembolsable. Compruebe el importe ya reembolsado antes de enviarlo.
Recupere la transacción mediante GET /transactions/{id}/ y compruebe amount_refunded para conocer el importe que aún se puede reembolsar.
json
{
  "error": {
    "type": "validation_error",
    "code": "refund_amount_exceeds_available",
    "message": "Le montant du remboursement dépasse le montant remboursable (10000 XAF restants).",
    "param": "amount"
  }
}
Response409 — Transacción no reembolsable
La transacción está en un estado que no permite el reembolso (failed, pending, disputed).
Solo se pueden reembolsar las transacciones en estado completed.
json
{
  "error": {
    "type": "conflict_error",
    "code": "transaction_not_refundable",
    "message": "Cette transaction est en statut failed et ne peut pas être remboursée."
  }
}