API de certificación de archivos

La certificación de archivos permite subir uno o varios archivos y obtener por cada uno una constancia NOM-151 (sello de tiempo de un Prestador de Servicios de Certificación). Esta guía describe los endpoints que consume un integrador.

Autenticación

Todos los endpoints usan el token de acceso de la API de Firma en el header Authorization: Bearer <token>. Vea Autenticación para obtener y renovar el token.

Roles: certificar archivos requiere un usuario con rol Owner, Administrador o Manager. Las demás rutas (listar, detalle, descargar, eventos y verificar) requieren solo un usuario de la empresa con sesión válida.

URL base

AmbienteURL base
Sandboxhttps://api.sandbox.jaak.ai
Producciónhttps://services.api.jaak.ai

Todos los paths (/api/v1/file-certifications/...) son relativos a esta base.

Cuota

Cada archivo certificado consume 1 unidad del consumible de certificación de archivos. La cuota se asigna por empresa (contacte a JAAK). Si la empresa no tiene unidades disponibles, la solicitud responde 429 y no se certifica ningún archivo. La respuesta de certificación incluye quota_remaining, el saldo restante.

Límites por solicitud

LímiteValor
Archivos por solicitud1 a 20
Tamaño por archivo10 MB
Tamaño total90 MB

Excederlos responde 400 (sin archivos, más de 20 o un archivo vacío) o 413 (un archivo mayor a 10 MB o un total mayor a 90 MB).


Certificar archivos

POST/api/v1/file-certifications

Sube uno o varios archivos y sella cada uno con una constancia NOM-151

Body (multipart/form-data)

CampoTipoRequeridoDescripción
filesfile[]SíArchivos a certificar (1 a 20, 10 MB cada uno, 90 MB en total).

Ejemplo de solicitud

curl -X POST https://api.sandbox.jaak.ai/api/v1/file-certifications \
  -H "Authorization: Bearer $TOKEN" \
  -F "files=@contrato.pdf" \
  -F "files=@anexo.pdf"

Respuesta exitosa (200 OK)

Cada archivo produce un resultado independiente en results; revise el campo status de cada uno. Si un archivo falla, los demás se certifican con normalidad y la unidad de cuota del archivo fallido no se consume.

{
  "batch_id": "batch_9f8e7d6c",
  "results": [
    {
      "id": "3f9a2b8c-1d4e-4f5a-9b6c-7e8d9f0a1b2c",
      "batch_id": "batch_9f8e7d6c",
      "filename": "contrato.pdf",
      "content_type": "application/pdf",
      "size_bytes": 483922,
      "sha256": "a3f1...b7e9",
      "status": "certified",
      "certificate_id": "NOM151-2026-000123",
      "certified_at": "2026-11-13T15:02:11Z",
      "created_at": "2026-11-13T15:02:09Z",
      "created_by": "usr_5a4b3c2d",
      "error_message": "",
      "storage_document_id": "doc_8c7b6a5d"
    },
    {
      "id": "e2d1c0b9-8a7b-4c6d-9e0f-1a2b3c4d5e6f",
      "batch_id": "batch_9f8e7d6c",
      "filename": "anexo.pdf",
      "content_type": "application/pdf",
      "size_bytes": 120044,
      "sha256": "c4b2...9d1a",
      "status": "certified",
      "certificate_id": "NOM151-2026-000124",
      "certified_at": "2026-11-13T15:02:12Z",
      "created_at": "2026-11-13T15:02:09Z",
      "created_by": "usr_5a4b3c2d",
      "error_message": "",
      "storage_document_id": "doc_1a2b3c4e"
    }
  ],
  "certified_count": 2,
  "failed_count": 0,
  "quota_remaining": 48
}

Errores

CódigoCuándo ocurre
400El cuerpo no es multipart/form-data, no se envió ningún archivo, se enviaron más de 20 o algún archivo está vacío
401Token ausente, inválido o expirado
403El rol del usuario no permite certificar (requiere Owner, Administrador o Manager)
413Algún archivo excede 10 MB o la solicitud excede 90 MB en total
429La empresa no tiene unidades de certificación disponibles
500Error interno; contacte a soporte con el identificador de la solicitud

