File certification API

File certification lets you upload one or several files and obtain a NOM-151 certificate (timestamp seal from a Certification Services Provider) for each one. This guide describes the endpoints an integrator consumes.

Authentication

Every endpoint uses the Signature API access token in the Authorization: Bearer <token> header. See Authentication to obtain and renew the token.

Roles: certifying files requires a user with the Owner, Administrator or Manager role. The other routes (list, detail, download, events and verify) only require a company user with a valid session.

Base URL

EnvironmentBase URL
Sandboxhttps://api.sandbox.jaak.ai
Productionhttps://services.api.jaak.ai

All paths (/api/v1/file-certifications/...) are relative to this base.

Quota

Each certified file consumes 1 unit of the file certification consumable. Quota is assigned per company (contact JAAK). If the company has no units available, the request answers 429 and nothing is certified. The certification response includes quota_remaining, the remaining balance.

Limits per request

LimitValue
Files per request1 to 20
Size per file10 MB
Total size90 MB

Exceeding them answers 400 (no files, more than 20 or an empty file) or 413 (a file over 10 MB or a total over 90 MB).


Certify files

POST/api/v1/file-certifications

Uploads one or several files and seals each one with a NOM-151 certificate

Body (multipart/form-data)

FieldTypeRequiredDescription
filesfile[]YesFiles to certify (1 to 20, 10 MB each, 90 MB total).

Request example

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

Successful response (200 OK)

Each file produces an independent result in results; check each one's status field. If a file fails, the others certify normally and the failed file's quota unit is not consumed.

{
  "batch_id": "batch_9f8e7d6c",
  "results": [
    {
      "id": "3f9a2b8c-1d4e-4f5a-9b6c-7e8d9f0a1b2c",
      "batch_id": "batch_9f8e7d6c",
      "filename": "contract.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"
    }
  ],
  "certified_count": 1,
  "failed_count": 0,
  "quota_remaining": 49
}

Errors

CodeWhen it happens
400The body is not multipart/form-data, no file was sent, more than 20 were sent or a file is empty
401Token missing, invalid or expired
403The user's role does not allow certifying (requires Owner, Administrator or Manager)
413A file exceeds 10 MB or the request exceeds 90 MB in total
429The company has no certification units available
500Internal error; contact support with the request identifier

List certifications

GET/api/v1/file-certifications

Paginated list of the company's certified files

Query params

ParameterTypeDescription
pageintPage (from 1).
limitintPage size (maximum 100).
batch_idstringFilter by upload batch.
statusstringFilter by status: certified or failed.
searchstringSearch by file name (partial match, case-insensitive).

Request example

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

Successful response (200 OK)

{
  "items": [
    {
      "id": "3f9a2b8c-1d4e-4f5a-9b6c-7e8d9f0a1b2c",
      "batch_id": "batch_9f8e7d6c",
      "filename": "contract.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
}

Certification detail

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

Returns the certification and its NOM-151 certificate in Base64

id is the certification's identifier (UUID).

Successful response (200 OK)

{
  "certification": {
    "id": "3f9a2b8c-1d4e-4f5a-9b6c-7e8d9f0a1b2c",
    "batch_id": "batch_9f8e7d6c",
    "filename": "contract.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..."
}

The document in constancia_base64 is the PSC certificate (PDF format in Base64).

CodeWhen it happens
404No certification with that id exists in your company

Download the certified file

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

Downloads the original certified file

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

Successful response (200 OK)

The response body is the file's bytes (Content-Type: application/octet-stream), identical to the original: its SHA-256 fingerprint matches the recorded one.

CodeWhen it happens
404No certification with that id exists in your company

Event history

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

Returns the event history of a certification, oldest first

Successful response (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": {}
    }
  ]
}
FieldDescription
event_typeEvent type: file_uploaded (file uploaded), nom151_issued (certificate issued), nom151_failed (certificate not issued), file_downloaded (file downloaded), file_verified (file verified).
actionAction associated with the event.
actor_idUser who performed the action.
resultSUCCESS or FAILURE.
timestampEvent date and time (RFC 3339, UTC).
metadataAdditional event data.

Verify files

Verify compares the SHA-256 fingerprint of the file you send with the recorded fingerprint of a certified file of your company. The file is not stored and nothing is certified; verification does not consume quota.

Verify against one certification

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

Compares a file with the fingerprint of a specific certification

Body (multipart/form-data)

FieldTypeRequiredDescription
filefileYesFile to compare (exactly one).
curl -X POST https://api.sandbox.jaak.ai/api/v1/file-certifications/3f9a2b8c-1d4e-4f5a-9b6c-7e8d9f0a1b2c/verify \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@contract.pdf"

Bulk verification

POST/api/v1/file-certifications/verify

Compares 1 to 20 files with the company's certified files

Body (multipart/form-data)

FieldTypeRequiredDescription
filesfile[]YesFiles to compare (1 to 20, with the same size limits).
curl -X POST https://api.sandbox.jaak.ai/api/v1/file-certifications/verify \
  -H "Authorization: Bearer $TOKEN" \
  -F "files=@contract.pdf" \
  -F "files=@modified-copy.pdf"

Successful response (200 OK, both endpoints)

results keeps the order of the files sent.

{
  "results": [
    {
      "filename": "contract.pdf",
      "sha256": "a3f1...b7e9",
      "valid": true,
      "certification": {
        "id": "3f9a2b8c-1d4e-4f5a-9b6c-7e8d9f0a1b2c",
        "batch_id": "batch_9f8e7d6c",
        "filename": "contract.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": "modified-copy.pdf",
      "sha256": "00aa...11bb",
      "valid": false,
      "certification": null,
      "reason": "not_found"
    }
  ],
  "valid_count": 1,
  "invalid_count": 1
}
FieldDescription
validtrue when the fingerprint matches a certified file's.
certificationThe matched certification (absent when there is no match).
reasonReason when not valid: hash_mismatch (the content changed compared to the queried certification), not_found (the company has no certified file with that fingerprint) or not_certified (the file is not certified).

Errors

CodeWhen it happens
400The body is not multipart/form-data, the file is missing, more than one file was sent to /{id}/verify, or more than 20 files were sent
404The queried certification does not exist in your company (only on /{id}/verify)
413A file exceeds 10 MB or the request exceeds 90 MB in total

Error format

Errors use the same body in every file certification endpoint:

{
  "error": "file certification quota exhausted",
  "message": "file certification quota exhausted"
}

error and message carry the same description, for compatibility with clients reading either field.

Next steps