API Docs
v1.0
Obtener API Key

DataRisk API

Integra los análisis de Carpeta Tributaria SII directamente en tu ERP, CRM o cualquier sistema. JSON limpio, tipado y con estructura jerárquica clara.

Quick Start

1

Genera tu API Key

Inicia sesión → Cuenta → API → Nueva API Key. Guárdala — no se volverá a mostrar.

2

Envía una Carpeta Tributaria

Llama a POST /api/v1/datarisk/evaluate con el PDF y los datos requeridos. Recibes un documentId de inmediato.

3

Consulta el estado (polling)

Haz polling a GET /api/v1/datarisk/reports/:id/status cada 2.5 segundos hasta obtener completed o failed.

4

Obtén el informe completo

El informe completo viene inline en el status completed, o consulta GET /api/v1/datarisk/reports/:id cuando lo necesites.

1 — Evaluar una Carpeta Tributaria
curl -X POST \
  -H "Authorization: Bearer TU_API_KEY" \
  -F "file=@carpeta.pdf" \
  -F "rut=76.123.456-7" \
  -F "creditoSolicitado=50000000" \
  -F "deterioroComercial=0" \
  https://api.prismal.cl/api/v1/datarisk/evaluate
2 — Consultar estado (polling)
curl -H "Authorization: Bearer TU_API_KEY" \
  https://api.prismal.cl/api/v1/datarisk/reports/DOCUMENT_ID/status
3 — Listar informes completos
curl -H "Authorization: Bearer TU_API_KEY" \
  https://api.prismal.cl/api/v1/datarisk/reports?limit=5

Autenticación

Los endpoints autenticados requieren una API Key que se genera desde la plataforma. Solo cuentas de empresa pueden crear keys (máximo 5 activas).

Envía la key en cualquiera de estos headers:

  • Authorization: Bearer prml_...
  • X-Api-Key: prml_...

El endpoint público (/api/public/datarisk/:code) no requiere autenticación.

Header de autenticación
Authorization: Bearer prml_abc123def456...

# Alternativa:
X-Api-Key: prml_abc123def456...
Rate limit: 100 requests/minuto por API key. Al exceder → 429 con Retry-After: 60.

Evaluar Carpeta Tributaria

POST
/api/v1/datarisk/evaluate

Sube un PDF de Carpeta Tributaria y lanza la evaluación. Requiere API Key.

Content-Type: multipart/form-data. La respuesta es inmediata (HTTP 202) — la extracción corre en background.

¿Qué es la Carpeta Tributaria?

La Carpeta Tributaria es un documento PDF oficial emitido por el Servicio de Impuestos Internos (SII) de Chile. Contiene información financiera y tributaria detallada de una empresa o persona natural:

  • Identificación: RUT, razón social, domicilio, actividad económica, fecha de inicio
  • Formulario 29 (F29): Declaraciones mensuales de IVA — ventas, compras, márgenes
  • Formulario 22 (F22): Declaraciones anuales de renta — ingresos, activos, pasivos, utilidad
  • Datos del contribuyente: Tramo de ventas, número de trabajadores

Se obtiene desde www.sii.cl → Servicios online → Carpeta tributaria electrónica. Debe descargarse como PDF nativo (no escaneado/imagen).

Cómo enviar el PDF

El archivo se envía como multipart/form-data, exactamente igual que un formulario HTML con <input type="file">. El campo debe llamarse file.

Requisitos del PDF:

  • Formato: PDF (application/pdf)
  • Tamaño máximo: 15 MB
  • Debe ser texto seleccionable (no imagen escaneada)
  • Descargado directamente del SII (no modificado ni re-exportado)

Flujo completo paso a paso

1

POST /evaluate → Envías el PDF + datos. Respuesta inmediata: {"documentId": "...", "status": "processing"}

2

Polling → Cada 2.5s haz GET /reports/:id/status. El backend extrae F29, F22, calcula score y ratios.

3

status: "completed" → El campo report contiene el informe completo con empresa, score, capacidad, F29, F22, alertas y ratios.

status: "failed" → El PDF no pudo procesarse. Revisa error.code y error.recommendation. No se descontó crédito.

Campos del formulario

