Tasvalúo SAI

Convenciones

URL base, formato de las peticiones, límites y la forma de los errores.

Lo que es igual en todos los endpoints.

URL base

https://tasvaluo-backend-testing.nexustma.dev

Todas las rutas del contrato empiezan por /v1. En los ejemplos de este manual la URL base y la llave están en variables de entorno:

export API_URL=https://tasvaluo-backend-testing.nexustma.dev
export API_KEY=sai_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
const API_URL = process.env.API_URL;
const API_KEY = process.env.API_KEY;

La documentación interactiva (Swagger) está en /api/docs.

Peticiones

AspectoValor
ProtocoloHTTPS
Cabecerasx-api-key siempre; Content-Type: application/json cuando hay cuerpo
CodificaciónUTF-8
FechasISO 8601 en UTC: 2026-06-24T18:30:00.000Z
Cuerpo JSON máximo50 MB (admite un PDF en base64)
Archivo multipart máximo30 MB, sólo PDF

Campos desconocidos = 400

El API rechaza cualquier campo que no esté en el contrato, aunque sea opcional o esté mal escrito. Envía sólo los campos documentados.

PDFs en base64

Varios endpoints reciben el PDF como texto base64. Tiene que ser base64 estándar, en una sola línea y sin prefijo data:application/pdf;base64,.

# macOS
base64 -i avaluo.pdf | tr -d '\n'
# Linux
base64 -w0 avaluo.pdf
// Node.js
const base64 = (await fs.promises.readFile('avaluo.pdf')).toString('base64');

Respuestas

  • JSON en todas las respuestas, salvo el stream de eventos (text/event-stream).
  • Los nombres de campo del contrato están en inglés o español según el recurso, pero los valores de estado son estables: están listados en estados.
  • Las operaciones asíncronas responden 202: la petición se aceptó, pero el trabajo sigue en curso.
  • Las URLs de descarga (url de documentos y certificados) son temporales: pídelas cuando las vayas a usar y no las guardes.

Paginación

Los listados paginados reciben ?page= (desde 1) y ?page_size= (1 a 100) y responden con este sobre:

{
  "data": [  ],
  "page": 1,
  "page_size": 20,
  "total": 57,
  "total_pages": 3
}

Errores

Todo error llega con la misma estructura:

{
  "statusCode": 409,
  "timestamp": "2026-06-24T18:30:00.000Z",
  "path": "/v1/avaluos/AVL-2026-000123/certificado",
  "method": "POST",
  "message": "Hay 2 hallazgo(s) sin justificar; …",
  "code": "HALLAZGOS_PENDIENTES"
}
CampoQué es
statusCodeEl status HTTP.
messageTexto en español para mostrar o registrar. Puede cambiar de redacción.
codeSólo en errores de negocio. Código estable: es el que debes usar en tu lógica.
errorNombre del status (Not Found, Bad Request…). No viene en los errores con code.

Ramifica por code, no por message

message puede reescribirse; code no. El catálogo completo está en códigos de error.

Errores de validación

Cuando el cuerpo o los parámetros no cumplen el contrato, la respuesta es 400 y message es un arreglo con un texto por problema:

{
  "statusCode": 400,
  "timestamp": "2026-06-24T18:30:00.000Z",
  "path": "/v1/avaluos/procesar",
  "method": "POST",
  "message": [
    "document.base64 must be base64 encoded",
    "property foo should not exist"
  ],
  "error": "Bad Request"
}

Qué significa cada status

HTTPSignificado¿Reintentar?
400La petición está mal formada o no cumple el contrato.No: corrige la petición.
401Falta la API Key o no es válida.No: revisa la llave.
403La llave no tiene el scope necesario o no es dueña del recurso.No.
404El folio o recurso no existe.No.
409El recurso no está en el estado que la operación necesita.Sí, cuando cambie el estado (p. ej. al terminar el procesamiento).
413El archivo (30 MB) o el cuerpo JSON (50 MB) supera el tamaño máximo.No: reduce el archivo o usa una URL prefirmada.
415El cuerpo usa una codificación o juego de caracteres no soportado.No: envía JSON en UTF-8.
422La petición es válida pero el contenido no se puede aceptar (p. ej. el PDF no trae folio).No: corrige el documento.
429Límite de peticiones superado.Sí, con backoff exponencial.
5xxError del servicio.Sí, con backoff. Si persiste, repórtalo con path y timestamp.

On this page