Idempotencia
Usa la cabecera Idempotency-Key para reintentar análisis, clasificaciones y lotes sin procesarlos ni cobrarlos dos veces, con ejemplos en varios lenguajes.
Una red puede cortarse justo después de que Constaia reciba tu petición. Si reintentas sin más, podrías analizar (y
pagar) el mismo documento dos veces. La cabecera Idempotency-Key lo evita: si repites una petición con la misma
clave, recibes la respuesta original en lugar de ejecutarla de nuevo.
Cómo funciona
curl https://api.constaia.com/v1/analyze \
-H "Authorization: Bearer $CONSTAIA_API_KEY" \
-H "Idempotency-Key: registration-123-dni" \
-F file=@dni.jpg \
-F 'options={"expect":"es_dni"}'- Funciona en
POST /v1/analyze,POST /v1/classifyyPOST /v1/batches. - La clave es una cadena de hasta 255 caracteres elegida por ti. Más larga:
400 invalid_idempotency_key. - Se guarda 24 horas por cuenta. Pasado ese tiempo, la misma clave cuenta como nueva.
- Si repites la petición con la misma clave y el mismo contenido, recibes la respuesta guardada (mismo estado HTTP y
mismo cuerpo) con la cabecera
Idempotent-Replayed: true. No se analiza de nuevo ni se cobra.
HTTP/1.1 200 OK
Content-Type: application/json
Idempotent-Replayed: true
X-Request-Id: req_01J9Z8Q3K4M5N6P7Q8R9S0T1V4La respuesta repetida es la original
Si la petición original devolvió 202 con el análisis en queued o processing, la repetición devuelve ese mismo
202, no el estado actual. Para saber cómo va, usa GET /v1/analyses/{id} con el id de la respuesta o espera al
webhook.
Conflictos
| Situación | Respuesta |
|---|---|
| Misma clave, mismo contenido, original terminada | La respuesta original + Idempotent-Replayed: true. |
| Misma clave, mismo contenido, original todavía en curso | 409 idempotency_in_progress. Reintenta en unos segundos. |
| Misma clave, contenido distinto (otro fichero, otras opciones u otro endpoint) | 422 idempotency_key_reused. |
| La original terminó con un error HTTP (4xx o 5xx) | La clave se libera: el reintento se ejecuta como nuevo. |
Que la clave se libere cuando hay error significa que puedes corregir y reintentar sin cambiar de clave, por ejemplo
tras un 402 insufficient_credits o un 503. Un análisis que termina con status: "failed" no es un error HTTP:
esa respuesta se guarda y se repite como cualquier otra.
{
"error": {
"type": "invalid_request",
"code": "idempotency_key_reused",
"message": "Esta Idempotency-Key ya se usó con otra petición distinta.",
"param": "Idempotency-Key",
"request_id": "req_01J..."
}
}Qué se compara
Constaia compara el contenido de la petición, no los bytes exactos del cuerpo HTTP:
- El fichero (su contenido y su nombre) o la
file_urly lo descargado de ella. - Las opciones ya normalizadas: da igual que mandes
optionscomo campo multipart o en el JSON, o que cambie elboundarydel multipart entre intentos. - En lotes, cada fichero y las opciones comunes.
Así un reintento de tu cliente HTTP, que genera un boundary nuevo, se reconoce como la misma petición.
Los SDK lo hacen por ti
Los SDK oficiales (JavaScript, PHP y Python) mandan una Idempotency-Key aleatoria en cada POST y la reutilizan en sus
propios reintentos. Un reintento automático nunca cobra dos veces. También reintentan solos el
409 idempotency_in_progress, esperando con backoff a que termine la petición original.
Eso protege frente a cortes dentro de una misma llamada. Si quieres deduplicar entre procesos (un job que se relanza, dos workers que cogen la misma tarea, un usuario que pulsa dos veces), pasa tu propia clave:
import { Constaia } from "@constaia/sdk";
import { fromPath } from "@constaia/sdk/node";
const constaia = new Constaia();
export async function verifyRegistrationDni(registrationId: string, path: string) {
return constaia.analyze(
await fromPath(path),
{ expect: "es_dni", metadata: { registration_id: registrationId } },
{ idempotencyKey: `registration-${registrationId}-dni` },
);
}Cómo elegir la clave
La clave debe identificar la operación de negocio, no el intento:
| Buena clave | Por qué |
|---|---|
registration-123-dni | Una inscripción, un DNI: si el proceso se repite, no se analiza dos veces. |
invoice-import-2026-09-29-file-8812 | Un fichero concreto de una importación concreta. |
batch-club-42-2026-09 | Un lote mensual por cliente. |
Evita:
- Una clave aleatoria generada en cada intento: no deduplica nada (los SDK ya hacen eso por ti).
- Una clave fija por usuario (
user-123): el siguiente documento que suba con otro contenido dará422 idempotency_key_reuseddurante 24 horas. - Datos personales en la clave (DNI, email): usa tus identificadores internos.
Si el usuario sube otro documento para la misma operación (por ejemplo, porque el primero salió invalid), usa
una clave nueva, por ejemplo añadiendo un número de intento: registration-123-dni-2.
Siguientes pasos
Límites de uso y cuotas
Límites de peticiones por segundo de la API de Constaia, cabeceras RateLimit, 429 con Retry-After, límites de ficheros y lotes, y cómo reintentar con backoff.
Paginación
Cómo recorrer listas de la API de Constaia con paginación por cursor (limit y starting_after) y filtros por estado, tipo y metadata, con ejemplos.