CampoTipoDescripción
fileFile (PDF)PDF de Carpeta Tributaria descargado del SII (máx 15 MB). Obligatorio.
rutstringRUT del evaluado (ej. "76.123.456-7"). Obligatorio. Debe coincidir con el RUT del PDF.
creditoSolicitadonumberMonto del crédito solicitado en CLP (ej. 50000000). Obligatorio.
deterioroComercialnumberMonto de deterioro comercial en CLP. Usar 0 si no tiene. Obligatorio si deterioroComercialDesconocido no es true.
deterioroComercialDesconocidobooleanEnviar "true" si no se conoce el deterioro. El scoring se penaliza levemente. Opcional.
deudaVigentenumberDeuda vigente del evaluado en CLP. Opcional, default 0.
Importante sobre créditos: Cada evaluación exitosa consume 1 crédito Datarisk. El crédito se descuenta al finalizar la extracción, no al enviar el PDF. Si la extracción falla, no se descuenta crédito.
PDFs no compatibles: Carpetas escaneadas (imagen), protegidas con contraseña, modificadas con editores de PDF, o generadas por terceros (no SII) pueden fallar con error E_EMPTY_EXTRACTION. Siempre usa el PDF original descargado del SII.
cURL — Evaluar CT
curl -X POST \
  -H "Authorization: Bearer TU_API_KEY" \
  -F "file=@carpeta_tributaria.pdf" \
  -F "rut=76.123.456-7" \
  -F "creditoSolicitado=50000000" \
  -F "deterioroComercial=0" \
  -F "deudaVigente=5000000" \
  https://api.prismal.cl/api/v1/datarisk/evaluate
Respuesta (202 Accepted)
{
  "ok": true,
  "data": {
    "documentId": "664a1b2c3d4e5f6a7b8c9d0e",
    "status": "processing"
  }
}

Consultar estado

GET
/api/v1/datarisk/reports/:id/status

Estado de una evaluación individual. Requiere API Key.

POST
/api/v1/datarisk/reports/status

Estado de múltiples evaluaciones (máx 20 IDs). Requiere API Key.

Estados posibles

CampoTipoDescripción
processingstringLa extracción está en curso. Sigue consultando cada 2.5 segundos.
completedstringEvaluación lista. El campo "report" contiene el informe completo.
failedstringExtracción fallida. Revisa "error.recommendation" para resolver.
Tiempos de procesamiento: La evaluación toma en promedio 4–5 s para carpetas de formato nuevo y 6–8 s para formato legacy. Recomendamos un intervalo de polling de 2.5 segundos para balancear latencia y carga.

Batch status (múltiples IDs)

Envía un JSON con un array de IDs para consultar el estado de varias evaluaciones en una sola llamada:

Request body
{
  "ids": ["664a1b2c...", "664a1b2d...", "664a1b2e..."]
}
Respuesta — processing
{
  "ok": true,
  "data": {
    "documentId": "664a1b2c...",
    "status": "processing",
    "timing": {
      "uploadedAt": "2025-02-01T12:00:00Z",
      "extractStartedAt": "2025-02-01T12:00:01Z"
    }
  }
}
Respuesta — completed
{
  "ok": true,
  "data": {
    "documentId": "664a1b2c...",
    "status": "completed",
    "report": { /* informe completo */ },
    "timing": {
      "uploadedAt": "...",
      "extractStartedAt": "...",
      "extractedAt": "..."
    }
  }
}
Respuesta — failed
{
  "ok": true,
  "data": {
    "documentId": "664a1b2c...",
    "status": "failed",
    "error": {
      "code": "E_EMPTY_EXTRACTION",
      "message": "El documento no contiene datos extraíbles.",
      "recommendation": "Re-descargar desde el SII."
    }
  }
}

Evaluaciones múltiples simultáneas

El backend soporta múltiples evaluaciones simultáneas. Cada petición POST /evaluate retorna inmediatamente con un documentId. Las extracciones se procesan en paralelo (hasta 10 simultáneas) con un semáforo interno.

¿Cómo funciona internamente?

  • Cada request HTTP se procesa en <100ms (crea el documento y responde).
  • La extracción del PDF corre en background como proceso Python.
  • Un semáforo limita a 10 procesos Python simultáneos.
  • Si hay más de 10, las siguientes esperan en cola (no se pierden).
  • Usa el endpoint batch status para consultar múltiples evaluaciones en una sola llamada.
JavaScript — 5 evaluaciones paralelas
const API_KEY = "prml_tu_api_key";
const files = ["ct1.pdf", "ct2.pdf", "ct3.pdf", "ct4.pdf", "ct5.pdf"];

