Constaia
Endpoints

Sesiones y claves publicables

Referencia de /v1/sessions y de las claves publicables pk_: tu backend crea una sesión de 15 minutos y el navegador sube cada documento directamente a Constaia con el client_secret, sin exponer tu clave secreta.

Las sesiones (sess_…) permiten que el navegador suba los documentos directamente a Constaia, sin pasar el fichero por tu servidor y sin exponer tu clave secreta:

  1. Tu backend crea una sesión con la clave secreta (ck_…) y decide qué se pide y qué se comprueba.
  2. Tu página recibe solo el client_secret de la sesión.
  3. El navegador sube el documento a POST /v1/analyze con una clave publicable (pk_…) y ese client_secret.

Guía completa con el widget, fetch y el SDK: Integración solo frontend.

Método y rutaClaveQué hace
POST /v1/sessionssecretaCrea una sesión y devuelve su client_secret.
GET /v1/sessions/{id}secretaRecupera la sesión: estado y análisis de cada documento.
POST /v1/analyzepublicableSube un documento de la sesión desde el navegador.
Tu servidor (ck_)                 Navegador (pk_)                     Constaia
─────────────────                 ───────────────                     ────────
POST /v1/sessions ──────────────────────────────────────────────────▶ sess_… + client_secret (15 min)
  └─ client_secret ─────────────▶ <constaia-upload> / fetch
                                  POST /v1/analyze ───────────────────▶ análisis con las opciones de la sesión
GET /v1/sessions/{id} ──────────────────────────────────────────────▶ documents[].analysis_id
GET /v1/analyses/{id}  (o webhook analysis.completed) ─────────────▶ veredicto

Claves publicables

Una clave publicable (pk_live_… o pk_test_…) puede ir en el código de tu web: solo sirve para subir documentos a una sesión que ya creó tu servidor, y solo desde los dominios que autorices.

  • Se crean en el panel: Desarrolladores → Claves de API, tipo Publicable. Como todas las claves, se muestran una sola vez.
  • Dominios permitidos (1–20): app.tuweb.com (ese host exacto), *.tuweb.com (cualquier subdominio, pero no tuweb.com a secas: añádelo aparte) y, solo en claves de test, localhost:3000. El puerto forma parte del host. Los cambios de dominios se aplican al momento.
  • La petición del navegador debe llevar la cabecera Origin de uno de esos dominios (los navegadores la ponen solos). Si no: 403 origin_not_allowed.
  • Solo sirven para POST /v1/analyze con client_secret. Cualquier otra ruta responde 403 publishable_key_not_allowed.
  • El modo va con la clave: una pk_test_… solo abre sesiones creadas con una ck_test_…, y una pk_live_…, las de ck_live_….

Las claves secretas, nunca en el navegador

Una clave ck_… que llega desde una página de otro origen (cabecera Sec-Fetch-Site distinta de same-origin) se rechaza con 403 secret_key_in_browser, aunque sea correcta. Si ya se ha publicado, revócala en el panel. Ver Autenticación.

Crear una sesión

POST /v1/sessions
Authorization: Bearer ck_live_…
Content-Type: application/json
CampoTipoDescripción
templatestringPlantilla (tpl_…) con las opciones de análisis de todos los documentos. 422 template_not_found si no existe.
documentsobjeto[] (1–10)Documentos que se pueden subir. Cada uno: key (1–40 caracteres: letras, números, - o _, única), label, expect (tipo o lista de tipos) y checks (como en analyze). Sin documents: uno, key: "document", con las opciones de la plantilla.
referencestringTu referencia (hasta 200 caracteres). Llega a cada análisis como metadata.session_reference.
metadataobjeto string → stringHasta 20 claves. Se copia a cada análisis. Ponle el id del usuario para cruzar el resultado.
languagees | en | pt | frIdioma de los mensajes del veredicto, si el navegador no manda otro.

Las opciones de cada documento salen de la plantilla y, encima, del expect y los checks del documento (checks clave a clave). Aquí es donde pones lo que no puede decidir el navegador: por ejemplo el titular esperado (checks.holder) a partir del usuario autenticado.

curl https://api.constaia.com/v1/sessions \
  -H "Authorization: Bearer $CONSTAIA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "template": "tpl_01J9Z8Q3K4M5N6P7Q8R9S0T1V2",
    "reference": "user_42",
    "metadata": { "user_id": "42" },
    "documents": [
      { "key": "id_card", "label": "DNI o NIE", "expect": ["es_dni", "es_nie"], "checks": { "holder": { "full_name": "María García López" } } }
    ]
  }'
