Paginación por cursor
Todo endpoint de lista (GET /v1/portfolios, /debtors, /debts, /calls,
/payments, /promises, /campaigns) devuelve la misma forma:
limit: cuántos ítems pediste (o el default). Acepta de 1 a 100:0o un valor negativo vuelve al default (50) y uno mayor a 100 se recorta a 100, sin error. Uno que no sea numérico (limit=abc) sí rechaza el request, con400yvalidation_error. El default es 50.pagination.hasMore: sitrue, hay más páginas.pagination.nextCursor: un cursor opaco — no intentes interpretar su contenido ni construirlo a mano. Para la próxima página, mandalo tal cual como el parámetrocursor. Un cursor está atado al endpoint que lo emitió: usarlo contra otro recurso no devuelve un error, sino una página sin sentido.
hasMore es false, nextCursor es null y ya recorriste todo.
Orden de las listas
El orden no es configurable en v1 (no hay parámetrosort), y cada recurso
usa un criterio estable para que avanzar con cursor nunca te salte ni te
repita un ítem:
Filtros y valores por defecto
Cada lista acepta filtros propios (están en la pestaña Referencia), pero hay comportamientos que no se deducen del nombre del parámetro:status: un valor o varios
- Un solo valor:
debts. Una lista separada por comas responde400 validation_error. - Uno o varios separados por coma:
debtors,calls,promises,campaigns(status=pending,partial).callstambién aceptadirectioncon dos valores (inbound,outbound).
400 validation_error y el mensaje nombra el
parámetro y los valores permitidos. Nunca devuelve una lista vacía.
from y to
Los dos recursos con rango de fechas los interpretan distinto, porque sus
fechas se guardan distinto:
- Llamadas:
from/tose interpretan como fecha o fecha y hora ISO 8601. Sitoviene sin hora (to=2026-01-31), se toma hasta el final de ese día en UTC. - Pagos:
from/tose comparan como texto contrapaymentDate, que puede venir como fecha (2026-01-31) o como fecha y hora (2026-01-31T14:45:00Z) según cómo se registró el pago.from=2026-01-01incluye todo ese día;to=2026-01-31deja afuera los pagos de ese día que tengan hora. Para incluirlos, mandáto=2026-01-31T23:59:59Z.
Un
from o to que no sea una fecha ISO 8601 parseable (from=ayer)
responde 400 con el código validation_error, en los dos recursos.createdAt,
updatedAt, connectedAt y demás timestamps reales siempre son fecha y hora
(date-time). En cambio dueDate, issueDate, paymentDate,
promiseDate y fulfillmentDate son columnas de texto que reflejan lo que se
cargó: pueden ser solo fecha (YYYY-MM-DD) o fecha y hora. No asumas hora en
esos campos; la Referencia describe, para cada uno, qué puede llegar a contener.
Formato de error
Cualquier error —4xx o 5xx— responde con el mismo sobre:La API devuelve
message en inglés, siempre: es para una persona leyendo
logs, no para tu código. Ramificá la lógica de tu integración por code,
nunca por message.requestId identifica el request — incluilo si le escribís a soporte sobre
un error puntual. Los errores de validación (validation_error) además
pueden traer un array issues con el detalle de qué campo falló.
Códigos de error
Un
GET /v1/debtors/:id sobre un deudor de otra organización responde
404 not_found, igual que si no existiera: la API pública nunca confirma que
un recurso ajeno existe.
Tope de lotes de escritura
Los endpoints que aceptan varios ítems en un solo request tienen su propio tope, distinto del rate limit:POST /v1/portfolios/:id/debtors acepta hasta
500 deudores por lote y 5 MB de cuerpo. Superar cualquiera de los dos
responde 413 payload_too_large. Un cuerpo de más de 6 MB cruza el límite
general de Lambda y responde igual 413, pero con el sobre crudo de la
plataforma, no el de la API (ver el detalle en
Deudores).
Límite de uso (rate limit)
Cada clave tiene un límite de 300 unidades por minuto. Para casi toda la API, cada request cuesta 1 unidad: el límite es, en la práctica, de 300 requests por minuto. Cada respuesta trae dos headers con tu consumo:POST /v1/portfolios/:id/debtors, el endpoint de
escritura masiva de deudores: ahí una sola request puede mover hasta 500
deudores con sus deudas, así que cobrarla como una unidad fija no acotaba
nada. Ese endpoint cuesta 1 unidad cada 50 deudores del lote, con un
mínimo de 1 unidad. Un lote de 500 deudores cuesta 10 unidades; un lote de 20
sigue costando 1. X-RateLimit-Remaining en la respuesta de ese endpoint ya
refleja el cobro del lote entero, no de una unidad fija.
Si superás el límite, la respuesta es 429 rate_limited con un header
adicional:
Retry-After son los segundos que faltan para que se abra la próxima
ventana. La ventana es fija (por minuto de reloj), no una ventana deslizante.
En POST /v1/portfolios/:id/debtors, un lote que cruza el límite responde
429 después de haber sido cobrado: ese lote no se procesa, pero las
unidades que consumió ya están descontadas de la ventana.
Cómo manejarlo
- Mirá
X-RateLimit-Remainingpara frenar antes de pegar contra el límite, en vez de esperar al 429. - Ante un
429, esperá los segundos deRetry-Afterantes de reintentar — no hagas backoff exponencial sobre una ventana fija, sólo generás más espera de la necesaria. - Si tu integración necesita más de 300 req/min de forma sostenida, hablalo con tu contacto en Mozart antes de paralelizar requests para esquivar el límite.