// 1. Enviar todas las evaluaciones en paralelo
const uploads = await Promise.all(
  files.map(async (file) => {
    const form = new FormData();
    form.append("file", fs.createReadStream(file));
    form.append("rut", "76.123.456-7");
    form.append("creditoSolicitado", "50000000");
    form.append("deterioroComercial", "0");

    const res = await fetch(
      `${BASE}/v1/datarisk/evaluate`,
      { method: "POST", headers: { Authorization: `Bearer ${API_KEY}` }, body: form }
    );
    return (await res.json()).data.documentId;
  })
);

// 2. Polling con batch status
let pending = [...uploads];
while (pending.length > 0) {
  await new Promise(r => setTimeout(r, 2500));
  const res = await fetch(`${BASE}/v1/datarisk/reports/status`, {
    method: "POST",
    headers: { Authorization: `Bearer ${API_KEY}`, "Content-Type": "application/json" },
    body: JSON.stringify({ ids: pending }),
  });
  const { data } = await res.json();
  for (const r of data) {
    if (r.status !== "processing") {
      console.log(`${r.documentId}: ${r.status}`);
      pending = pending.filter(id => id !== r.documentId);
    }
  }
}
Python — asyncio.gather
import asyncio, aiohttp

API_KEY = "prml_tu_api_key"
BASE = "https://api.prismal.cl/api"
headers = {"Authorization": f"Bearer {API_KEY}"}

async def evaluate(session, path, rut):
    data = aiohttp.FormData()
    data.add_field("file", open(path, "rb"), filename=path)
    data.add_field("rut", rut)
    data.add_field("creditoSolicitado", "50000000")
    data.add_field("deterioroComercial", "0")
    async with session.post(f"{BASE}/v1/datarisk/evaluate", headers=headers, data=data) as r:
        return (await r.json())["data"]["documentId"]

async def main():
    async with aiohttp.ClientSession() as s:
        ids = await asyncio.gather(
            evaluate(s, "ct1.pdf", "76.123.456-7"),
            evaluate(s, "ct2.pdf", "77.654.321-0"),
        )
        # Polling con batch status
        pending = list(ids)
        while pending:
            await asyncio.sleep(2.5)
            async with s.post(f"{BASE}/v1/datarisk/reports/status",
                headers={**headers, "Content-Type": "application/json"},
                json={"ids": pending}) as r:
                data = (await r.json())["data"]
            for d in data:
                if d["status"] != "processing":
                    print(f'{d["documentId"]}: {d["status"]}')
                    pending.remove(d["documentId"])

asyncio.run(main())

Endpoints de lectura

GET
/api/public/datarisk/:verificationCode

Informe público por código de verificación (DR-XXXXX). Sin autenticación.

GET
/api/v1/datarisk/reports

Listar informes con paginación y filtros. Requiere API Key.

GET
/api/v1/datarisk/reports/:id

Detalle completo de un informe (JSON limpio y tipado). Requiere API Key.

Sandbox (sin autenticación)

POST
/api/sandbox/evaluate

Evaluar mock (sin PDF, sin auth). Respuesta inmediata con datos ficticios.

GET
/api/sandbox/status/:id

Estado mock (siempre completed). Sin autenticación.

POST
/api/sandbox/status

Estado batch mock. Sin autenticación.

GET
/api/sandbox/reports

Listar reportes mock. Sin autenticación.

GET
/api/sandbox/reports/:id

Reporte mock completo. Sin autenticación.

Parámetros del listado

CampoTipoDescripción
limitnumberCantidad por página (1–100, default 20)
offsetnumberDesplazamiento (default 0)
rutstringFiltrar por RUT del evaluado
fromstringFecha desde (ISO 8601)
tostringFecha hasta (ISO 8601)
Respuesta — GET /v1/datarisk/reports
{
  "ok": true,
  "data": [
    {
      "documentId": "664a1b2c...",
      "rut": "76.123.456-7",
      "razonSocial": "Mi Empresa S.A.",
      "fechaEmisionCarpeta": "2025-01-15",
      "scoreValor": 0.72,
      "nivelRiesgo": "MODERADO",
      "resultadoCredito": "APROBADO",
      "createdAt": "2025-02-01T12:00:00Z"
    }
  ],
  "pagination": {
    "total": 150,
    "limit": 20,
    "offset": 0,
    "hasMore": true
  }
}

Esquema del informe (DatariskReport)

Cada informe sigue esta estructura jerárquica. Todos los montos están en CLP salvo donde se indique UF. Las fechas siguen ISO 8601. Los campos null indican dato no disponible.

