Saltar al contenido

Idempotencia y reintentos

Los reintentos ante fallas de red son inevitables en una integración server-to-server. Esta página describe qué operaciones son seguras de reintentar y cómo evitar duplicados.

Control de duplicados

La API v1 no implementa un header Idempotency-Key. El control de duplicados es responsabilidad del integrador, siguiendo los patrones descritos en esta página.

Operaciones idempotentes por naturaleza

Estos endpoints producen el mismo resultado al ejecutarse N veces. Se pueden reintentar libremente:

  • Toda lectura: GET /v1/accounts, GET /v1/accounts/{id}, GET /v1/accounts/{id}/checklist, GET /v1/accounts/{id}/documents, GET /v1/catalogs/{...}.
  • DELETE de documento: DELETE /v1/accounts/{id}/documents/{document}. La segunda llamada devuelve 404 Not Found (el documento ya no existe), que su sistema debe tratar como éxito del DELETE original.

Operaciones no idempotentes (POST de creación)

Estos endpoints crean un recurso nuevo cada vez. Reintentar sin precaución puede generar duplicados:

  • POST /v1/accounts — crea un nuevo legajo (con todas sus secciones anidadas) en cada llamada.
  • POST /v1/accounts/{id}/documents — sube un documento nuevo en cada llamada.
  • POST /v1/accounts/{id}/hosted-flow/link — emite un magic-link nuevo. Excepción positiva: cada nuevo link borra al anterior del mismo (account, consumer), por lo que reintentar no deja varios links válidos en paralelo — pero sí múltiples filas en auditoría.

Patrón recomendado para reintentos

Para creación de legajos (POST /v1/accounts)

El bulk POST no es idempotente. Para evitar duplicados ante timeouts o errores transitorios de red:

  1. Persistí el resultado de la primera llamada antes de reintentar. Si su cliente HTTP recibió respuesta (status code, sea cual sea), guardá el account.id que vino en el body. Reintentá sólo si no hubo respuesta del servidor (timeout puro, connection reset).

  2. Usá el campo denomination como identificador humano del legajo para detectar duplicados manualmente. Antes de un reintento dudoso, listá los últimos legajos creados y revisá por denomination antes de volver a llamar:

    bash
    curl -H "Authorization: Bearer $TOKEN" \
      "https://compliance.quantian.ar/api/v1/accounts?per_page=20"
  3. Mantené una correlación 1:1 entre su id interno y el account.id en su propia base de datos. La API no expone hoy un campo external_reference reservado para mapping — está previsto como evolución de la spec, pero hasta entonces el control de duplicados queda del lado del cliente.

Para uploads (POST /v1/accounts/{id}/documents)

Antes de reintentar, consultá la lista de documentos del legajo:

bash
curl -H "Authorization: Bearer $TOKEN" \
  https://compliance.quantian.ar/api/v1/accounts/{id}/documents

Si el documento del tipo que iba a subir ya está presente (mismo document_classification_id, mismo original_filename), no reintentes. Si necesita reemplazarlo, primero borre el anterior con DELETE /v1/accounts/{id}/documents/{document}.

Backoff exponencial para 5xx y 429

text
intento 1: inmediato
intento 2: esperar 1s
intento 3: esperar 2s
intento 4: esperar 4s
intento 5: esperar 8s
máximo: 5 intentos

Respetá siempre el header Retry-After cuando esté presente — sobrescribe la fórmula de backoff:

http
HTTP/1.1 429 Too Many Requests
Retry-After: 30

Significa: no reintentes antes de 30 segundos.

Rate limiting

La API v1 tiene un límite de 120 requests por minuto, compartido entre todos los tokens generados. Si necesitás aumentar el límite de llamadas, contactate con tu ejecutivo. Los headers de respuesta incluyen:

  • X-RateLimit-Limit: cuota total por minuto.
  • X-RateLimit-Remaining: requests restantes en la ventana actual.
  • Retry-After (sólo en 429): segundos hasta resetear.

Si su integración necesita un límite mayor, contactá al soporte técnico de Quantian para solicitar un ajuste.

Atomicidad del bulk POST

El bulk POST POST /v1/accounts ejecuta todas las inserts (legajo + human/company + direcciones + FATCA + SoF + cuestionario + UBOs + CBUs + cotitulares) dentro de una sola transacción. Esto significa que:

  • Si toda la validación pasa, el legajo y todas sus sub-entidades quedan persistidas atómicamente.
  • Si cualquier validación falla, no se crea nada — recibe 422 y la base queda intacta.

No hay un estado intermedio donde, por ejemplo, el Human exista pero su residential_address falte. Eso simplifica el modelo mental para reintentos: o todo, o nada.