Control
Bandejas, verificación de integridad y dictamen del controlador.
Endpoints del panel del controlador. Requieren control:read o control:write. Guía paso a
paso: control y dictamen.
/v1/control/verificacionescontrol:writeVerifica la integridad del avalúo y deja constancia
/v1/control/inboxcontrol:readBandeja de avalúos recibidos
/v1/control/resumencontrol:readConteos y tiempos del tablero de control
/v1/control/avaluos/{folio}control:readEstado de control de un avalúo
/v1/control/avaluos/{folio}/verificacionescontrol:readHistorial de verificaciones de integridad
/v1/control/avaluos/{folio}/dictamencontrol:writeRegistra el dictamen técnico humano
/v1/control/avaluos/{folio}/dictamen/reabrircontrol:writeDeja sin efecto el dictamen vigente
Consultar
Bandeja
/v1/control/inboxcontrol:readBandeja de avalúos recibidos
Tres bandejas excluyentes, ordenadas por última actualización (más reciente primero):
en_revision: tienen certificado vigente y aún no se dictaminan.requiere_correccion: enrequires_correction, pendientes de que el perito justifique o suba una corrección.dictaminados: con dictamen vigente.
Devuelve perito_id (opaco), no el nombre: la identidad del perito la resuelve tu aplicación.
| Campo | Tipo | Descripción |
|---|---|---|
?bandeja | en_revision | requiere_correccion | dictaminados | En la query. Bandeja a listar. (por defecto "en_revision") |
?desde | string | En la query. Creados a partir de esta fecha, ISO 8601 (2026-06-24 o 2026-06-24T18:30:00Z). |
?hasta | string | En la query. Creados hasta esta fecha, ISO 8601 (2026-06-24 o 2026-06-24T18:30:00Z). |
?search | string | En la query. Filtra por folio: coincidencias que lo contengan, sin distinguir mayúsculas. |
?page | integer | En la query. Página a devolver (desde 1). (mín. 1) (por defecto 1) |
?page_size | integer | En la query. Elementos por página. (mín. 1) (máx. 100) (por defecto 20) |
curl "$API_URL/v1/control/inbox?desde=2026-06-01&hasta=2026-06-30&search=000123" \
-H "x-api-key: $API_KEY"200 — Página de la bandeja.
{
"data": [
{
"folio": "AVL-2026-000123",
"avaluo_id": "8f14e45f-ceea-467a-9575-6e6b7c1a2f01",
"estado": "approved",
"bandeja": "en_revision",
"perito_id": "usr_7",
"institucion": "BBVA",
"tipo_inmueble": "CASA_HABITACION",
"documento_version": 1,
"created_at": "2026-09-10T15:00:00.000Z",
"updated_at": "2026-09-12T17:00:00.000Z",
"certificado": {
"emitido_at": "2026-09-12T16:45:00.000Z",
"estado": "vigente",
"sha256_certificado": "ec31682fde561917952ff78a7a8adeffd0febc372dd26871916c46c630381b45"
},
"hallazgos": {
"criticos": 0,
"tecnicos": 1,
"forma": 1,
"justificados": 2
},
"ultima_verificacion": {
"id": "3d2c1b0a-9f8e-4d7c-b6a5-4e3f2d1c0b9a",
"resultado": "coincide",
"firma_valida": true,
"coincide_hash": true,
"certificado_estado": "vigente",
"documento_version": 1,
"hash_esperado": "b70a14ee1e15d7aa94bd810ec06f4cb77a346e8f33aef6bfeae3d7c4442d7a93",
"hash_calculado": "b70a14ee1e15d7aa94bd810ec06f4cb77a346e8f33aef6bfeae3d7c4442d7a93",
"motivo": null,
"controlador_id": "ctl_2",
"controlador_nombre": "Luis R.",
"created_at": "2026-09-12T17:00:00.000Z"
},
"revision": null,
"puede_dictaminar": true,
"motivo_bloqueo": null
}
],
"page": 1,
"page_size": 20,
"total": 1,
"total_pages": 1
}| HTTP | Cuándo ocurre |
|---|---|
400 | bandeja no es válida, desde o hasta no son fechas ISO 8601 válidas, page es menor que 1, page_size está fuera de 1–100 o se envió un parámetro no permitido. |
401 | API Key ausente, inválida, revocada o expirada. |
403 | La API Key es válida pero le faltan permisos: Faltan scopes: <scope>. |
429 | Se superó el límite de peticiones (rate limit). |
Resumen
/v1/control/resumencontrol:readConteos y tiempos del tablero de control
curl "$API_URL/v1/control/resumen" \
-H "x-api-key: $API_KEY"200 — Resumen del tablero.
{
"en_revision": 8,
"requiere_correccion": 5,
"dictaminados": 25,
"dictaminados_hoy": 3,
"aprobados": 22,
"rechazados": 3,
"tiempo_medio_dictamen_seg": 1800
}| HTTP | Cuándo ocurre |
|---|---|
401 | API Key ausente, inválida, revocada o expirada. |
403 | La API Key es válida pero le faltan permisos: Faltan scopes: <scope>. |
429 | Se superó el límite de peticiones (rate limit). |
Detalle de un avalúo
/v1/control/avaluos/{folio}control:readEstado de control de un avalúo
Todo lo que el detalle necesita en una llamada: el avalúo completo (con hallazgos y justificaciones), la última verificación, el dictamen vigente y si se puede dictaminar (puede_dictaminar + motivo_bloqueo).
ultima_verificacion es null si no hay verificaciones y también cuando la última es de una versión anterior del documento; en ese caso motivo_bloqueo es verificacion_desactualizada.
| Campo | Tipo | Descripción |
|---|---|---|
foliorequerido | string | En la ruta. Identificador único global del avalúo. |
curl "$API_URL/v1/control/avaluos/AVL-2026-000123" \
-H "x-api-key: $API_KEY"200 — Estado de control.
{
"avaluo": {
"folio": "AVL-2026-000123",
"status": "approved",
"canal": "api",
"created_at": "2026-09-10T15:00:00.000Z",
"updated_at": "2026-09-10T15:06:12.000Z",
"puede_certificar": false,
"hallazgos_pendientes": 0,
"dictamen_control": null,
"certificado": {
"estado": "vigente",
"emitido_at": "2026-09-12T16:45:00.000Z",
"hash_avaluo": "b70a14ee1e15d7aa94bd810ec06f4cb77a346e8f33aef6bfeae3d7c4442d7a93",
"sha256_certificado": "ec31682fde561917952ff78a7a8adeffd0febc372dd26871916c46c630381b45",
"url": "https://storage.example.com/certificados/AVL-2026-000123-20260912-164500.xml?X-Amz-Signature=…"
},
"document": {
"version": 1,
"estado": "completed",
"nombre_archivo": "avaluo.pdf",
"paginas": 12,
"tamano_bytes": 482133,
"created_at": "2026-09-10T15:00:01.000Z",
"errores": [],
"puede_evaluar": false
},
"latest_evaluation": {
"id": "c9a1e2b3-4d5f-4a6b-8c7d-9e0f1a2b3c4d",
"estado": "completed",
"result": "aprobado_con_observaciones",
"stages": [
{
"name": "documental",
"status": "completed"
},
{
"name": "datos",
"status": "completed"
},
{
"name": "calculos",
"status": "completed"
},
{
"name": "mercado",
"status": "completed"
},
{
"name": "reglas",
"status": "completed"
}
],
"errors": [
{
"titulo": "Valor del avalúo >20% por DEBAJO del mercado web",
"codigo_regla": "MER-005",
"severidad": "tecnico",
"descripcion": "El valor unitario del avalúo queda por debajo del promedio de los comparables.",
"seccion_avaluo": "Enfoque Mercado",
"valor_encontrado": "Unitario avalúo $26,113/m²",
"valor_esperado": "Dentro de ±20% del promedio de mercado",
"sugerencia": "Revisa los comparables o justifica la diferencia.",
"id": "b1e7c0de-5a4f-4c3b-9d2e-1f0a9b8c7d6e",
"estado": "pending",
"justificacion": null,
"justificado_at": null,
"justificacion_heredada": false,
"justificacion_origen": null,
"sujeto_url": null
},
{
"titulo": "Superficie construida distinta a la de la escritura",
"codigo_regla": "DAT-012",
"severidad": "forma",
"descripcion": null,
"seccion_avaluo": "Cuadro de áreas",
"valor_encontrado": "78 m²",
"valor_esperado": "80 m²",
"sugerencia": null,
"id": "e2d3c4b5-a697-4887-9695-a4b3c2d1e0f9",
"estado": "dismissed",
"justificacion": "La superficie proviene de la escritura pública anexa (pág. 4).",
"justificado_at": "2026-09-10T15:05:40.000Z",
"justificacion_heredada": false,
"justificacion_origen": "directa",
"sujeto_url": null
}
],
"comparables_web": null,
"antecedentes": []
}
},
"perito_id": "usr_7",
"ultima_verificacion": {
"id": "3d2c1b0a-9f8e-4d7c-b6a5-4e3f2d1c0b9a",
"resultado": "coincide",
"firma_valida": true,
"coincide_hash": true,
"certificado_estado": "vigente",
"documento_version": 1,
"hash_esperado": "b70a14ee1e15d7aa94bd810ec06f4cb77a346e8f33aef6bfeae3d7c4442d7a93",
"hash_calculado": "b70a14ee1e15d7aa94bd810ec06f4cb77a346e8f33aef6bfeae3d7c4442d7a93",
"motivo": null,
"controlador_id": "ctl_2",
"controlador_nombre": "Luis R.",
"created_at": "2026-09-12T17:00:00.000Z"
},
"verificaciones_count": 1,
"revision": null,
"puede_dictaminar": true,
"motivo_bloqueo": null
}| HTTP | Cuándo ocurre |
|---|---|
401 | API Key ausente, inválida, revocada o expirada. |
403 | La API Key es válida pero le faltan permisos: Faltan scopes: <scope>. |
404 | El folio no existe: Avalúo '<folio>' no encontrado. |
429 | Se superó el límite de peticiones (rate limit). |
Historial de verificaciones
/v1/control/avaluos/{folio}/verificacionescontrol:readHistorial de verificaciones de integridad
Todas las verificaciones registradas para el avalúo, de la más reciente a la más antigua. Las verificaciones no se modifican ni se borran.
| Campo | Tipo | Descripción |
|---|---|---|
foliorequerido | string | En la ruta. Identificador único global del avalúo. |
curl "$API_URL/v1/control/avaluos/AVL-2026-000123/verificaciones" \
-H "x-api-key: $API_KEY"200 — Verificaciones, de la más reciente a la más antigua.
[
{
"id": "3d2c1b0a-9f8e-4d7c-b6a5-4e3f2d1c0b9a",
"resultado": "coincide",
"firma_valida": true,
"coincide_hash": true,
"certificado_estado": "vigente",
"documento_version": 1,
"hash_esperado": "b70a14ee1e15d7aa94bd810ec06f4cb77a346e8f33aef6bfeae3d7c4442d7a93",
"hash_calculado": "b70a14ee1e15d7aa94bd810ec06f4cb77a346e8f33aef6bfeae3d7c4442d7a93",
"motivo": null,
"controlador_id": "ctl_2",
"controlador_nombre": "Luis R.",
"created_at": "2026-09-12T17:00:00.000Z"
},
{
"id": "1f2e3d4c-5b6a-4798-8a7b-6c5d4e3f2a1b",
"resultado": "discrepancia",
"firma_valida": true,
"coincide_hash": false,
"certificado_estado": "vigente",
"documento_version": 1,
"hash_esperado": "b70a14ee1e15d7aa94bd810ec06f4cb77a346e8f33aef6bfeae3d7c4442d7a93",
"hash_calculado": "844ecc08164e2eab27634a9adee1afa6599e589570e719784e080ce747fc0e45",
"motivo": "hash_no_coincide",
"controlador_id": "ctl_2",
"controlador_nombre": "Luis R.",
"created_at": "2026-09-12T16:55:00.000Z"
}
]| HTTP | Cuándo ocurre |
|---|---|
401 | API Key ausente, inválida, revocada o expirada. |
403 | La API Key es válida pero le faltan permisos: Faltan scopes: <scope>. |
404 | El folio no existe: Avalúo '<folio>' no encontrado. |
429 | Se superó el límite de peticiones (rate limit). |
Verificar y dictaminar
Registrar una verificación
/v1/control/verificacionescontrol:writeVerifica la integridad del avalúo y deja constancia
Igual que POST /v1/avaluos/verify, pero guarda el veredicto como evidencia a nombre del controlador. Esa verificación es la que habilita —o bloquea— el dictamen: sólo un resultado coincide sobre la versión vigente del documento permite dictaminar.
- Si el XML es ilegible o su folio no existe, no se guarda nada:
verificacion_id: null,puede_dictaminar: falsey sinmotivo_bloqueo. - Si el XML se lee pero la firma no es válida, sí se guarda como
certificado_invalidoy bloquea el dictamen.
| Campo | Tipo | Descripción |
|---|---|---|
avaluo_base64requerido | string | PDF final del avalúo en base64 estándar, en una sola línea y sin prefijo data:. |
certificado_xmlrequerido | string | Certificado XML emitido por el sistema, como texto. (mín. 1 caracteres) |
controladorrequerido | object | Persona que actúa. La API Key autentica a la aplicación; la aplicación identifica a la persona y la envía aquí para que la acción quede atribuida. |
controlador.idrequerido | string | Id del usuario controlador en tu aplicación. (mín. 1 caracteres, máx. 120 caracteres) |
controlador.nombre | string | (máx. 160 caracteres) |
controlador.email | string | (máx. 160 caracteres) |
curl -X POST "$API_URL/v1/control/verificaciones" \
-H "x-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"avaluo_base64": "JVBERi0xLjcKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c+Pg==",
"certificado_xml": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><certificado>…</certificado>",
"controlador": {
"id": "ctl_2",
"nombre": "Luis R.",
"email": "luis.r@example.com"
}
}'201 — Veredicto registrado.
{
"valido": true,
"folio": "AVL-2026-000123",
"firma_valida": true,
"coincide_hash": true,
"certificado_estado": "vigente",
"hash_esperado": "b70a14ee1e15d7aa94bd810ec06f4cb77a346e8f33aef6bfeae3d7c4442d7a93",
"hash_calculado": "b70a14ee1e15d7aa94bd810ec06f4cb77a346e8f33aef6bfeae3d7c4442d7a93",
"resultado": "coincide",
"verificacion_id": "3d2c1b0a-9f8e-4d7c-b6a5-4e3f2d1c0b9a",
"documento_version": 1,
"puede_dictaminar": true,
"motivo_bloqueo": null
}| HTTP | Cuándo ocurre |
|---|---|
400 | Cuerpo o parámetros inválidos. message es un arreglo con un texto por problema (campo faltante, tipo incorrecto o campo no permitido). Si avaluo_base64 decodifica a vacío: El avalúo (base64) está vacío o es inválido. controlador y controlador.id son obligatorios (máx. 120 caracteres). Si los bytes no son un PDF: PDF_INVALIDO (El documento no es un PDF válido); si el PDF está cifrado: PDF_PROTEGIDO. |
401 | API Key ausente, inválida, revocada o expirada. |
403 | La API Key es válida pero le faltan permisos: Faltan scopes: <scope>. |
413 | El cuerpo supera el tamaño máximo de 50 MB: El cuerpo de la petición supera el tamaño máximo permitido. |
429 | Se superó el límite de peticiones (rate limit). |
Emitir el dictamen
/v1/control/avaluos/{folio}/dictamencontrol:writeRegistra el dictamen técnico humano
El juicio final sobre el avalúo es humano; el sistema sólo garantiza que se emita sobre un documento íntegro.
verificacion_id debe ser la última verificación del avalúo, haber resultado coincide y corresponder a la versión vigente del documento.
rechazadopasa el avalúo arequires_correctiony exigemotivo_rechazo.aprobadono cambia el estado del avalúo.
| Campo | Tipo | Descripción |
|---|---|---|
foliorequerido | string | En la ruta. Identificador único global del avalúo. |
| Campo | Tipo | Descripción |
|---|---|---|
dictamenrequerido | aprobado | rechazado | — |
verificacion_idrequerido | uuid | Última verificación del avalúo (coincide). |
observaciones | string | (máx. 2000 caracteres) |
motivo_rechazo | string | Obligatorio cuando dictamen es rechazado: mínimo 10 caracteres sin contar espacios al inicio y al final. (máx. 2000 caracteres) |
controladorrequerido | object | Persona que actúa. La API Key autentica a la aplicación; la aplicación identifica a la persona y la envía aquí para que la acción quede atribuida. |
controlador.idrequerido | string | Id del usuario controlador en tu aplicación. (mín. 1 caracteres, máx. 120 caracteres) |
controlador.nombre | string | (máx. 160 caracteres) |
controlador.email | string | (máx. 160 caracteres) |
curl -X POST "$API_URL/v1/control/avaluos/AVL-2026-000123/dictamen" \
-H "x-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"dictamen": "aprobado",
"verificacion_id": "3d2c1b0a-9f8e-4d7c-b6a5-4e3f2d1c0b9a",
"observaciones": "Documento íntegro; hallazgos justificados correctamente.",
"controlador": {
"id": "ctl_2",
"nombre": "Luis R.",
"email": "luis.r@example.com"
}
}'201 — Dictamen registrado.
{
"id": "6a5b4c3d-2e1f-4a0b-9c8d-7e6f5a4b3c2d",
"dictamen": "aprobado",
"observaciones": "Documento íntegro; hallazgos justificados correctamente.",
"motivo_rechazo": null,
"documento_version": 1,
"verificacion_id": "3d2c1b0a-9f8e-4d7c-b6a5-4e3f2d1c0b9a",
"controlador_id": "ctl_2",
"controlador_nombre": "Luis R.",
"controlador_email": "luis.r@example.com",
"vigente": true,
"created_at": "2026-09-12T17:30:00.000Z"
}| HTTP | Cuándo ocurre |
|---|---|
400 | Cuerpo o parámetros inválidos. message es un arreglo con un texto por problema (campo faltante, tipo incorrecto o campo no permitido). controlador y controlador.id son obligatorios. Un rechazo sin motivo de al menos 10 caracteres responde MOTIVO_REQUERIDO; se comprueba antes que la existencia del folio. |
401 | API Key ausente, inválida, revocada o expirada. |
403 | La API Key es válida pero le faltan permisos: Faltan scopes: <scope>. |
404 | El folio no existe: Avalúo '<folio>' no encontrado. |
409 | No se puede dictaminar; se comprueba en este orden: ya hay dictamen vigente (YA_DICTAMINADO), sin certificado vigente (SIN_CERTIFICADO), sin verificación (VERIFICACION_REQUERIDA), la última verificación no fue coincide (VERIFICACION_FALLIDA) y la verificación es de otra versión del documento o verificacion_id no es la última (VERIFICACION_DESACTUALIZADA). |
429 | Se superó el límite de peticiones (rate limit). |
Reabrir el dictamen
/v1/control/avaluos/{folio}/dictamen/reabrircontrol:writeDeja sin efecto el dictamen vigente
Marca el dictamen vigente con vigente: false y añade Reabierto por <nombre> (<id>): <motivo> a sus observaciones; no borra la evidencia.
- Reabrir un rechazo devuelve el avalúo a
approvedsi su certificado sigue vigente. - Para dictaminar de nuevo, la última verificación debe seguir siendo
coincidesobre la versión vigente del documento.
| Campo | Tipo | Descripción |
|---|---|---|
foliorequerido | string | En la ruta. Identificador único global del avalúo. |
| Campo | Tipo | Descripción |
|---|---|---|
motivorequerido | string | Por qué se reabre el dictamen. (mín. 10 caracteres, máx. 2000 caracteres) |
controladorrequerido | object | Persona que actúa. La API Key autentica a la aplicación; la aplicación identifica a la persona y la envía aquí para que la acción quede atribuida. |
controlador.idrequerido | string | Id del usuario controlador en tu aplicación. (mín. 1 caracteres, máx. 120 caracteres) |
controlador.nombre | string | (máx. 160 caracteres) |
controlador.email | string | (máx. 160 caracteres) |
curl -X POST "$API_URL/v1/control/avaluos/AVL-2026-000123/dictamen/reabrir" \
-H "x-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"motivo": "Se detectó un error en la captura del dictamen.",
"controlador": {
"id": "ctl_2",
"nombre": "Luis R."
}
}'201 — Dictamen reabierto; devuelve el dictamen actualizado.
{
"id": "6a5b4c3d-2e1f-4a0b-9c8d-7e6f5a4b3c2d",
"dictamen": "aprobado",
"observaciones": "Documento íntegro; hallazgos justificados correctamente.\nReabierto por Luis R. (ctl_2): Se detectó un error en la captura del dictamen.",
"motivo_rechazo": null,
"documento_version": 1,
"verificacion_id": "3d2c1b0a-9f8e-4d7c-b6a5-4e3f2d1c0b9a",
"controlador_id": "ctl_2",
"controlador_nombre": "Luis R.",
"controlador_email": "luis.r@example.com",
"vigente": false,
"created_at": "2026-09-12T17:30:00.000Z"
}| HTTP | Cuándo ocurre |
|---|---|
400 | Cuerpo o parámetros inválidos. message es un arreglo con un texto por problema (campo faltante, tipo incorrecto o campo no permitido). motivo debe tener entre 10 y 2000 caracteres; controlador y controlador.id son obligatorios. |
401 | API Key ausente, inválida, revocada o expirada. |
403 | La API Key es válida pero le faltan permisos: Faltan scopes: <scope>. |
404 | El folio no existe: Avalúo '<folio>' no encontrado. |
409 | El avalúo no tiene un dictamen vigente que reabrir (SIN_DICTAMEN). |
429 | Se superó el límite de peticiones (rate limit). |