API v1 · Guía del integrador · 1.2.0

Integrar Valida por API

Esta guía es todo lo que necesita un desarrollador para integrarse sin hablar con nadie: cómo autenticarse, cómo reintentar sin cobrar dos veces, qué versión de lista consultó, cómo se mide el paquete, cuándo se bloquea el servicio (spoiler: nunca por consumo) y cómo recibir alertas. Cada endpoint trae ejemplos en curl, JavaScript y Python.

Base URL: https://api.valida.metrikone.co · Vigente desde: 9 de septiembre de 2026

Contenido de la guía16 secciones

1. Introducción

Valida expone una API REST sobre HTTPS para validar personas naturales y jurídicas contra listas SARLAFT. Cada consulta se persiste 10 años con hash de integridad y puede descargarse como PDF auditable. La API es servidor a servidor: la API key nunca debe vivir en un navegador ni en una app móvil.

  • Base URL: https://api.valida.metrikone.co. Todas las rutas empiezan por /api/v1/.
  • Formato: JSON UTF-8 en ambos sentidos, salvo los PDF (application/pdf).
  • Timestamps: ISO 8601 en UTC (2026-09-08T14:32:00Z). Los periodos de consumo van en fechas locales de Bogotá (2026-09-01).
  • Request id: toda respuesta trae X-Valida-Request-Id. Guárdelo en sus logs; es lo primero que pide soporte.
  • CORS: las rutas /api/v1/* responden preflight, pero exponer la key en un navegador va contra el contrato. Llame siempre desde su backend.
  • Sin rate limit por ritmo: hoy no existe un 429. Lo que sí existe es la guía de concurrencia; respétela.

Qué es y qué no es Valida

Valida es una herramienta tecnológica de consulta automatizada. No constituye asesoría jurídica ni sustituye el sistema SARLAFT/SAGRILAFT/SIPLAFT del sujeto obligado. El análisis de coincidencias, la decisión de vinculación y el reporte a la UIAF siguen siendo del oficial de cumplimiento. OFAC SDN, Unión Europea y US State Dept FTO se consultan como referencia: no son vinculantes en Colombia.

2. Quickstart en 5 pasos

  1. Reciba su API key. MeTRIK la entrega por un canal seguro. Guárdela como secreto de su backend (variable de entorno VALIDA_API_KEY). No se puede recuperar; si se pierde, se rota.
  2. Compruebe que llega.
    curl -s https://api.valida.metrikone.co/api/v1/health
  3. Haga su primera validación con una Idempotency-Key desde el día uno.
    curl -s -X POST https://api.valida.metrikone.co/api/v1/validate \
      -H "Authorization: Bearer $VALIDA_API_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: $(uuidgen)" \
      -d '{
        "tipo": "natural",
        "nombre": "Juan Perez Gomez",
        "documento": { "tipo": "CC", "numero": "1077089147" },
        "referencia_externa": "EXP-2026-00123"
      }'
    Lea severidad, matches[] y listas_consultadas[]. Guarde consulta_id.
  4. Descargue el PDF auditable de esa consulta.
    curl -s https://api.valida.metrikone.co/api/v1/reporte/<consulta_id> \
      -H "Authorization: Bearer $VALIDA_API_KEY" -o reporte.pdf
  5. Mire su consumo y configure alertas.
    curl -s https://api.valida.metrikone.co/api/v1/cuenta/consumo -H "Authorization: Bearer $VALIDA_API_KEY"
    
    curl -s -X PUT https://api.valida.metrikone.co/api/v1/cuenta/alertas \
      -H "Authorization: Bearer $VALIDA_API_KEY" -H "Content-Type: application/json" \
      -d '{ "umbrales": [80, 100], "emails": ["cumplimiento@suempresa.co"], "webhook": { "url": "https://suempresa.co/valida/webhook" } }'
    La respuesta del PUT trae webhook.secret una sola vez. Guárdelo.

Si su cliente API opera para terceros (agregador)

Agregue sujeto_obligado: { "razon_social", "nit" } a cada consulta. Sin él recibe400 sujeto_obligado_requerido. El PDF se emite a nombre de ese sujeto obligado y usted queda como canal. Ver sujeto obligado final.

3. Autenticación y rotación de key

Toda ruta /api/v1/* exige Authorization: Bearer <api_key>. Valida guarda solo el hash SHA-256 de la key: nadie en MeTRIK puede leerla después de emitida.

Authorization: Bearer <api_key>
Content-Type: application/json
  • Key ausente, mal formada, revocada o de cliente inactivo: 401 invalid_api_key con header WWW-Authenticate: Bearer.
  • Rotación: escriba a soporte. Se emite una key nueva y la anterior sigue activa el tiempo que usted pida para hacer el cambio sin corte; luego se revoca. Hoy no hay endpoint de autoservicio para rotar.
  • Una key por integración. Si varios sistemas suyos consultan, pida una key por sistema: permite revocar una sin tumbar las demás.
  • Nunca la envíe en la URL, en un navegador ni en logs.

4. Idempotencia y reintentos

Cada POST /validate que se persiste es una consulta cobrable. Un timeout de su lado con un reintento a ciegas produce dos consultas cobradas. Para evitarlo, envíe siempre el header Idempotency-Key.

SituaciónQué devuelve Valida
Idempotency-KeyDe 1 a 64 caracteres ASCII imprimibles, único por consulta. Recomendado: UUID v4. Vale 24 horas.
Misma clave + mismo cuerpo en 24 hLa respuesta original, mismo consulta_id, header X-Valida-Idempotent-Replay: true. No se cobra.
Misma clave + cuerpo distinto409 idempotency_error. Use otra clave.
Clave mal formada400 idempotency_key_invalida.
Respuesta 4xx o 5xxNo reserva la clave: puede reintentar con la misma.

Reintentos recomendados

  • Timeout del cliente: 60 segundos o más. Lo normal son 1-4 s, pero una consulta con muchos candidatos puede tardar más; el servidor corta a los 60 s.
  • Reintente ante timeout, error de red y 500 persistencia_error, siempre con la misma Idempotency-Key, con espera exponencial (2 s, 4 s, 8 s) y máximo 3 intentos.
  • No reintente 400, 401, 402 ni 409: la respuesta no va a cambiar hasta que usted cambie algo.
  • referencia_externa: mande su id de expediente o fila; se devuelve tal cual y luego puede buscarlo con GET /consultas?referencia_externa=. Es para conciliar; no reemplaza la Idempotency-Key.

5. Listas, tiers y versión de lista

TierListasQué significa para usted
1_vinculanteONU Consolidated · CSN ColombiaObligación legal explícita en Colombia. Un exacto aquí es un hallazgo alto.
2_obligatoriaPEP Colombia (SIGEP)Obligatoria de construir por el sujeto obligado. Un exacto es hallazgo medio: activa debida diligencia intensificada, no bloqueo.
3_referenciaOFAC SDN · EU Consolidated Sanctions · US State Dept FTONo vinculantes en Colombia. Estándar de facto de debida diligencia; su tratamiento lo define el manual SARLAFT de cada sujeto obligado.

Valida descarga cada lista de su fuente oficial a diario y la versiona por hash. Cada respuesta declara contra qué versión se comparó y esa versión queda grabada con la consulta:

  • listas_consultadas[] en el cuerpo: slug, nombre, tier, version_id, hash_contenido, fetched_en, total_entradas.
  • Header X-Valida-Listas-Version: onu_consolidated=2026-09-05T05:15:12Z;ofac_sdn=….
  • El PDF de /reporte/{consulta_id} imprime esas mismas versiones aunque lo descargue meses después. Nunca se recalcula.

Para el oficial de cumplimiento de su cliente

Guarde listas_consultadas junto con el resultado. Es la evidencia de que la verificación se hizo contra la lista vigente ese día.

6. Valida Diligencia (módulo aparte)

POST /v1/diligencia consulta antecedentes de fuentes nacionales para debida diligencia ampliada. Es un módulo distinto, no una lista más de SARLAFT, y por eso vive en su propio endpoint. Está en beta y se cobra aparte del paquete SARLAFT.

No mezcle los dos módulos

Un hallazgo de Diligencia no es un hallazgo SARLAFT. No entra en /validate, no aparece en listas_consultadas[], no sale en el PDF ni en el certificado mensual, y no descuenta del paquete SARLAFT. Cada respuesta viene sellada como REFERENCIA — decisión del cliente. Tratarlo como sanción LA/FT/FP ante un supervisor es un error de fondo del sujeto obligado.

FuenteQué contieneQué NO es
siri_procuraduriaSubconjunto certificable del SIRI publicado como dato abierto por la Procuraduría General de la Nación: sanciones disciplinarias e inhabilidades.No equivale ni reemplaza al certificado de antecedentes disciplinarios que expide la Procuraduría.
secop2_multasMultas, sanciones e inhabilidades a contratistas en SECOP II (Ley 80/1993 y Ley 1150/2007).Parte de los registros figura «A la espera de aprobación»: lea estado_plataforma antes de concluir.

Ambas fuentes son datos abiertos de datos.gov.co bajo licencia CC BY-SA 4.0, se ingieren con el mismo cron diario y se versionan por hash igual que las listas SARLAFT. La respuesta trae fuentes_consultadas[] con la versión de cada una.

curl -X POST https://api.valida.metrikone.co/api/v1/diligencia \
  -H "Authorization: Bearer $VALIDA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "documento": "1020304050",
    "tipo_documento": "CC",
    "nombre": "Juan Pérez Gómez",
    "referencia_externa": "exp-4471"
  }'
{
  "consulta_id": "…",
  "modulo": "diligencia",
  "tipo": "referencia",
  "sello": "REFERENCIA — decisión del cliente",
  "leyenda": "Información de referencia para debida diligencia. No constituye lista de sancionados LA/FT/FP ni hallazgo SARLAFT. La decisión es del cliente.",
  "total_hallazgos": 1,
  "fuentes_consultadas": [
    { "slug": "siri_procuraduria", "version_id": "…", "hash_contenido": "…", "fetched_en": "…" }
  ],
  "hallazgos": [ { "fuente": "siri_procuraduria", "coincidencia_por": "documento", "score": 1 } ],
  "hash_respuesta": "…",
  "fecha_consulta": "…"
}
  • Autenticación: la misma api_key. No hay credencial aparte.
  • Entrada: documento obligatorio (mínimo 5 caracteres); tipo_documento, nombre y referencia_externa opcionales.
  • Errores: mismo contrato que el resto de la API (error, message, doc_url, request_id).
  • Consumo: el contador y el cobro de Diligencia son independientes y todavía no están expuestos en /cuenta/consumo. Mientras tanto, cada consulta queda registrada como facturable.

7. Sujeto obligado final (agregadores)

Si su plataforma consulta por cuenta de varias empresas (patrón agregador), el reporte no puede quedar a nombre de su plataforma: un supervisor concluiría que el obligado no consultó. Por eso existe sujeto_obligado.

CampoRegla
sujeto_obligado.razon_socialRazón social legal del sujeto obligado final. 3 a 200 caracteres.
sujeto_obligado.nitNIT. Se aceptan puntos y guion con dígito de verificación ("800.123.456-7"); se guarda normalizado a dígitos.
Cuándo es obligatorioCuando su cliente API está marcado como opera para terceros. Si falta: 400 sujeto_obligado_requerido. Si no está marcado, es opcional y se estampa igual si lo envía.
Efecto en el PDFLa banda principal dice "Sujeto obligado: <razón social> — NIT" y debajo "A través de <su razón social> — NIT". El pie repite al sujeto obligado en cada página.
BúsquedaGET /consultas?sujeto_obligado_nit=800123456 devuelve solo las consultas de ese sujeto obligado.
{
  "tipo": "juridica",
  "nombre": "Acme Trading SAS",
  "documento": { "tipo": "NIT", "numero": "900123456" },
  "sujeto_obligado": { "razon_social": "Transportes La Sabana SAS", "nit": "800.123.456-7" },
  "referencia_externa": "vinculacion-8841"
}

8. Consumo y paquete

Su contrato es un paquete de consultas por mes calendario (America/Bogotá). Cuenta toda consulta que se persiste (una respuesta 200 de /validate que no sea replay). No hay rollover: lo que no se usa en el mes no pasa al siguiente.

PaqueteConsultas/mesPrecio mes (COP + IVA)UnitarioExcedente por consulta
1K1.000$150.000$150$110
5K5.000$550.000$110$90
10K10.000$900.000$90$70
20K20.000$1.400.000$70$50
A medida+20.000Según contratoSegún contrato$50

El excedente se cobra al unitario del escalón siguiente y entra en la cuenta del siguiente periodo.

Headers en cada respuesta de /validate

Van en el 200 y en los 4xx de negocio (400, 402, 409). Son la misma lectura que alimenta /cuenta/consumo: no cuestan una llamada extra.

X-Valida-Plan:                20K
X-Valida-Periodo-Inicio:      2026-09-01
X-Valida-Periodo-Fin:         2026-10-01
X-Valida-Consumo-Incluidas:   20000
X-Valida-Consumo-Consumidas:  16421
X-Valida-Consumo-Restante:    3579
X-Valida-Consumo-Excedente:   0
X-Valida-Consumo-Estado:      ok | umbral_80 | agotado | excedente | bloqueado | sin_plan
X-Valida-Listas-Version:      onu_consolidated=2026-09-05T05:15:12Z;ofac_sdn=2026-09-07T05:16:03Z;...

Endpoints de cuenta

  • GET /api/v1/cuenta/consumo: plan, periodo, contador, excedente estimado, estado de cobro y política. 409 sin_plan_asignado si su cliente aún no tiene paquete (por ejemplo, una beta sin costo); /validate funciona igual.
  • GET /api/v1/cuenta/consumo/historial?periodos=6: periodos anteriores con consumidas, excedente y estado de cobro.

Al 100% no pasa nada malo

Valida no bloquea por consumo. La consulta 20.001 se procesa igual, se marca como excedente (X-Valida-Consumo-Estado: excedente) y se cobra al unitario del escalón siguiente. Un tope duro por consumo solo existe si su empresa lo pide por escrito.

9. Cobro y bloqueo por mora

En lenguaje claro: nunca se bloquea por consumo; solo por cuenta vencida sin pago. Así funciona el ciclo:

  1. Aviso de cobro. Cuando el consumo llega al 80% del paquete o cuando llega el día 20 del periodo (lo primero que ocurra), MeTRIK emite la cuenta de cobro del siguiente paquete. Usted recibe el evento paquete.cobro_emitido (si configuró alertas) con la fecha de vencimiento.
  2. Pago. Cuando MeTRIK registra el pago, recibe paquete.reactivado si estaba bloqueado. Si no lo estaba, no pasa nada visible: siguió consultando todo el tiempo.
  3. Bloqueo. Solo si se cumplen las dos condiciones a la vez: la cuenta de cobro venció sin pago registrado y el consumo del periodo supera el 100% del paquete. Entonces POST /validate responde 402 paquete_vencido_sin_pago con X-Valida-Consumo-Estado: bloqueado. Las demás rutas (consultas, reportes, cuenta) siguen funcionando.
  4. Reactivación. Se envía el soporte de pago a soporte. Al registrarlo, el siguiente /validate vuelve a funcionar. Ninguna consulta se pierde: reintente las que recibieron 402 con su misma Idempotency-Key.
Respuesta 402
{
  "error": "paquete_vencido_sin_pago",
  "message": "La cuenta de cobro del paquete esta vencida sin pago registrado y el consumo supera el paquete contratado. Registre el pago con soporte para reactivar; las consultas no se pierden.",
  "doc_url": "https://app.valida.metrikone.co/docs#error-paquete_vencido_sin_pago",
  "request_id": "req_3f9c1a2b4d5e6f708192a3b4",
  "consumo": { "consumidas": 21340, "incluidas": 20000, "excedente": 1340, "estado": "bloqueado", ... },
  "cobro": { "cuenta_vence_en": "2026-10-05T00:00:00Z", "cuenta_referencia": "CC-0042", "periodo": "2026-09-01" },
  "como_reactivar": "Envie el soporte de pago a mauricio.moreno@metrik.com.co o al WhatsApp +57 315 950 9103. ..."
}

Cómo programar el 402

Trátelo como un error de negocio, no de red: registre el request_id, avise a su área de cartera y no reintente en bucle. Puede sondear GET /cuenta/consumo (campo cobro.bloqueado) cada pocos minutos o esperar el evento paquete.reactivado.

10. Alertas y webhooks

Configure umbrales de consumo y canales (email y/o webhook). Por defecto los umbrales son 80 y 100 y no hay canal configurado: hasta que no ponga un email o una URL, no recibe nada.

RutaQué hace
GET /cuenta/alertasConfiguración vigente y eventos del periodo (disparados con su estado de entrega, y pendientes).
PUT /cuenta/alertasActualiza umbrales (1-200 %, máximo 6), emails, webhook.url (https) y activa. Los campos omitidos se conservan. Al configurar la URL por primera vez la respuesta trae webhook.secret una sola vez.
POST /cuenta/alertas/webhook/rotar-secretoSecreto nuevo (una sola vez). El anterior sigue firmando 24 h.
POST /cuenta/alertas/pruebaEnvía paquete.prueba a sus canales y devuelve el evento_id y el resultado del primer intento.

Eventos

EventoCuándoIdempotencia
paquete.umbral_alcanzadoPrimera consulta del periodo que cruza cada umbral < 100 que usted configuró.Una vez por (periodo, umbral).
paquete.agotadoPrimera consulta que cruza el 100%.Una vez por periodo.
paquete.excedenteCada umbral > 100 configurado (110, 120, 150…).Una vez por (periodo, umbral).
paquete.renovadoPrimera consulta del periodo nuevo: el contador volvió a cero.Una vez por periodo.
paquete.cobro_emitidoMeTRIK marcó la cuenta de cobro del siguiente paquete, con vencimiento.Una vez por periodo.
paquete.bloqueadoLa primera consulta que recibe 402 en el periodo.Una vez por periodo.
paquete.reactivadoSe registró el pago y el bloqueo se levantó.Puede repetirse.
paquete.pruebaA petición.Puede repetirse.

Entrega

  • POST JSON a su URL, timeout 10 s. Éxito = cualquier 2xx. Responda rápido y procese después.
  • Reintentos con espera 1 min, 5 min, 30 min, 2 h, 12 h, 24 h. Tras 6 fallos el evento queda fallido (visible en GET /cuenta/alertas).
  • El email se envía en paralelo al webhook, una vez por evento.
  • Headers: X-Valida-Event (tipo), X-Valida-Delivery-Id (cambia en cada intento), X-Valida-Signature.
  • Deduplique por id del cuerpo: puede recibir el mismo evento más de una vez.
Cuerpo de ejemplo · paquete.agotado
{
  "id": "0d6f2c3a-5b1e-4e8a-9c7d-2f1a3b4c5d6e",
  "tipo": "paquete.agotado",
  "creado_en": "2026-09-18T15:41:02Z",
  "version": "2026-09-01",
  "cliente_id": "55a4400c-...",
  "periodo": { "inicio": "2026-09-01", "fin": "2026-10-01" },
  "umbral": 100,
  "consumo": { "consumidas": 20000, "incluidas": 20000, "restantes": 0, "porcentaje": 100, "excedente": 0, "excedente_precio_unitario": 50 },
  "plan": { "codigo": "20K", "consultas_incluidas": 20000 },
  "politica": { "bloqueo_por_consumo": false, "bloqueo_por_mora": true, "rollover": false },
  "consulta_id_detonante": "c0a8..."
}

Verificar la firma

X-Valida-Signature: t=1758210062,v1=<hex>. La firma es hex(HMAC-SHA256(secret, t + "." + cuerpo_crudo)). Durante las 24 h siguientes a una rotación hay dos v1: acepte si cualquiera coincide. Compare en tiempo constante y rechace si|ahora − t| > 300 s. Use el cuerpo crudo (bytes), no el JSON re-serializado.

# Firma manual para probar con su secreto (t = ahora en segundos)
T=$(date +%s); BODY='{"id":"evt_test","tipo":"paquete.prueba"}'
SIG=$(printf '%s.%s' "$T" "$BODY" | openssl dgst -sha256 -hmac "$VALIDA_WEBHOOK_SECRET" | awk '{print $2}')
curl -s -X POST https://suempresa.co/valida/webhook \
  -H "Content-Type: application/json" -H "X-Valida-Event: paquete.prueba" \
  -H "X-Valida-Signature: t=$T,v1=$SIG" -d "$BODY"

11. Concurrencia para lotes

No hay endpoint de lote: un cargue de 9.000 filas son 9.000 llamadas a /validate. Está bien, siempre que las haga con cabeza. Esta es la guía que Valida aguanta hoy y que MeTRIK monitorea:

  • Hasta 20 peticiones en vuelo por cliente API. Más no es más rápido: entran a la misma base de datos y se estorban.
  • Una Idempotency-Key por fila (por ejemplo {lote}-{fila} o un UUID guardado con la fila). Reintente solo con esa clave.
  • Timeout 60 s por petición y reintento exponencial (2 s, 4 s, 8 s) ante timeout, error de red y 500.
  • Pare el lote si recibe 401 o 402: ninguna fila siguiente va a pasar.
  • Guarde por fila consulta_id, severidad y listas_consultadas. Con los consulta_id puede pedir un solo PDF agregado en POST /reporte-lote (hasta 500 por PDF).
  • Horario: las listas se actualizan a las 05:15 de Bogotá; en esa ventana una consulta puede tardar un poco más. Si puede elegir, corra los lotes grandes fuera de esa hora.
# 20 en paralelo con GNU parallel; cada linea del CSV: referencia,tipo,nombre,doc_tipo,doc_numero
parallel -j 20 --colsep ',' \
  'curl -s -X POST https://api.valida.metrikone.co/api/v1/validate \
     -H "Authorization: Bearer $VALIDA_API_KEY" -H "Content-Type: application/json" \
     -H "Idempotency-Key: lote-2026-09-08-{1}" \
     -d "{\"tipo\":\"{2}\",\"nombre\":\"{3}\",\"documento\":{\"tipo\":\"{4}\",\"numero\":\"{5}\"},\"referencia_externa\":\"{1}\"}" \
     > resultados/{1}.json' :::: filas.csv

12. Formato de error y códigos

Toda respuesta de error, en cualquier ruta /api/v1/*, tiene la misma forma:

{
  "error": "validation_error",           // codigo estable: programe contra este
  "message": "El cuerpo de la peticion no cumple el esquema. Revise el campo issues.",
  "doc_url": "https://app.valida.metrikone.co/docs#error-validation_error",
  "request_id": "req_3f9c1a2b4d5e6f708192a3b4",   // mismo valor del header X-Valida-Request-Id
  "issues": [ { "path": ["nombre"], "message": "..." } ]   // solo en validation_error
}
HTTPerrorCuándoQué hacer
400invalid_jsonEl cuerpo no es JSON válido.Corrija el cuerpo. No reintente igual.
400validation_errorEl JSON no cumple el esquema (falta tipo, ni nombre ni documento, NIT inválido…).Lea issues[] (path + message) y corrija ese campo.
400sujeto_obligado_requeridoSu cliente opera para terceros y la consulta no trae sujeto_obligado.Agregue { razon_social, nit } del sujeto obligado final.
400idempotency_key_invalidaIdempotency-Key vacía, con espacios o de más de 64 caracteres.Use un UUID v4.
400consulta_ids_requeridosPOST /reporte-lote sin consulta_ids.Envíe al menos un consulta_id.
400maximo_500_consultas_por_loteMás de 500 consulta_ids en un PDF.Parta el lote.
401invalid_api_keyKey ausente, mal formada, revocada o de cliente inactivo.Revise el header Authorization. Si se rotó, use la nueva. Pare el lote.
402paquete_vencido_sin_pagoCuenta de cobro vencida sin pago registrado Y consumo por encima del 100%.Avise a cartera y registre el pago con soporte. No reintente en bucle; el 402 no cambia solo.
404not_foundLa consulta no existe o no es de su cliente.Verifique el consulta_id.
404consultas_no_encontradas_para_clienteNinguno de los consulta_ids del lote es suyo.Verifique los ids.
409idempotency_errorLa Idempotency-Key ya se usó con un cuerpo distinto.Use una clave nueva para una consulta distinta.
409sin_plan_asignadoGET /cuenta/consumo de un cliente sin paquete.Escriba a soporte para activarlo. /validate sigue funcionando.
500persistencia_errorLa consulta corrió pero no se pudo guardar. No se cobró.Reintente con la misma Idempotency-Key tras 2 s.
500db_errorError interno al leer o escribir.Reintente con espera exponencial. Si persiste, soporte con el request_id.

Lo que NO existe

No hay 429, Retry-After, 403 permiso_denegado ni 503. Si su cliente HTTP los maneja de forma genérica, bien; pero no programe lógica de negocio sobre ellos.

13. Endpoints con ejemplos

MétodoRutaPara qué
GET/api/v1/healthEstado del servicio (sin auth).
POST/api/v1/validateValidar una persona o entidad contra las listas SARLAFT.
POST/api/v1/diligenciaAntecedentes nacionales de referencia. Módulo aparte, ver §6.
GET/api/v1/consultasListar y filtrar sus consultas.
GET/api/v1/reporte/{consulta_id}PDF auditable de una consulta.
POST/api/v1/reporte-lotePDF agregado de hasta 500 consultas.
GET/api/v1/cuenta/consumoContador del paquete y estado de cobro.
GET/api/v1/cuenta/consumo/historialPeriodos anteriores.
GET / PUT/api/v1/cuenta/alertasVer y configurar alertas.
POST/api/v1/cuenta/alertas/webhook/rotar-secretoRotar el secreto del webhook.
POST/api/v1/cuenta/alertas/pruebaProbar los canales.

Las rutas /api/v1/kyc/* y /api/v1/compliance/dual/* son internas de MeTRIK ONE y no forman parte del contrato con integradores. Las /api/admin/* son de operación de MeTRIK.

POST /api/v1/validate

curl -s -X POST https://api.valida.metrikone.co/api/v1/validate \
  -H "Authorization: Bearer $VALIDA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 4c6d1a4e-0e0f-4c37-9c7d-6a5b6f1f2e3d" \
  -d '{
    "tipo": "natural",
    "nombre": "Juan Perez Gomez",
    "documento": { "tipo": "CC", "numero": "1077089147" },
    "fecha_nacimiento": "1985-03-15",
    "pais": "CO",
    "referencia_externa": "EXP-2026-00123",
    "sujeto_obligado": { "razon_social": "Transportes La Sabana SAS", "nit": "800123456" }
  }' -D -
Respuesta 200 (resumida)
{
  "consulta_id": "4f8e2a91-1c3e-4f0a-9d2b-1a2b3c4d5e6f",
  "severidad": "sin_hallazgo",
  "total_matches": 0,
  "consulta_parcial": false,
  "matches": [],
  "hash_reporte": "a3f8d92e4b1c...",
  "consultado": { "tipo": "natural", "nombre": "Juan Perez Gomez", "documento": { "tipo": "CC", "numero": "1077089147" } },
  "sujeto_obligado": { "razon_social": "Transportes La Sabana SAS", "nit": "800123456" },
  "referencia_externa": "EXP-2026-00123",
  "listas_consultadas": [
    { "slug": "onu_consolidated", "nombre": "ONU Consolidated Sanctions List", "tier": "1_vinculante",
      "version_id": "…", "hash_contenido": "…", "fetched_en": "2026-09-05T05:15:12Z", "total_entradas": 1002 },
    ...
  ],
  "fecha_reporte": "2026-09-08T14:32:00.512Z",
  "cliente": "Plataforma Ejemplo"
}
Un match (elemento de matches[])
{
  "lista": "ofac_sdn",
  "lista_nombre": "OFAC Specially Designated Nationals (SDN)",
  "tier": "3_referencia",
  "vinculante_colombia": false,
  "nombre_coincidencia": "PEREZ GOMEZ, Juan",
  "score": 0.97,
  "resultado": "exacto",
  "fundamento_legal": "SDNTK",
  "match_por": "nombre",
  "documento_coincidencia": { "tipo": "Cedula No.", "numero": "1077089147", "pais": "Colombia" },
  "derivado": false,
  "derivado_de": null
}

GET /api/v1/consultas

curl -s "https://api.valida.metrikone.co/api/v1/consultas?limite=50&desde=2026-09-01T00:00:00Z&severidad=alto&sujeto_obligado_nit=800123456" \
  -H "Authorization: Bearer $VALIDA_API_KEY"

GET /api/v1/reporte/{consulta_id}

curl -s https://api.valida.metrikone.co/api/v1/reporte/4f8e2a91-1c3e-4f0a-9d2b-1a2b3c4d5e6f \
  -H "Authorization: Bearer $VALIDA_API_KEY" -o reporte.pdf

POST /api/v1/reporte-lote

curl -s -X POST https://api.valida.metrikone.co/api/v1/reporte-lote \
  -H "Authorization: Bearer $VALIDA_API_KEY" -H "Content-Type: application/json" \
  -d '{ "consulta_ids": ["4f8e2a91-…", "7b2c1d83-…"], "titulo": "Cargue plantilla septiembre 2026" }' -o lote.pdf

GET /api/v1/cuenta/consumo

curl -s https://api.valida.metrikone.co/api/v1/cuenta/consumo -H "Authorization: Bearer $VALIDA_API_KEY"
Respuesta 200
{
  "cliente": { "cliente_id": "55a4400c-…", "nombre": "Plataforma Ejemplo" },
  "plan": { "codigo": "20K", "nombre": "Paquete 20.000 consultas/mes", "consultas_incluidas": 20000, "precio_mes": 1400000,
            "precio_unitario": 70, "precio_excedente": 50, "a_medida": false, "moneda": "COP", "iva_incluido": false },
  "periodo": { "inicio": "2026-09-01", "fin": "2026-10-01", "zona": "America/Bogota", "dias_restantes": 23, "dia_del_periodo": 8,
               "renovacion_en": "2026-10-01T00:00:00-05:00" },
  "consumo": { "consumidas": 16420, "incluidas": 20000, "restantes": 3580, "porcentaje": 82.1, "excedente": 0,
               "excedente_precio_unitario": 50, "excedente_valor_estimado": 0, "estado": "umbral_80", "actualizado_en": "2026-09-08T14:02:11Z" },
  "cobro": { "cuenta_emitida_en": "2026-09-07T16:10:00Z", "cuenta_vence_en": "2026-09-22T00:00:00Z", "cuenta_referencia": "CC-0042",
             "pago_registrado_en": null, "cuenta_vencida_sin_pago": false, "bloqueado": false },
  "politica": { "bloqueo_por_consumo": false, "bloqueo_por_mora": "Solo con cuenta de cobro vencida sin pago registrado Y consumo por encima del 100% del paquete.",
                "excedente": "Se cobra al precio unitario del escalon siguiente y entra en la cuenta del siguiente periodo.",
                "rollover": false, "ciclo": "Mes calendario America/Bogota", "umbrales_alerta": [80, 100] }
}

GET /api/v1/cuenta/consumo/historial

curl -s "https://api.valida.metrikone.co/api/v1/cuenta/consumo/historial?periodos=6" -H "Authorization: Bearer $VALIDA_API_KEY"

GET / PUT /api/v1/cuenta/alertas

curl -s https://api.valida.metrikone.co/api/v1/cuenta/alertas -H "Authorization: Bearer $VALIDA_API_KEY"

curl -s -X PUT https://api.valida.metrikone.co/api/v1/cuenta/alertas \
  -H "Authorization: Bearer $VALIDA_API_KEY" -H "Content-Type: application/json" \
  -d '{ "umbrales": [50, 80, 100, 120], "emails": ["cumplimiento@suempresa.co"], "webhook": { "url": "https://suempresa.co/valida/webhook" }, "activa": true }'

POST /api/v1/cuenta/alertas/webhook/rotar-secreto · POST /api/v1/cuenta/alertas/prueba

curl -s -X POST https://api.valida.metrikone.co/api/v1/cuenta/alertas/webhook/rotar-secreto -H "Authorization: Bearer $VALIDA_API_KEY"
curl -s -X POST https://api.valida.metrikone.co/api/v1/cuenta/alertas/prueba -H "Authorization: Bearer $VALIDA_API_KEY"

14. Glosario

TérminoSignificado
tierClasificación normativa de la lista: 1_vinculante (obligación legal en Colombia), 2_obligatoria (el sujeto obligado debe construirla: PEP), 3_referencia (no vinculante, estándar de facto: OFAC SDN, Unión Europea y US State Dept FTO).
matchUna entrada de una lista cuyo nombre, alias o documento coincide con lo consultado. Una consulta puede tener cero, uno o varios.
scoreSimilitud entre 0 y 1 del nombre consultado contra el nombre o alias de la entrada (Jaro-Winkler 70% + Levenshtein 30% sobre nombres normalizados). Un match por documento tiene score 1.
resultadoexacto (score ≥ 0.95) o posible (0.70 a 0.95). Un posible exige análisis del oficial de cumplimiento; no es una confirmación.
severidadResumen de la consulta: alto (exacto en tier 1), medio (exacto en tier 2 o 3), bajo (solo posibles), informativo, sin_hallazgo.
consulta_parcialLa consulta trajo solo nombre o solo documento. La cobertura puede ser menor; el PDF lo advierte.
match_por / derivadoPor qué campo coincidió (nombre o documento). derivado = salió de un segundo pase con el dato complementario que trajo la entrada (por ejemplo, un documento encontrado por nombre se revalidó contra las demás listas).
versión de listaDescarga concreta de una lista desde su fuente oficial, identificada por version_id, hash_contenido y fetched_en. Toda consulta registra las versiones contra las que corrió.
sujeto obligadoLa empresa que por ley debe hacer la verificación SARLAFT. Con un agregador, es el cliente final de la plataforma, no la plataforma.
periodoMes calendario en America/Bogotá. El contador vuelve a cero el día 1.
paquete / incluidasConsultas del mes cubiertas por el precio fijo del plan.
excedenteConsultas por encima de las incluidas. Se cobran al unitario del escalón siguiente en la cuenta del siguiente periodo. No bloquean.
bloqueo por moraÚnico caso en que /validate responde 402: cuenta de cobro vencida sin pago registrado y consumo por encima del 100%.
Idempotency-KeyClave que usted elige por consulta para que un reintento devuelva la misma respuesta en vez de crear (y cobrar) otra.
request_idIdentificador de cada petición (header X-Valida-Request-Id y cuerpo de error). Cítelo en soporte.

15. Changelog

1.2.0 · 2026-09-09

  • Nuevo módulo POST /diligencia (beta) con dos fuentes nacionales: SIRI de la Procuraduría y multas de SECOP II. Aislado del motor SARLAFT: tabla propia, sello de referencia y consumo aparte. Ver §6.
  • El catálogo de listas queda separado por módulo. /validate y listas_consultadas[] solo devuelven listas SARLAFT; ninguna fuente de Diligencia puede entrar a un reporte SARLAFT.

1.1.0 · 2026-09-08

  • Formato de error uniforme { error, message, doc_url, request_id, issues? } y header X-Valida-Request-Id en toda respuesta. CORS (preflight) en /api/v1.
  • Idempotency-Key en POST /validate con replay 24 h y 409 idempotency_error. Campo referencia_externa y filtro en /consultas.
  • listas_consultadas[] y X-Valida-Listas-Version: la versión de cada lista queda grabada con la consulta y el PDF la lee de ahí.
  • sujeto_obligado en /validate (obligatorio para clientes que operan para terceros), estampado en el PDF; filtro sujeto_obligado_nit.
  • Contador de paquete: headers X-Valida-Plan / X-Valida-Periodo-* / X-Valida-Consumo-*, GET /cuenta/consumo y /cuenta/consumo/historial.
  • Cobro y bloqueo por mora: 402 paquete_vencido_sin_pago solo con cuenta vencida sin pago y consumo > 100%.
  • Alertas: GET/PUT /cuenta/alertas, rotación de secreto, prueba, webhooks firmados (X-Valida-Signature) con reintentos, eventos paquete.*.
  • Retención de consultas y evidencia: 10 años (antes 5).
  • Documentación: se retiran del contrato el 429 rate_limit, 403 permiso_denegado y 503 que nunca existieron, y el límite de "1000 consultas/día".

1.0.0-mvp · 2026-05

  • POST /validate, GET /consultas, GET /reporte/{id}, POST /reporte-lote, GET /health.

Política de versionado: los cambios compatibles (campos y headers nuevos, códigos de error nuevos) se publican aquí sin cambiar la ruta. Un cambio incompatible saldría como /api/v2 con al menos 90 días de convivencia.

16. Soporte