meta

CampoTipoDescripción
versionstringVersión de la API (ej. "1.0")
generatedAtstringISO 8601 datetime de generación
documentIdstringID único del documento
verificationCodestring | nullCódigo de verificación DR-XXXXX
Estructura raíz
{
  "meta": { ... },
  "empresa": { ... },
  "score": { ... },
  "capacidadCredito": { ... },
  "f29": { ... },
  "f22": { ... },
  "propiedades": { ... },
  "ponderaciones": { ... },
  "alertas": [ ... ],
  "sociedadYRepresentantes": { ... }
}

empresa

CampoTipoDescripción
rutstringRUT del contribuyente
razonSocialstringNombre legal
domiciliostring | nullDirección registrada
actividadEconomicastring | nullActividad económica principal (texto resumen)
actividadesDetalleobject[]Desglose de actividades económicas (nuevo formato CT)
actividadesDetalle[].codigostringCódigo SII de la actividad
actividadesDetalle[].actividadstringDescripción de la actividad
actividadesDetalle[].categoriastring | nullCategoría tributaria
actividadesDetalle[].desdestring | nullFecha de inicio de la actividad
sucursalesstring[]Sucursales registradas en el SII (nuevo formato CT)
anotacionesobject[]Anotaciones y observaciones tributarias vigentes (nuevo formato CT)
anotaciones[].fechastring | nullFecha de la anotación
anotaciones[].glosastring | nullCódigo/glosa de la anotación
anotaciones[].descripcionstring | nullTexto descriptivo de la anotación
fechaInicioActividadesstring | nullFecha ISO (YYYY-MM-DD)
fechaEmisionCarpetastring | nullFecha/hora ISO de emisión
antiguedadAniosnumber | nullAños desde inicio de actividades
tamanoEmpresaenum | null"micro" | "pequena" | "mediana" | "grande"
tramoVentasobject | null{ codigo: number, descripcion: string }
trabajadoresnumber | nullCantidad de trabajadores
Ejemplo
"empresa": {
  "rut": "76.123.456-7",
  "razonSocial": "Mi Empresa S.A.",
  "domicilio": "Av. Providencia 1234, Santiago",
  "actividadEconomica": "Venta al por mayor",
  "actividadesDetalle": [
    { "codigo": "466302", "actividad": "VENTA AL POR MAYOR...", "categoria": "Primera Categoría", "desde": "27/12/2005" }
  ],
  "sucursales": ["M. BAQUEDANO 655, NATALES", "..."],
  "anotaciones": [
    { "fecha": "01/01/2025", "glosa": "RETENEDOR", "descripcion": "C.S. PARA CUMPLIMIENTO DE IVA..." }
  ],
  "fechaInicioActividades": "2015-03-20",
  "fechaEmisionCarpeta": "2025-01-15T10:30:00",
  "antiguedadAnios": 9.8,
  "tamanoEmpresa": "pequena",
  "tramoVentas": { "codigo": 5, "descripcion": "..." },
  "trabajadores": 12
}

score (Prismal Score)

CampoTipoDescripción
valornumber | nullScore entre 0.000 y 1.000
nivelRiesgostring | nullNivel de riesgo textual
modeloVersionstring | nullVersión del modelo de scoring
interpretacionstring | nullTexto interpretativo
variablesobject | nullMapa de variables del score

Cada variable del score

CampoTipoDescripción
normalizadonumberValor normalizado (0–1)
pesonumberPeso en el modelo
puntajeParcialnumberContribución al score final
detalle.justificacionstringExplicación textual
detalle.formulastringFórmula aplicada
detalle.advertenciasstring[]Advertencias (si aplican)

Variables: antiguedad, tamano_empresa, capital_propio, deterioro_comercial, ventas_f29, margen_f29, f29_sin_pago, solvencia_f22, postergacion_iva

Ejemplo
"score": {
  "valor": 0.72,
  "nivelRiesgo": "MODERADO",
  "modeloVersion": "PS0-DR-v2",
  "interpretacion": "Riesgo moderado...",
  "variables": {
    "antiguedad": {
      "normalizado": 0.85,
      "peso": 0.12,
      "puntajeParcial": 0.102,
      "detalle": {
        "justificacion": "9.8 años...",
        "formula": "min(años/15, 1)",
        "advertencias": []
      }
    }
  }
}

capacidadCredito

