Validate a document
Authenticate with your API key, upload documents one-by-one or in batch, and receive complete, audit-ready ValidationReports. Every field, enum, error and warning is documented below.
https://api.sealium.euAuthentication
Authenticate with your secret API key as a Bearer token. The key is created in your dashboard and shown once. The Free tier includes 100 validations a month — no credit card required.
Authorization: Bearer slm_live_...The API key works on the developer API: /v1/validate, /v1/batch and /v1/reports. Account management (usage, keys, billing, webhook configuration) lives in the dashboard and authenticates with your account session, not the API key.
/v1/validateValidates a single document and returns a ValidationReport. The document bytes are processed in memory and never stored — only the report is persisted.
Request
Body parameters
| Field | Type | Required | Description |
|---|---|---|---|
file | binary | required | The document to validate. Max 50 MB. The format is detected automatically from the file's magic bytes — you never specify a type. Accepts PDF, ASiC-E, ASiC-S, KRX, XAdES, CAdES and JAdES. |
There are no path or query parameters.
Example request
curl -X POST https://api.sealium.eu/v1/validate \ -H "Authorization: Bearer slm_live_..." \ -F "file=@contract.pdf"Response
200 OK returns a ValidationReport. Fields that don't apply to a given document are omitted (the API uses JSON omit-null), so a typical PDF response is more compact than the full schema.
{ "documentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "filename": "contract.pdf", "format": "PDF", "valid": true, "documentIntact": true, "validatedAt": "2026-06-01T20:00:00Z", "signatures": [ { "signatureId": "id-abc123", "signerDn": "CN=Anna Schmidt, O=Example GmbH, C=DE", "signerName": "Anna Schmidt", "signingTime": "2026-06-01T10:00:00Z", "claimedSigningTime": "2026-06-01T10:00:00Z", "bestSignatureTime": "2026-06-01T10:00:01Z", "signatureIntact": true, "certValid": true, "revocationOk": true, "timestampValid": true, "indication": "TOTAL_PASSED", "subIndication": null, "signatureLevel": "QES", "signatureFormat": "PAdES_BASELINE_LT", "certIssuerDn": "CN=EU Qualified CA G2, O=TrustProvider, C=EU", "certNotBefore": "2024-01-01T00:00:00Z", "certNotAfter": "2027-01-01T00:00:00Z", "certExpiresInDays": 245, "certExpiryWarning": false, "timestamps": [ { "type": "SIGNATURE_TIMESTAMP", "productionTime": "2026-06-01T10:00:01Z", "valid": true, "issuerDn": "CN=Qualified TSA, O=TrustProvider, C=EU" } ], "certChain": [ { "subjectDn": "CN=Anna Schmidt, ...", "trusted": false, "...": "..." }, { "subjectDn": "CN=EU Qualified CA G2, ...", "trusted": true, "...": "..." } ] } ], "signaturesCount": 1, "validSignaturesCount": 1, "validationSummary": { "totalSignatures": 1, "totalPassed": 1, "totalIndeterminate": 0, "totalFailed": 0, "hasQualifiedSignature": true, "allQualified": true }, "pdfMetadata": { "title": "Service agreement 2026", "author": "Anna Schmidt", "creator": "Microsoft Word", "creationDate": "2026-05-15T08:30:00Z", "modificationDate": "2026-06-01T09:55:00Z", "encrypted": false, "pageCount": 12 }, "lotlSummary": { "loaded": true, "lastRefresh": "2026-06-01T03:00:00Z", "trustedListsCount": 31 }, "errorCode": null, "errorMessage": null, "warningCode": null, "warningMessage": null, "krxDocuments": null}Batch validation
Validate many documents in one asynchronous job. Available on Business and above — lower tiers receive 403 FEATURE_NOT_AVAILABLE.
/v1/batchSubmits up to 50 documents (multipart field files, repeatable) and returns 202 Accepted with { jobId, status, totalItems } immediately. Validation runs in the background — poll the job until status leaves PROCESSING. As with single validation, document bytes are staged transiently and deleted when the job finishes; only the reports are persisted.
curl -X POST https://api.sealium.eu/v1/batch \ -H "Authorization: Bearer slm_live_..." \ -F "files=@contract.pdf" \ -F "files=@annex-a.asice" \ -F "files=@invoice.xml"/v1/batch/{jobId}Job status with per-item results. Each completed item carries a reportId — fetch the full report via GET /v1/reports/{id}.
{ "jobId": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "status": "PARTIAL", "totalItems": 3, "completedItems": 2, "failedItems": 1, "createdAt": "2026-06-10T09:00:00Z", "finishedAt": "2026-06-10T09:00:41Z", "items": [ { "itemId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "filename": "contract.pdf", "status": "COMPLETED", "reportId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }, { "itemId": "9b2f3c1d-2c5a-4b8e-9f0d-1a2b3c4d5e6f", "filename": "annex-a.asice", "status": "COMPLETED", "reportId": "1c0d7e2a-4b6f-4f3a-8d9e-2f1a0b3c4d5e" }, { "itemId": "5e4d3c2b-1a0f-4e9d-8c7b-6a5f4e3d2c1b", "filename": "invoice.xml", "status": "FAILED", "reportId": null, "errorCode": "PARSE_ERROR" } ]}| Field | Type | Description |
|---|---|---|
jobId | string · uuid | Unique id of the batch job. |
status | enum JobStatus | PENDING → PROCESSING → COMPLETED, PARTIAL or FAILED. See below. |
totalItems | integer | Number of documents submitted in this job. |
completedItems | integer | Documents validated successfully so far. |
failedItems | integer | Documents that could not be processed. |
createdAt | string · date-time | When the job was submitted. |
finishedAt | string · date-time | null | When the job finished. null while still running. |
items | BatchJobItem[] | One entry per submitted document. Omitted in the GET /v1/batch list view. |
BatchJobItem
| Field | Type | Description |
|---|---|---|
itemId | string · uuid | Id of this document within the job. |
filename | string | Original filename of the submitted document. |
status | enum | PENDING, PROCESSING, COMPLETED or FAILED. |
reportId | string · uuid | null | Id of the resulting ValidationReport — fetch it via GET /v1/reports/{id}. null until completed or on failure. |
errorCode | string | null | Why this item failed (e.g. PARSE_ERROR). null unless status is FAILED. |
status — JobStatus
| Value | Description |
|---|---|
PENDING | Job accepted, waiting for a worker. |
PROCESSING | Documents are being validated. |
COMPLETED | Every document validated successfully. |
PARTIAL | Finished, but some documents failed — check items[].errorCode. |
FAILED | No document could be processed. |
/v1/batchThe 20 most recent jobs for your account — the same fields as the detail view, without items.
Reports
Every validation — single or batch — persists a ValidationReport you can retrieve later. Documents themselves are never stored.
/v1/reportsPaginated report list, newest first — metadata only.
Query parameters
| Field | Type | Description |
|---|---|---|
page | integer | Zero-based page index. Default 0. |
size | integer | Page size. Default 20, max 100. |
q | string | Signer-name search (Pro and above). |
from / to | string · date-time | date | Validation time range, ISO-8601 — full datetime or plain date (2026-06-12 expands to start/end of day UTC, inclusive). Business and above. |
valid | boolean | Filter by verdict (Business and above). |
format | string | Filter by detected format (Business and above). |
Response item
Returned as a standard Spring page: { content: [...], totalElements, totalPages, number, size }.
| Field | Type | Description |
|---|---|---|
id | string · uuid | Report id — use with GET /v1/reports/{id} for the full ValidationReport. |
filename | string | Original filename of the validated document. |
format | string | Detected document format (see FormatType enum). |
valid | boolean | Overall validation verdict. |
warningCode | string | null | Non-blocking finding, when present. |
signaturesCount | integer | Number of signatures found. |
hasQualifiedSignature | boolean | true if at least one signature is QES. |
createdAt | string · date-time | When the validation ran. |
/v1/reports/{id}The full ValidationReport — byte-for-byte the same object POST /v1/validate returns, documented in the schema section below. Unknown or foreign ids return 404 NOT_FOUND.
/v1/reports/exportCSV export (text/csv attachment, max 10,000 rows) of the filtered report list — same query parameters as the list endpoint. Available on Business and above.
# Paginated list (metadata only)curl "https://api.sealium.eu/v1/reports?page=0&size=20" \ -H "Authorization: Bearer slm_live_..." # Full ValidationReport by idcurl https://api.sealium.eu/v1/reports/3fa85f64-5717-4562-b3fc-2c963f66afa6 \ -H "Authorization: Bearer slm_live_..." # CSV export (Business+)curl -OJ "https://api.sealium.eu/v1/reports/export?valid=false" \ -H "Authorization: Bearer slm_live_..."The ValidationReport object
The full object graph returned by /v1/validate. Nested arrays — signatures, certChain, timestamps and krxDocuments — reference the object definitions below.
ValidationReportTop-level response.
| Field | Type | Description |
|---|---|---|
documentId | string · uuid | Unique id assigned to this validation run. |
filename | string | Original filename of the uploaded document. |
format | enum FormatType | Detected document format. See Enums. |
valid | boolean | true when every signature is TOTAL_PASSED and at least one exists. For KRX, true only if every sub-document is valid. |
documentIntact | boolean | true when every signature's cryptographic hash still matches the document. |
validatedAt | string · date-time | When validation ran (ISO-8601, UTC). |
signatures | SignatureInfo[] | One entry per electronic signature found in the document. |
signaturesCount | integer | Total number of signatures found. |
validSignaturesCount | integer | Number of signatures that passed (TOTAL_PASSED). |
validationSummary | ValidationSummary | Aggregated totals across all signatures. |
pdfMetadata | PdfMetadata | null | PDF document metadata. null for non-PDF formats. |
lotlSummary | LotlSummary | State of the EU List of Trusted Lists at validation time. |
errorCode | enum | null | Blocking error code. Always accompanied by valid=false. See Enums. |
errorMessage | string | null | Human-readable description of the blocking error. |
warningCode | enum | null | Non-blocking finding. valid may still be true. See Enums. |
warningMessage | string | null | Human-readable description of the warning, including the relevant dates. |
krxDocuments | KrxDocumentReport[] | null | Per-sub-document reports. Non-null only for KRX containers. |
SignatureInfo
| Field | Type | Description |
|---|---|---|
signatureId | string | Identifier of the signature within the document. |
signerDn | string | Full distinguished name of the signer's certificate. |
signerName | string | Common name (CN) extracted from the signer's certificate. |
signingTime | string · date-time | Backward-compatible alias of claimedSigningTime. |
claimedSigningTime | string · date-time | Signing time as claimed in the signature. |
bestSignatureTime | string · date-time | Proven signing time from a trusted timestamp. Falls back to the current time when no trusted timestamp exists — gate display on timestampValid. |
signatureIntact | boolean | Cryptographic integrity of this signature. |
certValid | boolean | Whether the signing certificate was valid. |
revocationOk | boolean | Whether revocation checking (OCSP/CRL) passed. |
timestampValid | boolean | Whether a trusted timestamp was found and is valid. |
indication | enum | DSS result: TOTAL_PASSED, INDETERMINATE or TOTAL_FAILED. See Enums. |
subIndication | string | null | DSS sub-indication when not TOTAL_PASSED (e.g. NO_CERTIFICATE_CHAIN_FOUND). |
signatureLevel | enum | eIDAS level: QES, AdESqc, AdES or unknown. See Enums. |
signatureFormat | string | ETSI baseline format, e.g. PAdES_BASELINE_LT. |
signaturePolicyId | string | null | Signature policy identifier, when present. |
commitmentTypeIndication | string | null | Commitment type, when present. |
signerLocation | string | null | Declared signer location, when present. |
certIssuerDn | string | Distinguished name of the certificate issuer. |
certNotBefore | string · date-time | Certificate validity start. |
certNotAfter | string · date-time | Certificate validity end. |
certExpiresInDays | integer · int64 | Days until the signing certificate expires. |
certExpiryWarning | boolean | true when the certificate is close to expiry. |
timestamps | TimestampInfo[] | Timestamp tokens embedded in the signature. |
certChain | CertInfo[] | Certificate chain from the signer up to a trust anchor. |
TimestampInfo
| Field | Type | Description |
|---|---|---|
type | string | Timestamp type, e.g. SIGNATURE_TIMESTAMP or ARCHIVE_TIMESTAMP. |
productionTime | string · date-time | When the timestamp token was produced. |
valid | boolean | Whether the timestamp token is valid. |
issuerDn | string | Distinguished name of the timestamp authority. |
CertInfo
| Field | Type | Description |
|---|---|---|
subjectDn | string | Subject distinguished name of this certificate. |
issuerDn | string | Issuer distinguished name. |
notBefore | string · date-time | Certificate validity start. |
notAfter | string · date-time | Certificate validity end. |
trusted | boolean | true when this certificate is a trust anchor on a recognised trusted list. |
ValidationSummary
| Field | Type | Description |
|---|---|---|
totalSignatures | integer | Total signatures examined. |
totalPassed | integer | Signatures with indication TOTAL_PASSED. |
totalIndeterminate | integer | Signatures with indication INDETERMINATE. |
totalFailed | integer | Signatures with indication TOTAL_FAILED. |
hasQualifiedSignature | boolean | true if at least one signature is QES. |
allQualified | boolean | true if every signature is QES. |
PdfMetadataPresent only when format is PDF.
| Field | Type | Description |
|---|---|---|
title | string | Document title from the PDF info dictionary. |
author | string | Document author. |
creator | string | Creating application. |
creationDate | string · date-time | PDF creation date. |
modificationDate | string · date-time | PDF last-modification date. |
encrypted | boolean | true if the PDF is encrypted. pageCount is then 0. |
pageCount | integer | Number of pages (0 when encrypted). |
LotlSummary
| Field | Type | Description |
|---|---|---|
loaded | boolean | Whether the EU LOTL was loaded for this validation. |
lastRefresh | string · date-time | null | Last successful LOTL refresh. null if never loaded. |
trustedListsCount | integer | Number of national trusted lists processed (~31). 0 only when loading failed. |
KrxDocumentReportOne per sub-document for KRX containers.
| Field | Type | Description |
|---|---|---|
documentIndex | integer | 1-based index of the sub-document inside the KRX container. |
filename | string | Filename of the enclosed document. |
format | string | Detected format of the sub-document. |
valid | boolean | Validity of this sub-document. |
documentIntact | boolean | Cryptographic integrity of this sub-document. |
signatures | SignatureInfo[] | Signatures found in this sub-document. |
warningCode | string | null | Per-document warning, e.g. NO_SIGNATURES or CERTIFICATE_CHAIN_INVALID. |
warningMessage | string | null | Human-readable per-document warning. |
Enums & codes
format — FormatType
| Value | Description |
|---|---|
PDF | PDF / PAdES signature. |
ASIC_E | ASiC-E container (CAdES or XAdES inside). |
ASIC_S | ASiC-S container. |
KRX | Hungarian KRX multi-document container. |
XADES | XAdES (XML) signature. |
CADES | CAdES (CMS/PKCS#7) signature. |
JADES | JAdES (JSON) signature. |
UNKNOWN | Format could not be detected. |
signatureLevel
| Value | Description |
|---|---|
QES | Qualified Electronic Signature — legal equivalent of a handwritten signature across the EU. |
AdESqc | Advanced signature backed by a qualified certificate. |
AdES | Advanced Electronic Signature. |
unknown | Cannot be determined (e.g. LOTL not loaded, or INDETERMINATE result). |
indication
| Value | Description |
|---|---|
TOTAL_PASSED | The signature is cryptographically valid and trusted. |
INDETERMINATE | Validity could not be fully established (e.g. missing revocation data or trust anchor). |
TOTAL_FAILED | The signature is invalid (e.g. hash mismatch). |
errorCode blocking
Parsing or integrity failures that stop validation. Always accompanied by valid: false.
| Value | Description |
|---|---|
NO_SIGNATURES | The document contains no electronic signature. |
PARSE_ERROR | The document could not be parsed by the engine. |
PREPROCESS_ERROR | A KRX container could not be unpacked. |
FORMAT_NOT_SUPPORTED | Unknown or unsupported format. |
HASH_FAILURE | Cryptographic integrity check failed. |
warningCode non-blocking
Certificate-quality findings. valid may still be true — for example, an LTA-timestamped signature with an expired certificate stays TOTAL_PASSED.
| Value | Description |
|---|---|
SIGNATURE_EXPIRED | The certificate expired. With a trusted timestamp the signature may still be valid at signing time. |
SIGNATURE_NOT_YET_VALID | The certificate was not yet valid at the claimed signing time. |
REVOKED | The certificate was revoked. If revocation came after signing, valid may still be true (INDETERMINATE). |
CERTIFICATE_CHAIN_INVALID | The certificate chain could not be built to a trusted root. |
PARTIAL_VALIDATION | KRX only: some sub-documents are valid and some are not. |
MULTIPLE_WARNINGS | KRX only: more than one sub-document carries a warning. |
warningMessage carries the human-readable detail with dates, e.g. “Certificate expired on 2021-07-12, but signature was valid at signing time (2019-09-22)”. When no trusted timestamp exists it instead notes that validity at signing time cannot be guaranteed.
Errors
Error responses use an ApiError body: { code, message, timestamp }.
| Status | Code | When |
|---|---|---|
| 400 | BAD_REQUEST | Missing or empty file field. |
| 401 | MISSING_API_KEY | No Authorization: Bearer slm_live_... header on /v1/validate. |
| 401 | INVALID_API_KEY | The API key does not exist or has been revoked. |
| 403 | FEATURE_NOT_AVAILABLE | Your tier does not include this feature (e.g. batch or CSV export below Business). |
| 404 | NOT_FOUND | Report or batch job not found, or it belongs to another account. |
| 413 | FILE_TOO_LARGE | File exceeds the 50 MB limit. |
| 429 | QUOTA_EXCEEDED | Monthly quota reached. Returns X-RateLimit-Remaining and X-RateLimit-Reset headers. |
| 502 | ENGINE_UNAVAILABLE | The validation engine could not be reached. |
| 503 | SERVICE_BUSY | Your tier's concurrency limit is in use — retry shortly. |
Ready to validate your first document?
100 free validations a month, every eIDAS format, no credit card.