Skip to main content
Una deuda (Debt) es un cargo puntual a un deudor conocido: un importe fijo que se cobra a una persona o entidad identificada, con una fecha de vencimiento y medios de pago configurables. Es el caso de uso más común de la API. Tú indicas quién paga, cuánto y cuándo vence. TapiPay resuelve internamente toda la complejidad (tu organización, las modalidades y los datos internos del sistema de cobranzas) y te devuelve un contrato limpio con la URL de pago lista para compartir.

Cuándo usar una deuda

Deuda

Un cobro único a alguien que conoces: una factura, una cuota, un servicio puntual.

Suscripción

Si el cobro se repite en el tiempo (mensualidades, cuotas).

Liga de pago

Si no conoces al deudor de antemano (donaciones, ventas sueltas).

Crear una deuda

Para crear una deuda necesitas, como mínimo, identificar al deudor, el monto y la fecha de vencimiento. El header opcional Idempotency-Key se usa como externalRequestId de la deuda, y el debtId resultante es debt_<key> (en el ejemplo, debt_INV-2026-001). Si no lo envías, el backend genera el externalRequestId. Ver Idempotencia.

Identificar al deudor

Debes enviar uno de estos dos campos (no ambos, no ninguno): Ver Contactos para el detalle del deudor reutilizable.
Un contacto puede tener más de un identificador. Si lo referencias por uno secundario, la deuda se crea con su identificador principal y contact.externalClientId en la respuesta devuelve ese valor, no el que enviaste.

Campos principales

number
requerido
Monto en pesos, con hasta 2 decimales (mínimo 0.01). Por ejemplo, 1500.50 equivale a $1,500.50 MXN.
string
requerido
Fecha de vencimiento en formato YYYY-MM-DD. Debe ser una fecha de calendario válida (2026-02-30 devuelve 400). No se valida que sea futura.
string
predeterminado:"MXN"
Código de moneda. Valores permitidos: MXN, ARS, PEN, COP, CLP, USD. Default MXN.
string
Descripción visible para el deudor. Debe ser un string (otro tipo devuelve 400).
string
ID de un producto existente en Tapi, con formato prd_<número> (por ejemplo, prd_12985). Otro formato devuelve 400 INVALID_REQUEST. Excluyente con externalProductId (enviar los dos devuelve 400); no crea productos. Ver Productos.
string
Tu identificador de un producto existente. Excluyente con productId; no crea productos. No admite los caracteres ', ", \, ; (400).
boolean
predeterminado:"true"
Habilita pagos parciales. Con true, la deuda pasa a PARTIALLY_PAID hasta saldarse. Solo acepta true o false literal: "true", 1, etc. devuelven 400 con details[].
boolean
predeterminado:"true"
Si es false, la deuda no puede pagarse después del dueDate. Solo acepta true o false literal, igual que allowPartialPayments.
object
Datos propios de tu sistema que quieras guardar en la deuda. Debe ser un objeto plano (un escalar, como un string o un número, devuelve 400) y no puede usar las claves reservadas que TapiPay escribe internamente: description, paymentMethods, productName, externalProductId, debtExpirationDate, overduePayment, allowPartialPayments, recurringDebt, debtReference. Si aparece alguna, la API responde 400 INVALID_REQUEST con details[].field = additionalData.
POST /v2/debts solo acepta estos campos en el body: externalClientId, contactData, amount, currency, dueDate, description, allowOverduePayment, allowPartialPayments, additionalData, productId, externalProductId. Cualquier otro, incluidos autopay, paymentMethods, productName y paymentMethod, devuelve 400 INVALID_REQUEST con el campo en details[].field. Un array JSON en la raíz (sin el sobre { "debts": [...] }) también devuelve 400.
La deuda no declara medio de pago: el cobro automático lo gobierna el medio de pago default que cada usuario registra una sola vez. Referenciar un producto (productId/externalProductId) es lo que activa esa posibilidad. Los campos paymentMethods y autopay aplican solo a suscripciones. Ver Débito automático para el detalle completo.
Nunca envías ni recibes datos internos del sistema (organización, modalidades, generationData). Trabajas solo con conceptos de negocio.

