Volver a Documentacion

Idempotencia

Cada endpoint M2M que cambia estado acepta un encabezado Idempotency-Key. Enviar la misma clave dos veces retorna la respuesta original — nunca una operación duplicada. Este documento especifica el contrato.


Inicio rápido

KEY=$(uuidgen)

# Primera llamada: crea la orden
curl -X POST "https://sandbox-api.ariari.xyz/api/v1/fxorder/createOrder" \
  -H "Ocp-Apim-Subscription-Key: $SU_CLAVE" \
  -H "Idempotency-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{...}'
# Retorna: 201 Created + reference_code FXT-20260428-000123

# Segunda llamada (reintento por hipo de red): retorna la MISMA respuesta, sin duplicado
curl -X POST "https://sandbox-api.ariari.xyz/api/v1/fxorder/createOrder" \
  -H "Ocp-Apim-Subscription-Key: $SU_CLAVE" \
  -H "Idempotency-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{...}'
# Retorna: 201 Created + reference_code FXT-20260428-000123 (igual)

Endpoints que requieren `Idempotency-Key`

Endpoint Requerido Razón
POST /api/v1/fxorder/createOrder Crea una orden FX — duplicado podría doble-debitar
POST /api/v1/transfer/createTransfer Crea una transferencia — mismo riesgo
POST /api/v1/external-accounts/register Registro idempotente en reintento
Endpoints de lectura (getQuote, getStatus, getHistory) No Solo lectura; seguro reintentar sin clave

Si usted omite Idempotency-Key en un endpoint de creación, la solicitud retorna 422 Unprocessable Entity con error_code: BFF-IDEM-001.


Formato de la clave

Restricción Valor
Formato UUID v4 (recomendado) o cualquier cadena que cumpla ^[a-zA-Z0-9_-]{1,128}$
Longitud 1–128 caracteres
Alcance Por suscripción. Dos socios usando la misma cadena no colisionan.
Generación Lado cliente. Nunca reutilice una clave entre operaciones lógicamente distintas.

Genere claves frescas del lado cliente. UUID v4 es la opción predeterminada más segura. ARi recomienda uuidgen (Linux/macOS) o crypto.randomUUID() (Node 19+).


Retención

Las claves de idempotencia se retienen durante 24 horas después de la solicitud original. Después de 24 h, la clave es purgada. Un reintento con una clave de 25 horas crea una nueva operación (sin detección de duplicado).

Implicación práctica: complete su secuencia de reintentos dentro de las 24 h de la solicitud original. Reintentos con demora larga deberían generar una clave fresca.


Semántica de conflicto — misma clave, cuerpo distinto

Enviar el mismo Idempotency-Key con un cuerpo de solicitud distinto dentro de la ventana de 24 h retorna:

HTTP/1.1 409 Conflict
Content-Type: application/problem+json

{
  "type": "about:blank",
  "title": "Conflict",
  "status": 409,
  "error_code": "DB-IDEM-409",
  "detail": "Idempotency-Key ya utilizada con un payload de solicitud distinto. Genere una clave fresca.",
  "trace_id": "..."
}

Esto protege contra errores del lado cliente donde la misma clave se reutiliza para operaciones lógicamente distintas. Siempre genere una clave fresca para cada nueva operación; solo reutilice una clave al reintentar la misma solicitud exacta tras un fallo transitorio.


Matriz de decisión de reintentos

Cuando una solicitud falla, esta matriz le indica si debe reintentar con la misma clave o generar una nueva.

Estado Clase ¿Reintentar? ¿Con la misma clave?
200, 201 Éxito No reintente n/a
400 Error de esquema (su solicitud está mal formada) No reintente Corrija la solicitud primero
401 Auth (clave de suscripción inválida) No reintente Corrija la clave
403 Prohibido (alcance ausente) No reintente Contacte ARi
404 No encontrado (p. ej. reference_code desconocido) No reintente Corrija la búsqueda
409 Conflicto (Idempotency-Key reutilizada con cuerpo distinto) No reintente Genere clave fresca
422 Error semántico (p. ej. cotización expirada) A veces — lea error_code Misma clave OK si corrige semánticamente
429 Limitado por tasa Sí, después de Retry-After Misma clave
500, 502, 503, 504 Error de servidor Sí, backoff exponencial Misma clave

Por qué la misma clave para reintentos 5xx/429: el servidor podría haber procesado la solicitud original aunque la respuesta no haya llegado a usted. Reutilizar la clave permite al servidor retornar la respuesta original (o detectar el duplicado en vuelo). Sin idempotencia, su reintento crea una operación duplicada.


Específico de FX: interacción con ventana de bloqueo de tasa

Las llamadas a createOrder de FX que incluyen un quote_id de una cotización bloqueada (getQuote con lock_rate=true) tienen una restricción temporal adicional: la cotización bloqueada expira después de 60 segundos (retornado en expires_at en la respuesta de cotización).

Matriz de decisión para reintentos de createOrder con cotización bloqueada:

Escenario ¿Reintentar? ¿Misma clave? Notas
5xx dentro de la ventana expires_at Misma clave La solicitud original probablemente tuvo éxito; reutilice la clave para recuperar la respuesta original.
5xx después de que expires_at expiró No Genere cotización fresca + clave nueva Cotización expirada; aunque el servidor haya procesado su solicitud original, no puede reintentarla con seguridad. Re-cotice y re-ordene.
422 error_code: DB-FX-410 ("Cotización expirada") No Obtenga una nueva cotización Auto-explicativo.
409 Conflict No Genere clave fresca El cuerpo cambió; idempotencia descarta la reutilización.

En caso de duda, trate cualquier reintento post-expiración como una nueva operación: cotización fresca, clave de idempotencia fresca.


Reutilización del campo de monto XOR en reintento

La forma del cable FX usa XOR para los campos de monto — los clientes envían exactamente uno de origin_amount (Tengo) o destination_amount (Quiero); nunca ambos. Cuando reintenta con la misma Idempotency-Key, el mismo lado XOR debe usarse.

  • Original: origin_amount: 1000, Idempotency-Key: K1 → respuesta guardada
  • Reintento: destination_amount: 50000, Idempotency-Key: K1409 Conflict (forma de solicitud distinta)

ARi trata el cuerpo de la solicitud — incluyendo qué lado XOR lleva el monto — como parte de la verificación hash-de-payload de la clave de idempotencia.


Mejores prácticas

  1. Genere claves del lado cliente, persístalas. No pierda la clave entre el primer intento y un reintento. Si su cliente se cae, recuperar la clave desde almacenamiento durable le permite reintentar con seguridad.
  2. No comparta claves entre operaciones. Una operación = una clave. Nunca etiquete dos intenciones distintas con el mismo valor de clave.
  3. No reutilice claves después de éxito explícito. Una vez que recibe una respuesta 200/201, esa clave está "quemada" — generar una nueva clave para la siguiente operación es más barato que arriesgar deduplicación involuntaria.
  4. Agregue un prefijo reconocible para depuración. ARi acepta cualquier cadena ^[a-zA-Z0-9_-]{1,128}$. Su equipo de operaciones se lo agradecerá cuando puedan hacer grep de partner-fx- en los logs.

Vea también