Skip to content

Exportar consultas (bulk reports export)

Esta pagina describe el feature de exportacion masiva de consultas a buros (type=reports) desde la seccion de Analisis. El endpoint canonico es POST /exports con body {type: "reports"}. Las rutas legacy /reports/export/* siguen funcionando con headers de deprecacion hasta el sunset (ver guia de migracion).

Flujo del usuario

  1. Navega a /analyses desde el menu lateral.
  2. Click en Exportar consultas (visible solo con permiso ExportReports).
  3. Se abre el modal Exportar consultas.
  4. Completa el formulario y revisa la estimacion.
  5. Click en Exportar para encolar el job.
  6. La pagina navega a /analyses/exports donde aparece el job con estado en vivo via SSE.
  7. Cuando el job esta done, descarga el ZIP desde la lista.

Formulario del modal

Rango de fechas

  • Desde (after): fecha inclusiva inicial. No puede ser futura.
  • Hasta (before): fecha inclusiva final. Debe ser >= after.
  • Maximo: 365 dias entre after y before. Excederlo retorna DATE_RANGE_TOO_LARGE.

Sources (sourceKeys)

Lista de identificadores de buros a incluir. Ejemplos: datacredito-acierta, datacredito-cifin, transunion-cdv, midas.

  • Por defecto: todas las sources marcadas (al abrir el modal sin seleccion previa).
  • Persistencia: la ultima seleccion se guarda en sessionStorage (reports-export-last-sources).
  • UX en listas largas (>10 sources):
    • Botones Seleccionar todos / Deseleccionar todos en la cabecera.
    • Barra de busqueda (ion-searchbar) que filtra por nombre/key sin perder la seleccion.
  • Dejar todas deshabilitadas deshabilita el boton Exportar con mensaje "Selecciona al menos una source".
  • Si sourceKeys viene vacio en la API se interpreta como "todas las sources" (sin filtro).

Statuses (statuses)

Estados de los reports a incluir (whitelist):

  • done
  • failed
  • running
  • retry
  • initial
  • unverifiable

Vacio significa "todos los estados".

Formato (format)

ValorSalida
consolidatedUn solo reports.csv con todas las columnas seleccionadas en cada fila
separatedUn manifest.csv con metadata + carpetas payloads-crudos/ y/o payloads-parseados/ con los payloads individuales por archivo

Columnas (columns)

Whitelist cerrada de columnas. Al menos una debe estar seleccionada (EMPTY_COLUMNS si no):

KeyDescripcionOrigen
dateFecha de creacion del reportreport.created_at
nameSource keyparametro del job
idTypeTipo de documento del consultadoparseado de report.input
idNumberNumero de documentoparseado de report.input
firstNameNombresparseado de report.input
lastNameApellidosparseado de report.input
statusEstado del reportenum
errorMensaje de error si falloreport.error
retriesReintentosreport.retries
durationMsDuracion en msreport.finished_in_ms
idID del reportreport.id
rawPayloadPayload crudo del buro (XML/JSON)report.Response
parsedPayloadPayload parseado (JSON)report.Output

rawPayload y parsedPayload se exportan como celdas escapadas si format=consolidated, o como archivos individuales en payloads-* si format=separated.

Estimacion previa (dry-run)

Antes de encolar el job, el modal hace una llamada de estimacion para mostrar:

  • itemCount: cantidad estimada de reports que entran en los filtros.
  • overflowed: true si el conteo excede el hard-cap del tenant — en ese caso el boton Exportar se deshabilita.
  • softWarn: true si el conteo supera el soft-warn (tipicamente 100k). El modal muestra una advertencia pero permite continuar.

Endpoint: POST /exports?dryRun=true body {type: "reports", ...}. No crea estado.

Permisos requeridos

  • ExportReports para todas las operaciones (abrir modal, crear, estimar, listar sources, descargar).
  • El boton Exportar consultas esta oculto si el usuario no tiene el permiso.
  • Las descargas validan ownership cross-tenant: el archivo de un tenant T1 no es accesible por T2 (404 Not Found).

Formato del ZIP descargado

format=consolidated

reports-export-2026-05-12.zip
+- reports.csv

reports.csv contiene una fila por report con las columnas seleccionadas. Encoding UTF-8 sin BOM.

format=separated

reports-export-2026-05-12.zip
+- manifest.csv
+- payloads-crudos/
|  +- datacredito-acierta/
|  |  +- 01H8XYZ.xml
|  |  +- 01H8ABC.xml
|  +- transunion-cdv/
|     +- 01H8DEF.json
+- payloads-parseados/
   +- datacredito-acierta/
   |  +- 01H8XYZ.json
   +- transunion-cdv/
      +- 01H8DEF.json

manifest.csv actua como indice e incluye las columnas de metadata seleccionadas (sin rawPayload/parsedPayload). Las carpetas payloads-crudos/ y payloads-parseados/ aparecen solo si las columnas correspondientes estan marcadas.

Nombres de archivos por payload

  • Crudos: <source>/<reportID>.<ext> donde <ext> es xml o json segun el formato nativo del buro.
  • Parseados: <source>/<reportID>.json.

Compliance y PII

  • Los payloads contienen PII: nombres, documentos, scores, deudas.
  • Acceso restringido por permiso ExportReports (no ReadAnalysis).
  • Retencion: 30 dias desde el finishedAt del job.
  • Tras la expiracion, GET /exports/{id}/file (y el alias legacy /reports/export/download/:fileid) retornan 410 Gone con code: "EXPORT_FILE_EXPIRED".
  • Cada descarga se loguea (entity_id, user_id, order_id, file_id, ip, user_agent).

Codigos de error

StatusCodeCausa
400EMPTY_COLUMNSEl array columns esta vacio
400INVALID_COLUMNUna columna no esta en la whitelist
400INVALID_STATUSUn status no esta en la whitelist
400INVALID_DATE_RANGEafter o before vacio, o before < after
400DATE_RANGE_TOO_LARGEbefore - after > 365 dias
400INVALID_FORMATformat no es consolidated ni separated
403Usuario sin permiso ExportReports
404Order no existe o pertenece a otro tenant
410EXPORT_FILE_EXPIREDArchivo expirado (>30 dias)
429Rate limit del tenant excedido

Ejemplos curl

bash
# Estimacion previa
curl -X POST "https://api.kuenta.co/v1/exports?dryRun=true" \
     -H "Authorization: Bearer $TOKEN" \
     -H "Organization-ID: $ORG_ID" \
     -H "Content-Type: application/json" \
     -d '{
       "type": "reports",
       "after": "2026-01-01T00:00:00Z",
       "before": "2026-04-30T23:59:59Z",
       "format": "consolidated",
       "columns": ["date", "name", "idNumber", "status"]
     }'

# Crear export
curl -X POST "https://api.kuenta.co/v1/exports" \
     -H "Authorization: Bearer $TOKEN" \
     -H "Organization-ID: $ORG_ID" \
     -H "Content-Type: application/json" \
     -d '{
       "type": "reports",
       "after": "2026-01-01T00:00:00Z",
       "before": "2026-04-30T23:59:59Z",
       "sourceKeys": ["datacredito-acierta"],
       "statuses": ["done"],
       "format": "separated",
       "columns": ["date", "name", "idNumber", "status", "rawPayload", "parsedPayload"]
     }'

# Sources disponibles
curl -H "Authorization: Bearer $TOKEN" \
     -H "Organization-ID: $ORG_ID" \
     "https://api.kuenta.co/v1/exports/sources?type=reports"

# Descarga
curl -OJ \
     -H "Authorization: Bearer $TOKEN" \
     -H "Organization-ID: $ORG_ID" \
     "https://api.kuenta.co/v1/exports/01H8XYZ/file"

Notas operativas

  • El job corre en un worker async; tiempos tipicos: 30s-2min para <50k reports.
  • El estado se actualiza via SSE en GET /exports/sse; el frontend escucha y actualiza la lista sin polling.
  • Si el job falla, status="failed" y error describe la causa. Se puede reintentar creando un nuevo export.

Proximos pasos