Respuesta (201)
{
  "id": "sess_01J9Z8Q3K4M5N6P7Q8R9S0T1V2",
  "object": "session",
  "client_secret": "sess_01J9Z8Q3K4M5N6P7Q8R9S0T1V2_secret_Xk2…",
  "status": "open",
  "livemode": true,
  "template": "tpl_01J9Z8Q3K4M5N6P7Q8R9S0T1V2",
  "reference": "user_42",
  "metadata": { "user_id": "42" },
  "documents": [
    { "key": "id_card", "label": "DNI o NIE", "expect": ["es_dni", "es_nie"], "analysis_id": null, "status": "pending" }
  ],
  "expires_at": "2026-09-30T10:15:00Z",
  "created_at": "2026-09-30T10:00:00Z"
}
CampoDescripción
client_secretSolo en la creación. Pásalo a la página. Da acceso a subir los documentos de esta sesión y a nada más.
statusopen, completed (todos los documentos subidos) o expired (pasados 15 minutos sin completarse).
documents[].statuspending (sin subir), processing (subida en curso) o submitted (ya tiene análisis).
documents[].analysis_idEl análisis creado con la subida, o null.
expires_at15 minutos después de crearla. Crea la sesión al pintar la página, no por adelantado.

Subir desde el navegador

POST /v1/analyze
Authorization: Bearer pk_live_…
Content-Type: multipart/form-data
CampoDescripción
fileEl documento.
client_secretEl de la sesión.
document_keyLa key del documento de la sesión. Opcional si la sesión tiene uno solo.
optionsOpcional. JSON en el que solo se tiene en cuenta language. Todo lo demás (expect, checks, almacenamiento…) sale de la sesión y su plantilla.
navegador
const form = new FormData();
form.append("file", input.files[0]);
form.append("client_secret", clientSecret);
form.append("document_key", "id_card");

const res = await fetch("https://api.constaia.com/v1/analyze", {
  method: "POST",
  headers: { Authorization: "Bearer pk_live_…" },
  body: form,
});
const analysis = await res.json();

Responde con el objeto analysis, igual que una llamada normal (200, o 202 si tarda más de 30 s), con session_id y document_key. Se cobra a tu cuenta como cualquier análisis.

  • Cada documento se analiza una vez. Una segunda subida del mismo documento devuelve 409 document_already_submitted. Si la subida falla antes de crear el análisis (fichero no válido, sin créditos, límite de peticiones), el documento queda libre para volver a intentarlo.
  • No hay resultados progresivos (stream) ni Idempotency-Key en este modo.
  • El navegador no puede leer análisis ni sesiones: el resultado que ve sirve para la interfaz, no para decidir.

Recuperar una sesión

curl https://api.constaia.com/v1/sessions/sess_01J9Z8Q3K4M5N6P7Q8R9S0T1V2 \
  -H "Authorization: Bearer $CONSTAIA_API_KEY"

Devuelve la sesión sin client_secret. Cuando el usuario termina, tu backend lee aquí el analysis_id de cada documento y el análisis con GET /v1/analyses/{id} (o lo recibe por el webhook analysis.completed), y decide con ese veredicto. Solo ve sesiones del modo de la clave; si no existe, 404 resource_missing.

SDK

Backend y navegador
import { Constaia } from "@constaia/sdk";

// Backend (clave secreta)
const constaia = new Constaia();
const session = await constaia.sessions.create({
  template: "tpl_01J9Z8Q3K4M5N6P7Q8R9S0T1V2",
  reference: "user_42",
  documents: [{ key: "id_card", expect: ["es_dni", "es_nie"] }],
});
// → session.client_secret a la página

// Navegador (clave publicable): solo permite sessions.submit()
const browser = new Constaia({ apiKey: "pk_live_…" });
const analysis = await browser.sessions.submit(file, { clientSecret, documentKey: "id_card" });

Errores

HTTPcodeCuándo
401session_invalidEl client_secret no existe, está mal formado o es de otro modo o cuenta.
401session_expiredLa sesión ha caducado (15 minutos). Crea otra.
403origin_not_allowedEl origen de la página no está en los dominios permitidos de la clave publicable.
403publishable_key_not_allowedUna clave pk_ en una ruta que no es POST /v1/analyze.
403secret_key_in_browserUna clave ck_ usada desde un navegador.
409document_already_submittedEse documento de la sesión ya se subió.
422invalid_document_keydocument_key no está en la sesión, o falta y la sesión tiene varios documentos.
422duplicate_document_keyAl crear: dos documentos con la misma key.
422template_not_foundAl crear: la plantilla no existe (param: "options.template").

Los mensajes de estos errores están pensados para enseñarse a la persona (en es, en, pt o fr). El resto de errores de la subida (saldo, límites, fichero no válido) son los de analyze.

Siguientes pasos

En esta página