Idempotencia
La API soporta idempotencia para repetir mutaciones con seguridad, sin ejecutar la misma operación dos veces. El caso clásico: un POST /api/v1/charges se cae por un error de red y no sabes si el cobro se creó — reenvía con la misma clave y vuelve la respuesta original, sin crear un segundo cobro.
Cómo usarla
Envía el header en cualquier POST, PUT o PATCH:
X-Idempotency-Key: <clave>
La clave se genera de tu lado — recomendamos UUID v4. Máximo de 255 caracteres.
curl -i \
-H "Authorization: Bearer $DUNNING_TOKEN" \
-H 'Content-Type: application/json' \
-H 'X-Idempotency-Key: 8c0f5d6e-3f8b-4cb5-9a47-d8f5b15e9b21' \
-d '{ "personId": "cmd8k1x2y0009cd4e", "amount": 1500.00, "dueDate": "2026-08-10" }' \
-X POST 'https://api.dunning.kobana.com.br/api/v1/charges'
Cómo funciona
- La clave se reserva atómicamente, acotada a tu organización (organizaciones distintas pueden usar la misma clave sin conflicto).
- El servidor calcula la huella digital de la request: hash de
método + ruta + body crudo. - El handler se ejecuta y la respuesta (status, body, headers) queda grabada vinculada a la clave — incluso cuando es un error.
- Una nueva request con la misma clave dentro de 24 horas recibe la respuesta original textual, con el header extra:
X-Idempotent-Replay: true
Pasadas las 24 horas la clave expira y la misma clave genera una ejecución nueva.
Conflictos
| Escenario | Status | code |
|---|---|---|
| Misma clave con método/ruta/body distinto | 409 | IDEMPOTENCY_KEY_REUSED |
| Otra request con la misma clave en curso | 409 | IDEMPOTENCY_REQUEST_IN_PROGRESS |
| Clave vacía o con más de 255 caracteres | 400 | VALIDATION_ERROR |
Ejemplo de respuesta de conflicto:
{
"message": "X-Idempotency-Key já foi usado com parâmetros diferentes. Reenvie os parâmetros originais ou gere uma nova chave",
"code": "IDEMPOTENCY_KEY_REUSED"
}
En IDEMPOTENCY_REQUEST_IN_PROGRESS, espera un instante y reenvía la misma request: o la primera ejecución termina y recibes el replay, o la reserva se liberó y tu intento se ejecuta.
Cuándo el resultado no se graba
Es seguro reenviar cuando el handler ni siquiera llegó a correr:
- Request rechazada antes del handler (JSON inválido, autenticación ausente).
- El handler lanzó una excepción — la reserva se libera para que el próximo reintento corra limpio.
Métodos aceptados
| Método | ¿Acepta X-Idempotency-Key? |
|---|---|
POST / PUT / PATCH | ✅ Sí |
GET / DELETE | ❌ No — ya son idempotentes por definición; el header se ignora |
Buenas prácticas
- Una clave por operación de negocio; repítela solo en reintentos de la misma operación.
- Persiste la clave junto con el estado de la operación de tu lado — el reintento post-crash usa la misma clave.
- Combínala con backoff exponencial en
5xx/timeout: la clave garantiza que el reintento no duplica nada. - Como los errores también se graban, un replay de error es señal para corregir la request y generar una clave nueva — no insistir con la misma.
- Descarta claves con más de 24 horas de tu lado; el servidor ya las expiró.