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
| Environment | Base URL |
|---|---|
| Sandbox | https://api.sandbox.jaak.ai |
| Production | https://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
| Limit | Value |
|---|---|
| Files per request | 1 to 20 |
| Size per file | 10 MB |
| Total size | 90 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
/api/v1/file-certificationsBearer TokenUploads one or several files and seals each one with a NOM-151 certificate
Body (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
files | file[] | Yes | Files 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
| Code | When it happens |
|---|---|
| 400 | The body is not multipart/form-data, no file was sent, more than 20 were sent or a file is empty |
| 401 | Token missing, invalid or expired |
| 403 | The user's role does not allow certifying (requires Owner, Administrator or Manager) |
| 413 | A file exceeds 10 MB or the request exceeds 90 MB in total |
| 429 | The company has no certification units available |
| 500 | Internal error; contact support with the request identifier |
List certifications
/api/v1/file-certificationsBearer TokenPaginated list of the company's certified files
Query params
| Parameter | Type | Description |
|---|---|---|
page | int | Page (from 1). |
limit | int | Page size (maximum 100). |
batch_id | string | Filter by upload batch. |
status | string | Filter by status: certified or failed. |
search | string | Search 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
/api/v1/file-certifications/{id}Bearer TokenReturns 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).
| Code | When it happens |
|---|---|
| 404 | No certification with that id exists in your company |
Download the certified file
/api/v1/file-certifications/{id}/downloadBearer TokenDownloads 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.
| Code | When it happens |
|---|---|
| 404 | No certification with that id exists in your company |
Event history
/api/v1/file-certifications/{id}/eventsBearer TokenReturns 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": {}
}
]
}
| Field | Description |
|---|---|
event_type | Event type: file_uploaded (file uploaded), nom151_issued (certificate issued), nom151_failed (certificate not issued), file_downloaded (file downloaded), file_verified (file verified). |
action | Action associated with the event. |
actor_id | User who performed the action. |
result | SUCCESS or FAILURE. |
timestamp | Event date and time (RFC 3339, UTC). |
metadata | Additional 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
/api/v1/file-certifications/{id}/verifyBearer TokenCompares a file with the fingerprint of a specific certification
Body (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
file | file | Yes | File 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
/api/v1/file-certifications/verifyBearer TokenCompares 1 to 20 files with the company's certified files
Body (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
files | file[] | Yes | Files 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
}
| Field | Description |
|---|---|
valid | true when the fingerprint matches a certified file's. |
certification | The matched certification (absent when there is no match). |
reason | Reason 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
| Code | When it happens |
|---|---|
| 400 | The 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 |
| 404 | The queried certification does not exist in your company (only on /{id}/verify) |
| 413 | A 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
- Authentication - Get and renew your access token
- File certification - Guide for the screen in the JAAK Platform
- Errors - Complete catalogue of error codes