Saltar al contenido principal

Idempotencia

La API soporta idempotencia para reintentar solicitudes de forma segura, sin ejecutar la misma operación dos veces. Útil cuando una llamada se interrumpe en tránsito y no recibes respuesta — por ejemplo, una solicitud para crear una suscripción que falla por un error de red puede reintentarse con la misma clave, garantizando que solo se cree una suscripción.

Cómo usarlo​

Envía la cabecera X-Idempotency-Key: <clave> en cualquier solicitud POST, PUT o PATCH. La clave es opaca y la generas en tu lado. Recomendamos UUID v4 u otra cadena aleatoria con entropía suficiente para evitar colisiones.

curl -i \
-H "Authorization: Bearer $KOBANA_TOKEN" \
-H 'Content-Type: application/json' \
-H 'X-Idempotency-Key: 8c0f5d6e-3f8b-4cb5-9a47-d8f5b15e9b21' \
-H 'User-Agent: Kevin Mitnick <kmitnick@kobana.com.br>' \
-d '{
"subscription": {
"billing_account_id": "ba_01HXY123",
"plan_id": "plan_01HPRO",
"billing_cycle": "monthly"
}
}' \
-X POST 'https://api.billing.sandbox.kobana.com.br/v1/subscriptions'

Cómo funciona​

Cuando el servidor recibe una solicitud con X-Idempotency-Key:

  1. Reserva la clave de forma atómica, en el ámbito de tu organización. Dos organizaciones distintas pueden usar la misma clave sin conflicto.
  2. Calcula la huella de la solicitud — SHA-256 de método + ruta + cuerpo en bruto. Ese hash se almacena junto a la clave.
  3. Ejecuta el handler. Si devuelve una respuesta, el servidor registra status_code, cuerpo y cabeceras relevantes vinculados a la clave.
  4. Marca la clave como completada. Cualquier nueva solicitud que reutilice la clave dentro de 24 horas recibe la respuesta original verbatim — mismo status_code, mismo cuerpo, mismas cabeceras — más la cabecera X-Idempotent-Replay: true que indica que se trata de una reejecución.

La capa guarda el resultado independientemente de éxito o fracaso. Los reintentos con la misma clave devuelven el mismo resultado, incluyendo errores 5xx.

Límites​

  • Longitud máxima de la clave: 255 caracteres.
  • Retención: las claves expiran automáticamente 24 horas después de su creación. Tras expirar, una nueva solicitud con la misma clave genera un resultado nuevo.
  • Ámbito: por organización. Una clave usada en una organización no interfiere con otra.
  • Caracteres aceptados: cualquier cadena UTF-8 imprimible.

Cuándo el resultado no se guarda​

La capa solo guarda el resultado cuando el handler ha comenzado a ejecutarse. No se registra nada en los siguientes casos — es seguro reenviar la solicitud:

  • La clave está vacía o supera los 255 caracteres → respuesta 400 bad_request.
  • El parser del envoltorio de la API rechaza la solicitud antes del handler (JSON inválido, autenticación ausente, etc.).
  • El handler lanza una excepción durante la ejecución — la reserva se libera para que el siguiente reintento pueda correr limpio.
  • Otra solicitud con la misma clave está ejecutándose en paralelo → respuesta 409 conflict con details.reason = "idempotency_request_in_progress".

Conflictos​

Si la misma clave se reutiliza con una solicitud diferente (cualquier cambio en método, ruta o cuerpo), la API responde 409 conflict con details.reason = "idempotency_key_reused". Esto protege contra reuso accidental — por ejemplo, persistir la clave junto a la operación en tu lado y luego intentar crear dos recursos diferentes con el mismo identificador.

Respuesta de error​

{
"error": {
"code": "conflict",
"message": "X-Idempotency-Key was already used with different request parameters. Reuse the original parameters or generate a new key.",
"details": { "reason": "idempotency_key_reused" }
}
}

Otras respuestas posibles​

EscenarioStatuserror.codedetails.reason
Otra solicitud con la misma clave en ejecución409conflictidempotency_request_in_progress
Misma clave reutilizada con un cuerpo distinto409conflictidempotency_key_reused
Clave vacía o mayor que 255 caracteres400bad_requestinvalid_idempotency_key

Métodos aceptados​

Método¿Acepta X-Idempotency-Key?
POST✅ Sí
PUT✅ Sí
PATCH✅ Sí
GET❌ No (ya es idempotente por definición)
DELETE❌ No (ya es idempotente por definición)

Enviar la clave en GET o DELETE no tiene efecto — la API procesa la solicitud normalmente sin registrar nada.

Identificando una reejecución​

Toda respuesta servida desde el registro lleva la cabecera:

X-Idempotent-Replay: true

Puedes usar esta cabecera en tu lado para distinguir la primera ejecución de una reejecución hecha por el servidor.

Buenas prácticas​

  • Una clave por operación lógica. No reutilices la misma clave para crear dos recursos diferentes — recibirás 409 conflict.
  • Persiste la clave junto al estado de la operación en tu lado, para que el reintento tras un crash o reinicio use la misma clave.
  • Combínalo con backoff exponencial ante 5xx o timeout — la clave garantiza que el reintento no duplica el recurso. Como los fallos también se registran, puedes detener los reintentos en cuanto llegue el status code esperado.
  • Descarta la clave a las 24 horas. No tiene sentido mantenerla en tu lado después: el servidor ya ha descartado el registro.
  • No envíes la clave en métodos que no la aceptan. En GET/DELETE se ignora silenciosamente — preferimos que el cliente la omita para dejar claro qué es idempotente por contrato y qué depende de la clave.