CampoTipoDescripción
resultadoenum"APROBADO" | "DISMINUIDO" | "SIN_CAPACIDAD"
capacidadSugeridaCLPnumberCapacidad de crédito sugerida (CLP)
creditoSolicitadoCLPnumberCrédito solicitado (CLP)
deudaVigenteCLPnumberDeuda vigente informada (CLP)
notaRiesgoLegacynumber | nullNota de riesgo legacy (0–7)
mesesEvaluadosnumberMeses evaluados
Ejemplo
"capacidadCredito": {
  "resultado": "APROBADO",
  "capacidadSugeridaCLP": 25000000,
  "creditoSolicitadoCLP": 15000000,
  "deudaVigenteCLP": 3000000,
  "notaRiesgoLegacy": 5.2,
  "mesesEvaluados": 12
}

f29 (Declaraciones mensuales IVA)

Las series están indexadas por periodo. periodos[0] corresponde a series.ventasCLP[0], etc.

CampoTipoDescripción
periodos[].fechastringISO date primer día del mes
periodos[].labelstringNombre legible (ej. "Enero 2025")
series.ventasCLPnumber[]Base imponible por periodo
series.comprasCLPnumber[]Compras por periodo
series.margenCLPnumber[]Margen por periodo
series.remanenteCLPnumber[]Remanente IVA
series.ivaCreditoCLPnumber[]IVA crédito
series.postergacionCLPnumber[]IVA postergado
series.ivaPagadoCLPnumber[]IVA pagado / determinado
tipoDeclaracionstring[]Tipo de declaración por periodo
pagoEstadostring[]Estado de pago por periodo
promedios.ventaCLPnumberPromedio de ventas
Ejemplo
"f29": {
  "periodos": [
    { "fecha": "2025-01-01", "label": "Enero 2025" },
    { "fecha": "2025-02-01", "label": "Febrero 2025" }
  ],
  "series": {
    "ventasCLP": [12500000, 13200000],
    "comprasCLP": [8300000, 9100000],
    "margenCLP": [4200000, 4100000],
    ...
  },
  "promedios": {
    "ventaCLP": 12850000,
    "compraCLP": 8700000,
    "margenCLP": 4150000
  }
}

f22 (Declaración anual de renta)

CampoTipoDescripción
series.ingresosCLPnumber[]Ingresos por periodo
series.totalActivoCLPnumber[]Total activo
series.totalPasivoCLPnumber[]Total pasivo
series.utilidadCLPnumber[]Utilidad
series.perdidaCLPnumber[]Pérdida
series.capitalPropioPosUFnumber[]Capital propio positivo (UF)
series.capitalPropioNegUFnumber[]Capital propio negativo (UF)
ratios.solvencianumber | nullRatio de solvencia
ratios.endeudamientonumber | nullRatio de endeudamiento
ratios.margenUtilidadPctnumber | nullMargen de utilidad (%)
ratios.rentabilidadSobreActivoPctnumber | nullRentabilidad sobre activo (%)
ratios.rotacionActivonumber | nullRotación del activo
ratios.variacionVentasPctnumber | nullVariación de ventas (%)
Ejemplo
"f22": {
  "periodos": [
    { "fecha": "2024-01-01", "label": "AT 2024" }
  ],
  "series": {
    "ingresosCLP": [180000000],
    "totalActivoCLP": [95000000],
    "totalPasivoCLP": [42000000],
    "utilidadCLP": [22000000],
    "perdidaCLP": [0],
    "capitalPropioPosUF": [1350],
    "capitalPropioNegUF": [0]
  },
  "ratios": {
    "solvencia": 2.26,
    "endeudamiento": 0.44,
    "margenUtilidadPct": 12.2,
    ...
  }
}

alertas

Array de alertas detectadas. Cada una tiene codigo, severidad y mensaje.

CódigoSev.Descripción
TENDENCIA_POSITIVAinfoTendencia positiva en ventas
TENDENCIA_NEGATIVAwarningTendencia negativa en ventas
CARPETAwarningCarpeta tributaria desactualizada (más de 30 días de su emisión)
CREDITOwarningAlertas de capacidad crediticia
RUT_DISTINTOdangerRUT distinto al informado
MARGEN_NEGATIVOdangerMargen operacional negativo
CAPACIDAD_MENOR_DEUDAdangerCapacidad menor a deuda vigente
CARPETA_MAS_180_DIASwarningCarpeta con más de 180 días de antigüedad
PERDIDA_EJERCICIOdangerPérdida en el ejercicio
Ejemplo
"alertas": [
  {
    "codigo": "TENDENCIA_NEGATIVA",
    "severidad": "warning",
    "mensaje": "Tendencia negativa en ventas"
  },
  {
    "codigo": "MARGEN_NEGATIVO",
    "severidad": "danger",
    "mensaje": "Margen operacional negativo"
  }
]