La respuesta

La respuesta de creación y de consulta incluye paymentUrl (la URL lista para compartir con tu deudor; viene en null solo si falla la integración con el portal) y amountPaid (el acumulado pagado). La creación también incluye autopay (si el cobro automático quedó activo) y, cuando es false, el motivo en autopayReason. Si la deuda no referencia un producto, el motivo es NO_PRODUCT. Ver Débito automático.
  • debtId es siempre debt_ + externalRequestId.
  • description se devuelve en la creación y en las lecturas (GET /debts/{id}, GET /debts) cuando la deuda tiene una; si no, el campo no viene.
  • contact.contactId trae el prefijo con_, también cuando el contacto se crea en línea.
  • Las fechas date-time vienen en UTC con milisegundos y Z. Ver Convenciones de la API.
El paymentUrl es un deep link que apunta directo a esa deuda puntual. Es una URL opaca: compártela tal cual con tu deudor, no la parsees ni la construyas a mano (su formato puede cambiar). Las deudas generadas por una suscripción también traen su propio deep link (lo ves en GET /subscriptions/{id}/debts).

Ciclo de vida

Consultar y listar

GET /debts/{id} acepta el debtId (debt_...) o el externalRequestId sin prefijo. También devuelve deudas canceladas (status: CANCELLED). GET /debts devuelve tus deudas de la más reciente a la más antigua, paginadas con page y limit (ver Convenciones de la API). No incluye deudas canceladas: para leer una cancelada, usa GET /debts/{id}.
  • Aceptan una fecha (YYYY-MM-DD) o un date-time RFC 3339. Otro formato devuelve 400.
  • Una fecha sola cubre el día UTC completo, incluido en los dos extremos: createdAtFrom=2026-09-24 empieza a las 00:00:00.000Z y createdAtTo=2026-09-24 termina a las 23:59:59.999Z. Con la misma fecha en los dos, obtienes las deudas de ese día.
  • Un date-time se convierte a UTC y la precisión del filtro es diaria: se incluye el día UTC completo que lo contiene. Un createdAtTo exactamente a las 00:00:00Z no incluye ese día.
  • Sin createdAtTo, el rango llega hasta hoy. Un createdAtFrom futuro sin createdAtTo devuelve una lista vacía.
  • createdAtFrom posterior a createdAtTo devuelve 400.

Actualizar y cancelar

Solo se puede actualizar una deuda en estado PENDING. Intentarlo en otro estado, incluida una deuda cancelada, devuelve 422 BUSINESS_RULE_VIOLATION.Campos editables: amount y dueDate. Envía al menos uno: un body vacío o cualquier otro campo devuelve 400 INVALID_REQUEST. dueDate va en formato YYYY-MM-DD y debe ser una fecha de calendario válida. companyCode en el body se toma como contexto, no como campo a modificar.El PATCH no modifica allowPartialPayments. La respuesta trae dueDate como YYYY-MM-DD y amountPaid con el monto pagado actual.
Se puede cancelar una deuda en estado PENDING, PARTIALLY_PAID u OVERDUE. No se puede cancelar una deuda ya PAID o CANCELLED: cancelarla por segunda vez devuelve 422 BUSINESS_RULE_VIOLATION.El endpoint no lleva body (si envías uno, se ignora). La deuda cancelada se sigue leyendo con GET /debts/{id}, pero ya no aparece en GET /debts.

Errores

Además del catálogo general, estas son las causas más comunes de error en los endpoints de deudas y el error.code que devuelve cada una. El error.message es informativo y puede cambiar: decide tu lógica con el status, error.code y error.details[].field, no con el texto. Algunos mensajes reales, solo como referencia: Cuando la falla no es de validación, la API conserva el status real en lugar de convertirlo siempre en 500, así que también puedes recibir un 409 RESOURCE_CONFLICT o un 422 BUSINESS_RULE_VIOLATION fuera de los casos de la tabla. Estos errores no traen error.details, porque no señalan un campo puntual de tu payload.

Endpoints

Pruébalo en el API Reference

Explora cada endpoint con su playground interactivo.