Tasvalúo SAI

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.

POST/v1/control/verificacionescontrol:write

Verifica la integridad del avalúo y deja constancia

GET/v1/control/inboxcontrol:read

Bandeja de avalúos recibidos

GET/v1/control/resumencontrol:read

Conteos y tiempos del tablero de control

GET/v1/control/avaluos/{folio}control:read

Estado de control de un avalúo

GET/v1/control/avaluos/{folio}/verificacionescontrol:read

Historial de verificaciones de integridad

POST/v1/control/avaluos/{folio}/dictamencontrol:write

Registra el dictamen técnico humano

POST/v1/control/avaluos/{folio}/dictamen/reabrircontrol:write

Deja sin efecto el dictamen vigente

Consultar

Bandeja

GET/v1/control/inboxcontrol:read

Bandeja 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: en requires_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.

Parámetros
CampoTipoDescripción
?bandejaen_revision | requiere_correccion | dictaminadosEn la query. Bandeja a listar. (por defecto "en_revision")
?desdestringEn la query. Creados a partir de esta fecha, ISO 8601 (2026-06-24 o 2026-06-24T18:30:00Z).
?hastastringEn la query. Creados hasta esta fecha, ISO 8601 (2026-06-24 o 2026-06-24T18:30:00Z).
?searchstringEn la query. Filtra por folio: coincidencias que lo contengan, sin distinguir mayúsculas.
?pageintegerEn la query. Página a devolver (desde 1). (mín. 1) (por defecto 1)
?page_sizeintegerEn la query. Elementos por página. (mín. 1) (máx. 100) (por defecto 20)
Petición
curl "$API_URL/v1/control/inbox?desde=2026-06-01&hasta=2026-06-30&search=000123" \
  -H "x-api-key: $API_KEY"
Respuesta

200Pá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
}
Errores
HTTPCuándo ocurre
400bandeja 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.
401API Key ausente, inválida, revocada o expirada.
403La API Key es válida pero le faltan permisos: Faltan scopes: <scope>.
429Se superó el límite de peticiones (rate limit).

Resumen

GET/v1/control/resumencontrol:read

Conteos y tiempos del tablero de control

Petición
curl "$API_URL/v1/control/resumen" \
  -H "x-api-key: $API_KEY"
Respuesta

200Resumen del tablero.

{
  "en_revision": 8,
  "requiere_correccion": 5,
  "dictaminados": 25,
  "dictaminados_hoy": 3,
  "aprobados": 22,
  "rechazados": 3,
  "tiempo_medio_dictamen_seg": 1800
}
Errores
HTTPCuándo ocurre
401API Key ausente, inválida, revocada o expirada.
403La API Key es válida pero le faltan permisos: Faltan scopes: <scope>.
429Se superó el límite de peticiones (rate limit).

Detalle de un avalúo

GET/v1/control/avaluos/{folio}control:read

Estado 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.

Parámetros
CampoTipoDescripción
foliorequeridostringEn la ruta. Identificador único global del avalúo.
Petición
curl "$API_URL/v1/control/avaluos/AVL-2026-000123" \
  -H "x-api-key: $API_KEY"
Respuesta

200Estado 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
}
Errores
HTTPCuándo ocurre
401API Key ausente, inválida, revocada o expirada.
403La API Key es válida pero le faltan permisos: Faltan scopes: <scope>.
404El folio no existe: Avalúo '<folio>' no encontrado.
429Se superó el límite de peticiones (rate limit).

Historial de verificaciones

GET/v1/control/avaluos/{folio}/verificacionescontrol:read

Historial 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.

Parámetros
CampoTipoDescripción
foliorequeridostringEn la ruta. Identificador único global del avalúo.
Petición
curl "$API_URL/v1/control/avaluos/AVL-2026-000123/verificaciones" \
  -H "x-api-key: $API_KEY"
Respuesta

200Verificaciones, 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"
  }
]
Errores
HTTPCuándo ocurre
401API Key ausente, inválida, revocada o expirada.
403La API Key es válida pero le faltan permisos: Faltan scopes: <scope>.
404El folio no existe: Avalúo '<folio>' no encontrado.
429Se superó el límite de peticiones (rate limit).