Otros campos

propiedades

CampoTipoDescripción
cantidadnumberCantidad de propiedades registradas
avaluoTotalCLPnumberAvalúo total (CLP)
bienesobject[]Detalle de cada bien raíz (nuevo formato CT)
bienes[].comunastringComuna donde está ubicado el bien
bienes[].rolstringRol SII del bien raíz
bienes[].direccionstringDirección del bien
bienes[].destinostringDestino (Habitacional, Comercial, etc.)
bienes[].avaluoFiscalCLPstringAvalúo fiscal (string formateado CLP)
bienes[].condicionstring | null"Afecto" o "Exento" de contribuciones
bienes[].porcentajeDerechostring | null% de derecho sobre el bien
bienes[].fojasNumeroAnoInscripcionstring | nullReferencia Fojas/Nº/Año de inscripción
bienes[].numeroCuotasstring | nullNúmero de cuotas contribuciones
bienes[].vencidasPorPagarstring | nullCuotas vencidas por pagar
bienes[].vigentesPorPagarstring | nullCuotas vigentes por pagar
bienes[].valorContribucionSemestralstring | nullValor contribución semestral ($)

ponderaciones

CampoTipoDescripción
antiguedadnumber | nullPonderación antigüedad
tamanonumber | nullPonderación tamaño
ventasnumber | nullPonderación ventas
desempenoVentasnumber | nullPonderación desempeño ventas
deudaVigentenumber | nullPonderación deuda vigente

sociedadYRepresentantes

Los campos representantes y socios mantienen el formato legacy. Los tres campos nuevos solo se populan en documentos procesados con el extractor de nuevo formato CT.

CampoTipoDescripción
representantesobject[]Lista legacy: { nombre, rut, fechaIncorporacion }
sociosobject[]Lista legacy: { nombre, rut, fechaIncorporacion }
representantesLegalesobject[]Representantes con forma de actuación (nuevo formato CT)
representantesLegales[].nombrestringNombre completo
representantesLegales[].rutstringRUT
representantesLegales[].fechaIncorporacionstring | nullFecha ISO de incorporación
representantesLegales[].formaActuacionstring | nullForma de actuación (ej. "Cualquiera", "Conjunta")
conformacionSociedadobject[]Socios con % de participación (nuevo formato CT)
conformacionSociedad[].nombrestringNombre o razón social del socio
conformacionSociedad[].rutstringRUT
conformacionSociedad[].fechaIncorporacionstring | nullFecha ISO de incorporación
conformacionSociedad[].participacionCapitalstring | nullPorcentaje de participación en capital (ej. "34%")
conformacionSociedad[].participacionUtilidadesstring | nullPorcentaje de participación en utilidades
participacionSociedadesobject[]Sociedades donde participa el contribuyente (mismo schema que conformacionSociedad)
Ejemplo
"propiedades": {
  "cantidad": 1,
  "avaluoTotalCLP": 70781209,
  "bienes": [
    {
      "comuna": "HUECHURABA",
      "rol": "04021-00015",
      "direccion": "RECOLETA 6006 V WOLF",
      "destino": "HABITACIONAL",
      "avaluoFiscalCLP": "70.781.209",
      "condicion": "Afecto",
      "porcentajeDerecho": "100%",
      "fojasNumeroAnoInscripcion": "59890/87243/2022",
      "numeroCuotas": null,
      "vencidasPorPagar": "-",
      "vigentesPorPagar": "-",
      "valorContribucionSemestral": "0"
    }
  ]
},
"ponderaciones": { "antiguedad": 0.85, ... },
"sociedadYRepresentantes": {
  "representantes": [
    { "nombre": "Juan Pérez", "rut": "12.345.678-9", "fechaIncorporacion": "2015-03-20" }
  ],
  "socios": [...],
  "representantesLegales": [
    { "nombre": "Juan Pérez", "rut": "12.345.678-9",
      "fechaIncorporacion": "2015-03-20", "formaActuacion": "Cualquiera" }
  ],
  "conformacionSociedad": [
    { "nombre": "Inv. Holding SpA", "rut": "76.000.001-K",
      "fechaIncorporacion": "2015-03-20",
      "participacionCapital": "60%", "participacionUtilidades": "60%" }
  ],
  "participacionSociedades": [...]
}

