Saltar al contenido principal

Idempotencia

POST /orders mueve dinero, así que es el único endpoint donde un reintento no puede significar un segundo pago. Para eso está X-Idempotency-Key, y es obligatorio — no es un nice-to-have.

X-Idempotency-Key: 0190f9b2-3c4d-4e5f-8a6b-7c8d9e0f1a2b

Si lo omites, la request nunca llega a la lógica de órdenes:

{
"message": "\"Missing required request parameters: [X-Idempotency-Key]\"",
"requestId": "92885917-5fb9-41d1-8272-70cfdefe6c23"
}

Ese body lo devuelve el API gateway, no el servicio: el header está declarado como requerido en el borde, así que la request se rechaza antes de que corra lógica de órdenes. Es la única forma de error con requestId y sin statusCode — cita ese id si abres un ticket.

También es tu referencia​

La key es un string opaco generado por el cliente — el formato lo eliges tú y lo reenviamos sin tocarlo. Vuelve en la orden como idempotency_key, que es el handle con el que después encuentras esa orden:

GET /orders?idempotency_key=0190f9b2-3c4d-4e5f-8a6b-7c8d9e0f1a2b

Así que elige algo con sentido y único en tu sistema — el id de una factura, el id de una corrida de pagos, un UUID que guardas junto al pagadero. Si generas una key al azar y la descartas, descartaste tu propia referencia.

Qué pasa si repites​

EnvíasResultado
Misma key, misma request201 con la orden original. No se crea nada nuevo.
Misma key, request distinta409 B2B_IDEMPOTENCY_CONFLICT
Key nuevaUna orden nueva

La primera fila es el comportamiento que quieres después de un timeout, una conexión cortada, o cualquier respuesta que no pudiste leer. Repite la request idéntica con la key idéntica y o creas la orden (si el primer intento nunca llegó) o recibes la que ya tienes.

La segunda fila es señal de un bug, no algo para esquivar: la misma key llegó con datos distintos. No lo reintentes con una key nueva hasta saber cuál de los dos payloads era el que querías.

La otra cosa de uso único​

Las keys de idempotencia no son la única regla de unicidad de POST /orders, y la otra se comporta distinto:

{
"code": "B2B_QUOTATION_ALREADY_USED",
"category": "PERMANENT",
"message": "La cotización referenciada ya respalda otra operación: es de uso único. NO reintente con la misma cotización. Verifique el estado de la operación existente antes de crear una nueva; si corresponde, genere una cotización nueva."
}

Una cotización es de uso único: respalda exactamente una orden, para siempre, sin importar cómo terminó esa orden. Entonces:

  • Nunca reintentes con el mismo quotation_id. Falla idéntico siempre.
  • Antes de crear una orden de reemplazo, busca la que ya existe. Ya hay una operación en curso o completada contra esa cotización, y crear una segunda es la forma de pagarle dos veces al beneficiario.

Un intento nuevo significa una cotización nueva — lo que también significa una tasa nueva, porque las cotizaciones expiran.

Ningún otro endpoint la usa​

X-Idempotency-Key solo aplica a POST /orders. Las lecturas son idempotentes por naturaleza, y POST /quotations es seguro de repetir: una cotización de más no cuesta ni compromete nada hasta que una orden la referencia.