Verificar y dictaminar

Registrar una verificación

POST/v1/control/verificacionescontrol:write

Verifica 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: false y sin motivo_bloqueo.
  • Si el XML se lee pero la firma no es válida, sí se guarda como certificado_invalido y bloquea el dictamen.
Cuerpo application/json
CampoTipoDescripción
avaluo_base64requeridostringPDF final del avalúo en base64 estándar, en una sola línea y sin prefijo data:.
certificado_xmlrequeridostringCertificado XML emitido por el sistema, como texto. (mín. 1 caracteres)
controladorrequeridoobjectPersona 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.idrequeridostringId del usuario controlador en tu aplicación. (mín. 1 caracteres, máx. 120 caracteres)
controlador.nombrestring(máx. 160 caracteres)
controlador.emailstring(máx. 160 caracteres)
Petición
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"
  }
}'
Respuesta

201Veredicto 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
}
Errores
HTTPCuándo ocurre
400Cuerpo 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.
401API Key ausente, inválida, revocada o expirada.
403La API Key es válida pero le faltan permisos: Faltan scopes: <scope>.
413El cuerpo supera el tamaño máximo de 50 MB: El cuerpo de la petición supera el tamaño máximo permitido.
429Se superó el límite de peticiones (rate limit).

Emitir el dictamen

POST/v1/control/avaluos/{folio}/dictamencontrol:write

Registra 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.

  • rechazado pasa el avalúo a requires_correction y exige motivo_rechazo.
  • aprobado no cambia el estado del avalúo.
Parámetros
CampoTipoDescripción
foliorequeridostringEn la ruta. Identificador único global del avalúo.
Cuerpo application/json
CampoTipoDescripción
dictamenrequeridoaprobado | rechazado
verificacion_idrequeridouuidÚltima verificación del avalúo (coincide).
observacionesstring(máx. 2000 caracteres)
motivo_rechazostringObligatorio cuando dictamen es rechazado: mínimo 10 caracteres sin contar espacios al inicio y al final. (máx. 2000 caracteres)
controladorrequeridoobjectPersona 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.idrequeridostringId del usuario controlador en tu aplicación. (mín. 1 caracteres, máx. 120 caracteres)
controlador.nombrestring(máx. 160 caracteres)
controlador.emailstring(máx. 160 caracteres)
Petición
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"
  }
}'
Respuesta

201Dictamen 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"
}
Errores
HTTPCuándo ocurre
400Cuerpo 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.
401API Key ausente, inválida, revocada o expirada.
403La API Key es válida pero le faltan permisos: Faltan scopes: <scope>.
404El folio no existe: Avalúo '<folio>' no encontrado.
409No 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).
429Se superó el límite de peticiones (rate limit).

Reabrir el dictamen

POST/v1/control/avaluos/{folio}/dictamen/reabrircontrol:write

Deja 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 approved si su certificado sigue vigente.
  • Para dictaminar de nuevo, la última verificación debe seguir siendo coincide sobre la versión vigente del documento.
Parámetros
CampoTipoDescripción
foliorequeridostringEn la ruta. Identificador único global del avalúo.
Cuerpo application/json
CampoTipoDescripción
motivorequeridostringPor qué se reabre el dictamen. (mín. 10 caracteres, máx. 2000 caracteres)
controladorrequeridoobjectPersona 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.idrequeridostringId del usuario controlador en tu aplicación. (mín. 1 caracteres, máx. 120 caracteres)
controlador.nombrestring(máx. 160 caracteres)
controlador.emailstring(máx. 160 caracteres)
Petición
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."
  }
}'
Respuesta

201Dictamen 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"
}
Errores
HTTPCuándo ocurre
400Cuerpo 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.
401API Key ausente, inválida, revocada o expirada.
403La API Key es válida pero le faltan permisos: Faltan scopes: <scope>.
404El folio no existe: Avalúo '<folio>' no encontrado.
409El avalúo no tiene un dictamen vigente que reabrir (SIN_DICTAMEN).
429Se superó el límite de peticiones (rate limit).

On this page