Informes de evidencias
Cada verificación completada lleva un informe de evidencias: un documento que registra el veredicto, los hallazgos que lo sustentan con sus fuentes y el pin con el que se derivó. Puede entregarlo a un responsable de cumplimiento, a un auditor o a una contraparte, y estos pueden confirmar que es auténtico sin ninguna cuenta. El informe está incluido en el precio de la verificación y nunca se factura por separado.
De dónde sale el enlace
Una verificación completada tiene un objeto report (vea Verificaciones de dirección):
| Campo | Descripción |
|---|---|
id | El ID del informe: r1_ seguido de 32 caracteres. |
pdf_url | El informe en PDF. |
json_url | El gemelo legible por máquina del PDF. |
verification_url | La consulta de integridad. |
report es null mientras la verificación está pending o failed. El enlace es permanente: nunca caduca.
Los informes se abren sin clave de API. El ID del informe en la URL es la única protección, así que cualquiera que tenga el enlace puede abrir el informe. Trátelo como el propio informe: no lo pegue en tickets públicos, chats ni registros, y compártalo solo con quienes deban leerlo.
Abra el informe
Los tres endpoints son públicos y no necesitan el encabezado Authorization. Tienen límite de solicitudes por dirección IP de origen; vea Límites de solicitudes y cuotas.
PDF
GET /v1/reports/{token}/pdf, donde {token} es el ID del informe.
La primera vez que se abre un informe en un idioma y un diseño determinados, se genera en el momento y la solicitud espera hasta unos 20 segundos. Cada apertura posterior entrega el archivo almacenado, con su integridad comprobada.
| Parámetro de consulta | Descripción |
|---|---|
lang | El idioma del informe. Inglés si se omite. Uno de en, es, pt, ru, uk, tr, vi, id, zh, ja, ko, hi, ar, fr, de. |
templateId | El diseño por número, de 1 a 6. |
templateCode | El diseño por nombre. Se ignora si también se envía templateId. |
templateId | templateCode |
|---|---|
| 1 | datasheet |
| 2 | classic |
| 3 | editorial |
| 4 | signal |
| 5 | soft |
| 6 | depth |
Si no envía ninguno, el informe se abre en el diseño al que quedó fijado cuando se creó. Un idioma, un id o un código desconocidos, o un ID de informe mal formado, responden 400 VALIDATION_ERROR y parameter indica el parámetro de consulta erróneo; los códigos distinguen mayúsculas de minúsculas.
Si el documento aún se está generando y no está listo dentro de la espera, la solicitud responde 503 REPORT_RENDERING con Retry-After: espere esa cantidad de segundos y abra de nuevo el mismo enlace. Si la generación falló, responde 503 REPORT_RENDER_FAILED; el mensaje incluye el ID corto del informe que debe indicar a soporte, y abrir el enlace otra vez tras una breve pausa reintenta la generación.
- curl
- Node.js
- Python
curl -s -o report.pdf "https://api.leeri.ai/v1/reports/$REPORT_ID/pdf?lang=es&templateCode=classic"
import { writeFile } from 'node:fs/promises';
const url = `https://api.leeri.ai/v1/reports/${reportId}/pdf?lang=es&templateCode=classic`;
const response = await fetch(url);
if (response.status === 503) {
console.log('not ready, retry in', response.headers.get('retry-after'), 'seconds');
} else if (response.ok) {
await writeFile('report.pdf', Buffer.from(await response.arrayBuffer()));
}
import requests
response = requests.get(
f"https://api.leeri.ai/v1/reports/{report_id}/pdf",
params={"lang": "es", "templateCode": "classic"},
timeout=60,
)
if response.status_code == 503:
print("not ready, retry in", response.headers.get("Retry-After"), "seconds")
elif response.ok:
with open("report.pdf", "wb") as f:
f.write(response.content)
Todos los diseños imprimen el ID del informe y la dirección de la página de verificación. Todos menos depth imprimen también el hash del informe.
JSON
GET /v1/reports/{token}/json devuelve el mismo informe como datos, en el sobre de éxito habitual. Se reconstruye a partir del veredicto fijado cuando se registró el informe, así que siempre describe ese veredicto, sea lo que sea lo que haya cambiado desde entonces.
Campo en data | Descripción |
|---|---|
report_id | El ID del informe. |
schema_version | La versión del payload con la que se registró el informe. Fija durante toda la vida del informe: un informe anterior se sirve siempre en su propia versión. |
payload | El contenido del informe que se calcula con hash: el veredicto, su pin, el resultado, los hallazgos con sus fuentes, la exposición, las rutas y la metodología. |
hash | algorithm (SHA-256), canonicalization (RFC 8785), value y covers. |
hash.value es el SHA-256, en hexadecimal, de la forma canónica de payload (canonicalización JSON según RFC 8785). Es igual al hash registrado cuando se entregó el enlace por primera vez.
hash.covers es payload en todo informe actual: puede recalcular el hash a partir del payload recibido y compararlo con hash.value. En algunos informes más antiguos es unredacted_original: el hash cubre una forma anterior del contenido que no se sirve, por lo que no puede recalcularse a partir de la respuesta y se confirma mediante el endpoint de verificación.
Verificación
GET /v1/reports/{token}/verification confirma que un ID de informe es auténtico. Responde:
Campo en data | Descripción |
|---|---|
valid | Siempre true cuando el ID existe; un ID desconocido responde 404. |
issued_at | Cuándo se emitió el informe. |
payload_hash | El SHA-256 registrado, en hexadecimal. |
hash_algorithm | SHA-256. |
No revela nada sobre la dirección, el cliente ni el veredicto, así que puede usarlo para demostrar que un informe es auténtico sin exponer su contenido.
- curl
- Node.js
- Python
curl -s https://api.leeri.ai/v1/reports/$REPORT_ID/verification
const response = await fetch(`https://api.leeri.ai/v1/reports/${reportId}/verification`);
const { data } = await response.json();
console.log(data.valid, data.issued_at, data.payload_hash);
import requests
response = requests.get(f"https://api.leeri.ai/v1/reports/{report_id}/verification", timeout=30)
data = response.json()["data"]
print(data["valid"], data["issued_at"], data["payload_hash"])
Verifique un informe a mano
Cualquiera que tenga un informe puede comprobarlo en https://leeri.ai/es/verify. Pegue el ID del informe y la página muestra cuándo se emitió y el hash registrado. Compare ese hash con el impreso en el informe. Un valor distinto significa que el documento se modificó después de emitirse.
Para comprobar el JSON de forma automática, canonicalice payload con una biblioteca RFC 8785, calcule su SHA-256 y compare el resumen hexadecimal con hash.value y con el payload_hash que devuelve el endpoint de verificación.
Errores esperados
| Estado | Código | Cuándo |
|---|---|---|
400 | VALIDATION_ERROR | Un ID de informe mal formado, o un lang, templateId o templateCode desconocido. |
404 | NOT_FOUND | Ningún informe tiene este ID. |
429 | RATE_LIMIT_EXCEEDED | Demasiadas solicitudes desde esta dirección IP. Reintente tras Retry-After. |
503 | REPORT_RENDERING o REPORT_RENDER_FAILED | El PDF aún se está generando, o la generación falló. |
Para reproducir el veredicto que hay detrás de un informe, vea Rederive.