Seguir el avance
Cómo saber cuándo termina la lectura y la evaluación de un avalúo.
Crear un avalúo no devuelve el resultado: primero se lee el PDF y, cuando queda limpio,
tú lanzas la evaluación con POST /v1/avaluos/{folio}/evaluar. Las dos fases tardan
unos minutos. Hay tres formas de enterarte de cómo van.
| Caso | Usa |
|---|---|
| Pantalla de detalle abierta, o un proceso que espera el resultado | Stream en tiempo real (SSE) |
| Integración sencilla, sin conexiones abiertas | Consulta periódica del avalúo |
| Lista con muchos avalúos | Estados en lote |
Cuándo ha terminado
La evaluación no arranca sola. Cuando el PDF queda leído y sin errores,
document.puede_evaluar pasa a true y tienes que
lanzarla con
POST /v1/avaluos/{folio}/evaluar. Si ese documento ya tiene una evaluación en curso o
terminada, la llamada no crea otra.
Revisa el avalúo completo (el de GET /v1/avaluos/{folio} o el del stream) en este orden;
la primera fila que se cumpla decide:
| Situación | Condición | Qué hacer |
|---|---|---|
| No se pudo leer el PDF | document.estado es error | Termina. |
| El PDF se está leyendo | document.estado no es completed | Sigue esperando. |
| El PDF no sirvió | document.errores no está vacío | Termina: sube una versión corregida. |
| La evaluación falló | document.puede_evaluar es true y status es error | Termina. El motivo viene en latest_evaluation.error. |
| Falta lanzar la evaluación | document.puede_evaluar es true | Llama a POST /v1/avaluos/{folio}/evaluar y sigue esperando. |
| La evaluación terminó | latest_evaluation.estado es completed | Termina. |
| La evaluación está en curso | Cualquier otro caso | Sigue esperando. |
Mientras el PDF se lee, latest_evaluation puede ser todavía la de la versión anterior:
no la tengas en cuenta hasta que document.estado sea completed. Y mira status solo
junto con puede_evaluar: si relanzas una evaluación que falló, status sigue en error
hasta que la nueva termina.
function termino(avaluo) {
const doc = avaluo.document;
const ev = avaluo.latest_evaluation;
if (doc?.estado === 'error') return true; // no se pudo leer el PDF
if (doc?.estado !== 'completed') return false; // el PDF aún se está leyendo
if (doc.errores.length > 0) return true; // el PDF no sirvió
if (doc.puede_evaluar) return avaluo.status === 'error'; // falló, o falta lanzarla
return ev?.estado === 'completed';
}
// Lanza la evaluación si el PDF está listo y todavía no se ha lanzado.
async function evaluarSiFalta(folio, avaluo) {
if (termino(avaluo) || !avaluo.document?.puede_evaluar) return;
const res = await fetch(`${API_URL}/v1/avaluos/${folio}/evaluar`, {
method: 'POST',
headers: { 'x-api-key': API_KEY },
});
if (!res.ok) throw new Error(`No se pudo lanzar la evaluación: ${res.status}`);
}evaluarSiFalta() comprueba termino() antes de llamar: tras una evaluación fallida
puede_evaluar vuelve a ser true, y lanzarla sin mirar la reintentaría en bucle.
Stream en tiempo real (SSE)
/v1/avaluos/{folio}/streamavaluos:readFlujo SSE del estado del avalúo (tiempo real)
Abre una conexión que recibe el avalúo completo —el mismo objeto que
GET /v1/avaluos/{folio}— cada vez que cambia.
curl -N "$API_URL/v1/avaluos/26091000123/stream" \
-H "x-api-key: $API_KEY" \
-H "Accept: text/event-stream"data: {"folio":"26091000123","status":"processing","document":{"estado":"processing",…},…}
data: {"folio":"26091000123","status":"processing","document":{"estado":"completed","errores":[],"puede_evaluar":true,…},"latest_evaluation":null,…}
event: ping
data: keepalive
data: {"folio":"26091000123","status":"processing","document":{"estado":"completed","errores":[],"puede_evaluar":false,…},"latest_evaluation":{"estado":"processing",…},…}
data: {"folio":"26091000123","status":"requires_correction",…}Entre el segundo y el tercer data: {…} está tu llamada a
POST /v1/avaluos/{folio}/evaluar: sin ella, el stream se queda en puede_evaluar: true y
la evaluación no empieza.
| Mensaje | Qué es |
|---|---|
data: {…} | El avalúo completo. Llega al conectar, en cada cambio y en una revisión cada 30 s. Nunca se repite un mensaje idéntico al anterior. |
event: ping | Mantiene viva la conexión cada 20 s. Ignóralo. |
Consúmelo desde tu servidor
La llave va en la cabecera x-api-key, y el EventSource nativo del navegador no puede
enviar cabeceras. Abre el stream desde tu backend y reenvíalo a tu interfaz, sin exponer la
llave.
Si el folio no existe, la respuesta es 404 en JSON y el stream no llega a abrirse: comprueba
res.ok antes de leer eventos.
Ejemplo en Node.js
const res = await fetch(`${API_URL}/v1/avaluos/${folio}/stream`, {
headers: { 'x-api-key': API_KEY, Accept: 'text/event-stream' },
});
if (!res.ok) throw new Error(`No se pudo abrir el stream: ${res.status}`);
const decoder = new TextDecoder();
let buffer = '';
for await (const chunk of res.body) {
buffer += decoder.decode(chunk, { stream: true });
const mensajes = buffer.split('\n\n');
buffer = mensajes.pop(); // el último puede estar incompleto
for (const mensaje of mensajes) {
if (mensaje.startsWith('event: ping')) continue;
const data = mensaje.split('\n').find((l) => l.startsWith('data: '));
if (!data) continue;
const avaluo = JSON.parse(data.slice(6));
console.log(avaluo.status, avaluo.document?.estado, avaluo.latest_evaluation?.estado);
if (termino(avaluo)) process.exit(0);
await evaluarSiFalta(folio, avaluo);
}
}Si la conexión se corta, vuelve a abrirla: el primer mensaje trae el estado actual, así que no pierdes nada.
Consulta periódica
/v1/avaluos/{folio}avaluos:readEstado completo del avalúo
curl "$API_URL/v1/avaluos/26091000123" -H "x-api-key: $API_KEY"Devuelve el mismo objeto que el stream. Consulta cada 10–15 segundos, lanza la
evaluación cuando toque y para cuando termino() sea verdadero. Un intervalo más corto no
acelera el proceso y consume tu cuota de peticiones.
async function esperar(folio) {
for (;;) {
const res = await fetch(`${API_URL}/v1/avaluos/${folio}`, { headers: { 'x-api-key': API_KEY } });
if (res.status === 404) throw new Error(`El folio ${folio} no existe`);
const avaluo = await res.json();
if (termino(avaluo)) return avaluo;
await evaluarSiFalta(folio, avaluo);
await new Promise((r) => setTimeout(r, 12_000));
}
}Estados en lote
/v1/avaluos/estadosavaluos:readEstados ligeros de varios folios
Para una lista, pide el estado de varios folios en una sola llamada en vez de uno por uno.
curl -X POST "$API_URL/v1/avaluos/estados" \
-H "x-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"folios":["26091000123","26091000124"]}'{
"estados": [
{
"folio": "26091000123",
"status": "approved",
"document": {
"version": 2,
"estado": "completed",
"created_at": "2026-03-10T14:00:00.000Z",
"procesado_at": "2026-03-10T14:01:12.000Z"
},
"latest_evaluation": {
"id": "e1a2b3c4-0000-4000-8000-000000000001",
"estado": "completed",
"result": "aprobado",
"error": null,
"created_at": "2026-03-10T14:02:00.000Z",
"started_at": "2026-03-10T14:02:01.000Z",
"completed_at": "2026-03-10T14:05:40.000Z"
}
}
]
}- Los folios que no existen no aparecen en la respuesta; no hay error.
- El orden de
estadosno está garantizado: búscalos porfolio. foliosno puede ir vacío (400).- No trae
document.erroresnidocument.puede_evaluar, así que no sirve paratermino(): para saber si el PDF no sirvió o si falta lanzar la evaluación, pide el avalúo completo conGET /v1/avaluos/{folio}.
Diagnóstico: los jobs
Cuando algo parece detenido, puedes ver el trabajo interno de cada fase.
/v1/avaluos/{folio}/jobsavaluos:readProgreso de los jobs de etapa
El progreso de cada etapa de la última evaluación:
{
"folio": "26091000123",
"evaluacion_id": "e1a2b3c4-0000-4000-8000-000000000001",
"estado": "en_progreso",
"resultado": null,
"etapas": [
{
"tipo": "documental",
"orden": 1,
"estado": "completed",
"job": { "job_id": "…", "status": "completed", "progress": 100, "error": null, "started_at": "…", "completed_at": "…" }
}
]
}Valores en español en este endpoint
A diferencia del resto del contrato, el estado de la evaluación usa valores en español
(pendiente, en_progreso, completada, fallida, cancelada) y resultado usa
rechazado en lugar de no_aprobado. etapas[].estado sí usa los valores habituales. Para la lógica de tu integración usa
GET /v1/avaluos/{folio}.
Si el avalúo aún no tiene evaluación, responde evaluacion_id, estado y resultado en
null y etapas vacío.
/v1/avaluos/{folio}/jobavaluos:readJob de procesamiento más reciente
El trabajo más reciente del avalúo, con status (received, dispatched, running,
completed, failed), progress, error y latency_ms. Puede ser null.