Constaia
Endpoints

POST /v1/classify

Referencia de POST /v1/classify: identifica el tipo de un documento por 0,2 créditos, con candidatos y veredicto de tipo, para enrutarlo antes de analizarlo.

POST https://api.constaia.com/v1/classify solo responde a una pregunta: qué documento es. No extrae campos ni ejecuta checks, y cuesta 0,2 créditos por documento, sea cual sea su número de páginas (en modo test, 0).

Úsalo cuando recibes documentos sin saber qué son (un buzón de correo, una carpeta compartida, un formulario con un único campo "adjunta tu documentación") y necesitas enrutarlos: decidir a qué cola va cada uno o qué expect y checks aplicarle después en POST /v1/analyze. Si ya sabes qué documento esperas, llama directamente a analyze con expect: te ahorras una llamada.

Petición

Acepta exactamente las mismas entradas que POST /v1/analyze: multipart/form-data con file y options, o JSON con file_url o file_base64 + filename. Mismos formatos, mismo límite de 20 MB y el mismo atajo -F expect=….

Las opciones se validan con el mismo esquema estricto. Las que tienen efecto en una clasificación son:

OpciónDescripción
expectTipo o tipos aceptados. Con expect recibes un verdict de tipo.
languageIdioma de document.label y de los mensajes de verdict.reasons.
metadataTus datos (hasta 20 claves), devueltos tal cual.
asynctrue para responder 202 al momento y recibir el resultado por webhook.
curl https://api.constaia.com/v1/classify \
  -H "Authorization: Bearer $CONSTAIA_API_KEY" \
  -F file=@dni_valid.jpg \
  -F 'options={"expect":["es_dni","es_nie","passport"]}'

Respuesta: el objeto classification

200 OK (dni_valid.jpg, modo test)
{
  "id": "an_01J9Z8Q3K4M5N6P7Q8R9S0T1V2",
  "object": "classification",
  "status": "completed",
  "livemode": false,
  "created_at": "2026-09-29T10:00:00Z",
  "completed_at": "2026-09-29T10:00:01Z",
  "file": { "name": "dni_valid.jpg", "mime_type": "image/jpeg", "pages": 1, "size_bytes": 482133 },
  "document": { "type": "es_dni", "label": "DNI (España)", "confidence": 0.97 },
  "candidates": [{ "type": "es_dni", "confidence": 0.97 }],
  "verdict": {
    "expected": ["es_dni", "es_nie", "passport"],
    "match": true,
    "status": "valid",
    "reasons": [{ "code": "type_match", "severity": "info", "message": "El documento es DNI (España)." }]
  },
  "warnings": [],
  "usage": { "credits": 0, "pages": 1 },
  "metadata": {}
}
CampoDescripción
idId con prefijo an_.
objectSiempre "classification".
statusqueued, processing, completed o failed.
livemodetrue con clave live.
created_at, completed_atFechas ISO 8601; completed_at es null hasta que termina.
filename, mime_type, pages, size_bytes.
documentTipo más probable: type, label, confidence (0–1). null si no se pudo clasificar.
candidatesTipos candidatos con su confidence. Útil para decidir tú mismo cuando la confianza es baja.
verdictSolo con expect. Es un veredicto de tipo: type_match (el tipo está en expected), type_mismatch (se reconoce otro tipo del catálogo, invalid) o type_unknown (no se pudo identificar o la confianza es menor de 0,5, review). Puede añadir low_quality o low_confidence como warning, que llevan a review.
warningsAvisos de calidad detectados.
usagecredits (0,2 en live, 0 en test) y pages.
metadataTu metadata.
errorSolo si status es failed.

Un verdict: "valid" de classify solo dice que el tipo es el esperado. No comprueba caducidad, titular ni ningún otro check: para eso está analyze.

Como analyze, puede responder 202 si pasa a asíncrono; en ese caso el resultado llega en el webhook analysis.completed con data.object: "classification". Los errores son los mismos que en analyze.

Patrón: clasificar y después analizar

Clasifica el documento con la lista de tipos que tu flujo sabe tratar.

Enruta según document.type: cada tipo tiene sus propios checks. Si el veredicto no es valid (type_mismatch, type_unknown o confianza baja), mándalo a revisión manual.

Analiza con expect igual al tipo detectado y los checks de ese tipo.

route-document.ts
import { Constaia, type Checks } from "@constaia/sdk";
import { fromPath } from "@constaia/sdk/node";

const constaia = new Constaia();

const checksByType: Record<string, Checks> = {
  payment_receipt: { expectedAmount: 45, expectedReference: "INSCRIPCION 123" },
  medical_certificate_sport: { maxAgeDays: 365, requireSignature: true },
  invoice: {},
};

const file = await fromPath("./adjunto.pdf");
const classification = await constaia.classify(file, { expect: Object.keys(checksByType) });

const type = classification.document?.type;
if (classification.verdict?.status !== "valid" || !type) {
  console.log("A revisión manual:", classification.candidates);
} else {
  const analysis = await constaia.analyze(file, { expect: type, checks: checksByType[type] });
  console.log(type, analysis.verdict?.status);
}

Con este patrón pagas 0,2 créditos de más por documento. Si tus documentos son siempre de pocos tipos, suele salir más barato llamar directamente a analyze con expect como lista y ramificar por document.type, como se explica en Tipos de documento.

Siguientes pasos

En esta página