Códigos de error HTTP

CódigoNombreCuándo ocurre
400Bad RequestParámetros inválidos (ID malformado, campos faltantes, PDF no válido)
401UnauthorizedAPI key no proporcionada, inválida o desactivada
402Payment RequiredNo hay créditos Datarisk disponibles para tu empresa
404Not FoundInforme no encontrado o no pertenece a tu empresa
413Payload Too LargeEl archivo excede el límite de 15 MB
422UnprocessableEl informe aún no fue procesado completamente
429Too Many RequestsRate limit excedido — espera 60 segundos
500Server ErrorError interno del servidor
Formato de error
{
  "ok": false,
  "error": "Descripción del error"
}

Buenas prácticas

Polling

  • Intervalo recomendado: 3 segundos entre consultas.
  • Usa backoff exponencial para reducir carga (2s → 3s → 4.5s → ... hasta 15s).
  • Timeout máximo sugerido: 120 segundos. La mayoría de PDFs se procesa en 15-40s.
  • Para múltiples evaluaciones, usa batch status en vez de consultas individuales.

Archivos PDF

  • El PDF debe ser una Carpeta Tributaria descargada directamente del SII.
  • PDFs escaneados, protegidos con contraseña o reenviados por terceros pueden fallar.
  • Tamaño máximo: 15 MB.
  • Carpetas con más de 180 días de antigüedad generan una alerta pero se procesan normalmente.

Concurrencia

  • Puedes enviar hasta 10 evaluaciones simultáneas sin problemas.
  • Evaluaciones adicionales se encolan automáticamente (no se pierden).
  • Rate limit HTTP: 100 req/min por API key (aplica a todas las llamadas).
  • Cada evaluación exitosa consume 1 crédito Datarisk.
Polling con backoff exponencial
async function pollStatus(docId, apiKey) {
  let delay = 2000; // 2s inicial
  const maxDelay = 15000; // 15s máximo
  const timeout = 120000; // 2 min timeout total
  const start = Date.now();

  while (Date.now() - start < timeout) {
    const res = await fetch(
      `${BASE}/v1/datarisk/reports/${docId}/status`,
      { headers: { Authorization: `Bearer ${apiKey}` } }
    );
    const { data } = await res.json();

    if (data.status === "completed") return data.report;
    if (data.status === "failed") throw new Error(data.error.message);

    await new Promise(r => setTimeout(r, delay));
    delay = Math.min(delay * 1.5, maxDelay);
  }
  throw new Error("Timeout: evaluación no completó en 2 min");
}

Ejemplos de integración

JavaScript / Node.js
const API_KEY = "prml_tu_api_key";
const BASE = "https://api.prismal.cl/api";

// Listar informes
const res = await fetch(
  `${BASE}/v1/datarisk/reports?limit=10`,
  { headers: { "Authorization": `Bearer ${API_KEY}` } }
);
const { data, pagination } = await res.json();
console.log(`Total: ${pagination.total} informes`);

// Detalle de un informe
const detail = await fetch(
  `${BASE}/v1/datarisk/reports/${data[0].documentId}`,
  { headers: { "Authorization": `Bearer ${API_KEY}` } }
);
const { data: report } = await detail.json();
console.log(report.empresa.razonSocial);
console.log(`Score: ${report.score.valor}`);
console.log(report.capacidadCredito.resultado);
Python
import requests

API_KEY = "prml_tu_api_key"
BASE = "https://api.prismal.cl/api"
headers = {"Authorization": f"Bearer {API_KEY}"}

# Listar informes
res = requests.get(
  f"{BASE}/v1/datarisk/reports?limit=10",
  headers=headers
)
data = res.json()
for r in data["data"]:
    print(f"{r['rut']} - Score: {r['scoreValor']}")

# Detalle
doc_id = data["data"][0]["documentId"]
detail = requests.get(
  f"{BASE}/v1/datarisk/reports/{doc_id}",
  headers=headers
)
report = detail.json()["data"]
print(report["empresa"]["razonSocial"])
print(report["capacidadCredito"]["resultado"])

Sandbox (pruebas sin cuenta)

Hay dos formas de probar la API sin cuenta real ni créditos:

Opción A — Endpoints públicos (sin autenticación)

