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 |
Sí | Crea una orden FX — duplicado podría doble-debitar |
POST /api/v1/transfer/createTransfer |
Sí | Crea una transferencia — mismo riesgo |
POST /api/v1/external-accounts/register |
Sí | 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 |
Sí | 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: K1→ 409 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
- 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.
- No comparta claves entre operaciones. Una operación = una clave. Nunca etiquete dos intenciones distintas con el mismo valor de clave.
- 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. - 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 hacergrepdepartner-fx-en los logs.
Vea también
- Autenticación — encabezados requeridos
- Errores — códigos
BFF-IDEM-001,DB-IDEM-409 - Órdenes FX — mecánica de la ventana de bloqueo de tasa