Constaia
Conceptos

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

Terminal
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/classify y POST /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.
Respuesta repetida
HTTP/1.1 200 OK
Content-Type: application/json
Idempotent-Replayed: true
X-Request-Id: req_01J9Z8Q3K4M5N6P7Q8R9S0T1V4

La 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ónRespuesta
Misma clave, mismo contenido, original terminadaLa respuesta original + Idempotent-Replayed: true.
Misma clave, mismo contenido, original todavía en curso409 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.

422 idempotency_key_reused
{
  "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_url y lo descargado de ella.
  • Las opciones ya normalizadas: da igual que mandes options como campo multipart o en el JSON, o que cambie el boundary del 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:

src/verify-registration.ts
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 clavePor qué
registration-123-dniUna inscripción, un DNI: si el proceso se repite, no se analiza dos veces.
invoice-import-2026-09-29-file-8812Un fichero concreto de una importación concreta.
batch-club-42-2026-09Un 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_reused durante 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

En esta página