Endpoints dedicados bajo /api/sandbox/* que no requieren ningún header de autenticación. Ideales para pruebas rápidas desde el navegador o cURL.

CampoTipoDescripción
POST /api/sandbox/evaluateEvaluar mock sin PDF. Acepta rut y creditoSolicitado opcionales.
GET /api/sandbox/status/:idEstado mock (siempre completed con reporte completo).
POST /api/sandbox/statusBatch status mock. Envía { ids: [...] } en el body.
GET /api/sandbox/reportsLista mock con 1 reporte de ejemplo.
GET /api/sandbox/reports/:idReporte mock completo.

Opción B — Sandbox API Key

Usa la sandbox key con los endpoints reales (/api/v1/datarisk/*). Simula el flujo completo de autenticación — ideal para validar tu integración antes de pasar a producción.

Sandbox API Key

prml_test_sandbox_0000000000000000000000000000000000000000000000

Cualquier key que comience con prml_test_sandbox_ activa el modo sandbox.

Probar en Postman (paso a paso)

1

Método y URL

Selecciona POST y escribe la URL:

https://api.prismal.cl/api/v1/datarisk/evaluate
2

Pestaña Authorization

Haz clic en la pestaña Authorization. En "Type" selecciona Bearer Token. En el campo "Token" pega:

prml_test_sandbox_0000000000000000000000000000000000000000000000

No va en Params ni en la URL. Debe ir en Authorization → Bearer Token.

3

Pestaña Body

Haz clic en la pestaña Body. Selecciona form-data. Agrega estas filas:

KEYVALUE
rut76.123.456-7
creditoSolicitado50000000
deterioroComercial0

En sandbox no necesitas agregar el campo file. En producción sí es obligatorio (tipo File, seleccionas el PDF).

4

Click Send

Recibirás un 202 Accepted con el reporte mock completo. Verifica que ves "sandbox": true en la respuesta.

5

Probar otros endpoints

Con la misma Authorization, prueba:

GET https://api.prismal.cl/api/v1/datarisk/reports/000000000000000000000001/status

GET https://api.prismal.cl/api/v1/datarisk/reports/000000000000000000000001

GET https://api.prismal.cl/api/v1/datarisk/reports?limit=5

¿Qué hace el modo Sandbox?

No requiere PDF — puedes enviar el POST sin archivo
No consume créditos — prueba ilimitadamente
Respuesta inmediata — no hay extracción real
Datos realistas — misma estructura JSON que producción
Todos los endpoints — evaluate, status, reports, list
Rate limit: 30 req/min — suficiente para pruebas

Diferencias con producción

CampoTipoDescripción
sandbox: truebooleanTodas las respuestas sandbox incluyen este campo. Úsalo para detectar modo prueba.
fileopcionalEn sandbox el PDF es opcional. En producción es obligatorio.
_mockReportobjectEn POST /evaluate, sandbox incluye el reporte mock inline para conveniencia.
DatosficticiosEmpresa "EMPRESA DEMO SANDBOX S.A." con RUT, score, F29 y F22 de ejemplo.
Para producción: Genera una API Key real desde tu cuenta → Configuración → API. Las keys reales comienzan con prml_ (sin "test_sandbox").
Opción A — Endpoints públicos (sin auth)
# Evaluar mock
curl -X POST https://api.prismal.cl/api/sandbox/evaluate

# Consultar estado (siempre completed)
curl https://api.prismal.cl/api/sandbox/status/000000000000000000000001

# Obtener reporte completo
curl https://api.prismal.cl/api/sandbox/reports/000000000000000000000001

# Listar reportes
curl https://api.prismal.cl/api/sandbox/reports
Opción B — Con Sandbox API Key
curl -X POST \
  -H "Authorization: Bearer prml_test_sandbox_0000000000000000000000000000000000000000000000" \
  -F "rut=76.123.456-7" \
  -F "creditoSolicitado=50000000" \
  https://api.prismal.cl/api/v1/datarisk/evaluate

curl -H "Authorization: Bearer prml_test_sandbox_0000000000000000000000000000000000000000000000" \
  https://api.prismal.cl/api/v1/datarisk/reports/000000000000000000000001/status

curl -H "Authorization: Bearer prml_test_sandbox_0000000000000000000000000000000000000000000000" \
  https://api.prismal.cl/api/v1/datarisk/reports/000000000000000000000001

curl -H "Authorization: Bearer prml_test_sandbox_0000000000000000000000000000000000000000000000" \
  https://api.prismal.cl/api/v1/datarisk/reports?limit=5