Ir al contenido

Idempotency-Key

Todo método no seguro (POST, PUT, PATCH, DELETE) en las operaciones de /api/v1 con contexto de organización — es decir, las que se ejecutan dentro de una organización activa, como proyectos, defectos, casos de prueba, ejecuciones y planes — acepta una cabecera OPCIONAL Idempotency-Key. Envía la misma clave en un reintento y Probara reproduce la respuesta original en lugar de volver a ejecutar la mutación — útil para reintentos de red, timeouts del cliente y esos dobles clics donde no sabes si la petición llegó a enviarse. Las peticiones GET/HEAD ignoran la cabecera por completo.

Los endpoints de autenticación (/api/v1/auth/*), perfil de usuario (/api/v1/profile, /api/v1/profile/avatar) y subida de avatar de proyecto (/api/v1/projects/{projectId}/avatar) no admiten esta cabecera — se ignora en silencio.

Las subidas de archivos (cualquier petición con cuerpo multipart/form-data, como la preparación de adjuntos o la subida de evidencias de un defecto) también ignoran la cabecera: no se registra ni se reproduce nada. Solo las peticiones de preparación se pueden reintentar sin clave de forma segura, porque un archivo preparado que ninguna petición posterior referencia caduca por sí solo. La subida de evidencias de un defecto no es una preparación: un reintento puede guardar los mismos archivos dos veces, así que revisa la lista de adjuntos del defecto antes de reintentarla.

Las claves están limitadas por organización y por el miembro que actúa: el mismo valor de clave usado por otra organización, o por otro miembro dentro de la misma organización, se trata como una clave independiente y nunca reproduce una respuesta entre esos límites.

  • No vacía
  • No mayor de 255 caracteres ASCII visibles (sin espacios en blanco, caracteres de control ni puntos de código fuera de ASCII)

Una clave inválida responde 400 y el handler nunca se ejecuta.

Ventana de terminal
# Primer intento — se ejecuta con normalidad y la respuesta queda registrada bajo la clave.
curl -sS -X POST \
-H "Authorization: Bearer $PROBARA_API_TOKEN" \
-H "Idempotency-Key: 8f14e45f-ceea-4a3c-b9a8-1a6b3d2f0e91" \
-H "Content-Type: application/json" \
-d '{"name":"Flujo de checkout"}' \
"https://app.probara.net/api/v1/projects"
HTTP/1.1 201 Created
Content-Type: application/json
{ "ulid": "01J...PROJ", "name": "Flujo de checkout", ... }

Reintentar la petición idéntica con la misma clave y el mismo cuerpo dentro de la ventana de retención devuelve el mismo estado y cuerpo — sigue siendo 01J...PROJ, sin un segundo proyecto creado — con una cabecera adicional en la respuesta:

HTTP/1.1 201 Created
Idempotency-Replayed: true
Content-Type: application/json
{ "ulid": "01J...PROJ", "name": "Flujo de checkout", ... }
SituaciónRespuesta
Primera petición con una clave nunca vistaSe ejecuta con normalidad; la respuesta se registra para reproducirla (JSON, estado < 500, sin ser 204 ni binaria)
Reintento idéntico dentro de la ventana de retenciónMismo estado y cuerpo que el original, más Idempotency-Replayed: true
Llega un duplicado mientras la primera petición sigue en curso409 con el envoltorio de error estándar (code: "conflict") y una cabecera Retry-After
Se reutiliza la misma clave con un método, ruta o cuerpo distinto422 con code: "validation_failed"; no se ejecuta nada
Clave inválida (vacía o de más de 255 caracteres ASCII visibles)400; no se ejecuta nada
La primera petición fallaSe libera la reserva de la clave; un reintento posterior con la misma clave se ejecuta con normalidad
La respuesta es 204, no es JSON o es binariaPasa sin registrarse — un reintento con la misma clave vuelve a ejecutar el handler

Los registros de clave se conservan durante 24 horas. Pasada esa ventana, la misma clave se comporta como una clave nueva, nunca vista: la petición idéntica vuelve a ejecutar el handler y Idempotency-Replayed no aparece en esa respuesta.

EstadoCódigoSignificado
400validation_failedIdempotency-Key está vacía o supera los 255 caracteres ASCII visibles
409conflictHay una petición en curso con la misma clave; incluye una cabecera Retry-After
422validation_failedLa clave ya se usó con un método, ruta o cuerpo de petición distinto