Listar certificaciones

GET/api/v1/file-certifications

Lista paginada de los archivos certificados de la empresa

Query params

ParámetroTipoDescripción
pageintPágina (desde 1).
limitintTamaño de página (máximo 100).
batch_idstringFiltra por lote de carga.
statusstringFiltra por estado: certified o failed.
searchstringBusca por nombre de archivo (coincidencia parcial, sin distinguir mayúsculas).

Ejemplo de solicitud

curl "https://api.sandbox.jaak.ai/api/v1/file-certifications?page=1&limit=20&search=contrato" \
  -H "Authorization: Bearer $TOKEN"

Respuesta exitosa (200 OK)

{
  "items": [
    {
      "id": "3f9a2b8c-1d4e-4f5a-9b6c-7e8d9f0a1b2c",
      "batch_id": "batch_9f8e7d6c",
      "filename": "contrato.pdf",
      "content_type": "application/pdf",
      "size_bytes": 483922,
      "sha256": "a3f1...b7e9",
      "status": "certified",
      "certificate_id": "NOM151-2026-000123",
      "certified_at": "2026-11-13T15:02:11Z",
      "created_at": "2026-11-13T15:02:09Z",
      "created_by": "usr_5a4b3c2d",
      "error_message": "",
      "storage_document_id": "doc_8c7b6a5d"
    }
  ],
  "total": 1,
  "page": 1,
  "limit": 20
}

Detalle de una certificación

GET/api/v1/file-certifications/{id}

Devuelve la certificación y su constancia NOM-151 en Base64

id es el identificador (UUID) de la certificación.

Respuesta exitosa (200 OK)

{
  "certification": {
    "id": "3f9a2b8c-1d4e-4f5a-9b6c-7e8d9f0a1b2c",
    "batch_id": "batch_9f8e7d6c",
    "filename": "contrato.pdf",
    "content_type": "application/pdf",
    "size_bytes": 483922,
    "sha256": "a3f1...b7e9",
    "status": "certified",
    "certificate_id": "NOM151-2026-000123",
    "certified_at": "2026-11-13T15:02:11Z",
    "created_at": "2026-11-13T15:02:09Z",
    "created_by": "usr_5a4b3c2d",
    "error_message": "",
    "storage_document_id": "doc_8c7b6a5d"
  },
  "constancia_base64": "JVBERi0xLjQKJ..."
}

La constancia en constancia_base64 es el documento del PSC (formato PDF en Base64).

CódigoCuándo ocurre
404No existe una certificación con ese id en su empresa

Descargar el archivo certificado

GET/api/v1/file-certifications/{id}/download

Descarga el archivo original certificado

curl -o contrato.pdf "https://api.sandbox.jaak.ai/api/v1/file-certifications/3f9a2b8c-1d4e-4f5a-9b6c-7e8d9f0a1b2c/download" \
  -H "Authorization: Bearer $TOKEN"

Respuesta exitosa (200 OK)

El cuerpo de la respuesta son los bytes del archivo (Content-Type: application/octet-stream), idéntico al original: su huella SHA-256 coincide con la registrada.

CódigoCuándo ocurre
404No existe una certificación con ese id en su empresa

Histórico de eventos

GET/api/v1/file-certifications/{id}/events

Devuelve el histórico de eventos de una certificación, del más antiguo al más reciente

Respuesta exitosa (200 OK)

