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ón | Descripción |
|---|---|
expect | Tipo o tipos aceptados. Con expect recibes un verdict de tipo. |
language | Idioma de document.label y de los mensajes de verdict.reasons. |
metadata | Tus datos (hasta 20 claves), devueltos tal cual. |
async | true 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
{
"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": {}
}| Campo | Descripción |
|---|---|
id | Id con prefijo an_. |
object | Siempre "classification". |
status | queued, processing, completed o failed. |
livemode | true con clave live. |
created_at, completed_at | Fechas ISO 8601; completed_at es null hasta que termina. |
file | name, mime_type, pages, size_bytes. |
document | Tipo más probable: type, label, confidence (0–1). null si no se pudo clasificar. |
candidates | Tipos candidatos con su confidence. Útil para decidir tú mismo cuando la confianza es baja. |
verdict | Solo 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. |
warnings | Avisos de calidad detectados. |
usage | credits (0,2 en live, 0 en test) y pages. |
metadata | Tu metadata. |
error | Solo 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.
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
POST /v1/analyze
Referencia completa de POST /v1/analyze: formas de envío, todas las opciones y checks, objeto analysis campo a campo, códigos de estado y ejemplos.
Análisis guardados
Recupera, lista con filtros y paginación por cursor, exporta y borra análisis con /v1/analyses, y descarga exportaciones con las URLs firmadas de /v1/files.