{
  "events": [
    {
      "event_type": "file_uploaded",
      "action": "upload",
      "actor_id": "usr_5a4b3c2d",
      "result": "SUCCESS",
      "timestamp": "2026-11-13T15:02:09Z",
      "metadata": {}
    },
    {
      "event_type": "nom151_issued",
      "action": "seal",
      "actor_id": "usr_5a4b3c2d",
      "result": "SUCCESS",
      "timestamp": "2026-11-13T15:02:11Z",
      "metadata": {}
    },
    {
      "event_type": "file_verified",
      "action": "verify",
      "actor_id": "usr_9z8y7x6w",
      "result": "SUCCESS",
      "timestamp": "2026-11-13T16:40:02Z",
      "metadata": {}
    }
  ]
}
CampoDescripción
event_typeTipo de evento: file_uploaded (archivo subido), nom151_issued (constancia emitida), nom151_failed (constancia no emitida), file_downloaded (archivo descargado), file_verified (archivo verificado).
actionAcción asociada al evento.
actor_idUsuario que realizó la acción.
resultSUCCESS o FAILURE.
timestampFecha y hora del evento (RFC 3339, UTC).
metadataDatos adicionales del evento.

Verificar archivos

Verificar compara la huella SHA-256 del archivo que envía con la huella registrada de un archivo certificado de su empresa. El archivo no se guarda y no se certifica nada; la verificación no consume cuota.

Verificación contra una certificación

POST/api/v1/file-certifications/{id}/verify

Compara un archivo con la huella de una certificación específica

Body (multipart/form-data)

CampoTipoRequeridoDescripción
filefileSíArchivo a comparar (exactamente uno).
curl -X POST https://api.sandbox.jaak.ai/api/v1/file-certifications/3f9a2b8c-1d4e-4f5a-9b6c-7e8d9f0a1b2c/verify \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@contrato.pdf"

Verificación masiva

POST/api/v1/file-certifications/verify

Compara de 1 a 20 archivos con los archivos certificados de la empresa

Body (multipart/form-data)

CampoTipoRequeridoDescripción
filesfile[]SíArchivos a comparar (1 a 20, con los mismos límites de tamaño).
curl -X POST https://api.sandbox.jaak.ai/api/v1/file-certifications/verify \
  -H "Authorization: Bearer $TOKEN" \
  -F "files=@contrato.pdf" \
  -F "files=@copia-modificada.pdf"

Respuesta exitosa (200 OK, ambos endpoints)

results mantiene el orden de los archivos enviados.

{
  "results": [
    {
      "filename": "contrato.pdf",
      "sha256": "a3f1...b7e9",
      "valid": true,
      "certification": {
        "id": "3f9a2b8c-1d4e-4f5a-9b6c-7e8d9f0a1b2c",
        "batch_id": "batch_9f8e7d6c",
        "filename": "contrato.pdf",
        "content_type": "application/pdf",
        "size_bytes": 483922,
        "sha256": "a3f1...b7e9",
        "status": "certified",
        "certificate_id": "NOM151-2026-000123",
        "certified_at": "2026-11-13T15:02:11Z",
        "created_at": "2026-11-13T15:02:09Z",
        "created_by": "usr_5a4b3c2d",
        "error_message": "",
        "storage_document_id": "doc_8c7b6a5d"
      },
      "reason": ""
    },
    {
      "filename": "copia-modificada.pdf",
      "sha256": "00aa...11bb",
      "valid": false,
      "certification": null,
      "reason": "not_found"
    }
  ],
  "valid_count": 1,
  "invalid_count": 1
}
CampoDescripción
validtrue cuando la huella coincide con la de un archivo certificado.
certificationLa certificación con la que coincidió (ausente si no hay coincidencia).
reasonMotivo cuando no es válido: hash_mismatch (el contenido cambió respecto de la certificación consultada), not_found (la empresa no tiene ningún archivo certificado con esa huella) o not_certified (el archivo no está certificado).

Errores

CódigoCuándo ocurre
400El cuerpo no es multipart/form-data, falta el archivo, se envió más de un archivo en /{id}/verify o se enviaron más de 20 archivos
404La certificación consultada no existe en su empresa (solo en /{id}/verify)
413Algún archivo excede 10 MB o la solicitud excede 90 MB en total

Formato de error

Los errores usan el mismo cuerpo en todos los endpoints de certificación de archivos:

{
  "error": "cuota de certificaciones de archivos agotada",
  "message": "cuota de certificaciones de archivos agotada"
}

error y message contienen la misma descripción, para compatibilidad con clientes que lean cualquiera de los dos campos.

Siguientes pasos