Classification
This document describes how to use the DIMARC API to classify a document into page ranges according to business categories. The API does not split the file and does not emit any binary: the deliverable is a JSON indicating where each category starts and ends.
Prerequisites
Section titled “Prerequisites”- An active DIMARC account.
- Administrator status in your organization.
- Your authentication token
x-api-key(see Retrieving Your Authentication Token)
Endpoints
Section titled “Endpoints”POST /v2/classificationPOST /v2/classification/asyncUse case: Sorting a batch of scanned pages mixing several document types (e.g. invoices, delivery notes, contracts) without manually splitting them beforehand.
Processing Modes
Section titled “Processing Modes”- Synchronous: The request is processed immediately and the response is returned in the same HTTP connection.
- Asynchronous: The processing is queued and the results are sent to a defined webhook once the classification is completed.
Synchronous Classification
Section titled “Synchronous Classification”Request
Section titled “Request”curl --location 'https://api.dimarc.ai/v2/classification' \--header 'Content-Type: application/json' \--header 'x-api-key: <your_api_key>' \--data '{ "filename": "document-batch.pdf", "file": "<base64_encoded_file>", "classes": [ { "name": "invoice", "description": "Invoice issued by a supplier" }, { "name": "delivery_note", "description": "Delivery note accompanying an order" } ]}'Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
filename |
string | Original filename (with extension) |
file |
string | File content encoded in base64 |
classes |
array | Categories to detect (see Classes Structure) — can be empty only if options.guess is true |
options |
object | Optional options (see Options) |
Classes Structure
Section titled “Classes Structure”Each element in the classes array is an object with the following properties:
| Property | Type | Description |
|---|---|---|
name |
string | Category name |
description |
string | Category description (helps the AI tell documents apart) |
Options
Section titled “Options”| Property | Type | Description |
|---|---|---|
guess |
boolean | Guess the categories instead of relying on classes — the only case where classes can be empty. Proposed categories are returned in discovered_classes |
per_page |
boolean | Classify page by page instead of by document range (reflected in the response’s data.mode) |
system |
string | Additional system instruction passed to the classification model |
Synchronous Response Format
Section titled “Synchronous Response Format”{ "status": "success", "data": { "source_name": "document-batch.pdf", "mode": "document", "segments": [ { "start": 1, "end": 3, "label": "invoice", "title": "Invoice #2024-001", "confidence": 0.92 }, { "start": 4, "end": 5, "label": "delivery_note", "title": "Delivery note", "confidence": 0.87 } ], "discovered_classes": [], "pages_count": 5 }, "metadata": { "filename": "document-batch.pdf", "duration": 4.12, "tokens_consumed": 1, "thread_id": "01J..." }}On error
Section titled “On error”{ "status": "error", "code": "classification_failed", "error": "Classification failed", "detail": { }}code is a stable machine identifier — error remains a human-readable message that can change without notice. detail is optional and absent most of the time. See the error codes table for the full set of possible codes.
Error Codes
Section titled “Error Codes”| Status | Code | Case |
|---|---|---|
| 422 | invalid_request |
Invalid request body, or classes empty without options.guess |
| 429 | spending_limit_reached |
Organization spending limit reached |
| 429 | concurrent_limit_exceeded |
More than 4 concurrent jobs for the organization, synchronous and asynchronous alike; Retry-After carries the seconds to wait before retrying |
| 429 | queue_saturated |
The processing engine is saturated; Retry-After carries the seconds to wait before retrying |
| 413 | file_too_large |
File larger than 36 MB; detail carries limit and size in bytes |
| 422 | infected_file |
File flagged by the antivirus |
| 503 | antivirus_unavailable |
Antivirus service unavailable |
| 503 | agent_unavailable |
Processing queue unavailable |
| 502 | classification_failed |
The agent could not process the classification |
| 504 | agent_timeout |
Processing deadline exceeded (120 s synchronous, 5 min asynchronous) |
Asynchronous Classification
Section titled “Asynchronous Classification”Asynchronous mode raises the processing deadline to 5 min (120 s in synchronous mode): use it from a few dozen pages upward.
Request
Section titled “Request”curl --location 'https://api.dimarc.ai/v2/classification/async' \--header 'Content-Type: application/json' \--header 'x-api-key: <your_api_key>' \--data '{ "filename": "document-batch.pdf", "file": "<base64_encoded_file>", "classes": [ { "name": "invoice", "description": "Invoice issued by a supplier" } ], "callback": "https://your-callback-endpoint.com/webhook"}'Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
filename |
string | Original filename (with extension) |
file |
string | File content encoded in base64 |
classes |
array | Categories to detect — same rules as synchronous |
options |
object | Optional options (see Options) |
callback |
string | URL of the webhook that will receive the result |
Immediate Response
Section titled “Immediate Response”{ "status": "started", "classification_id": "01K74Z3Q8RVN5XW2B6JHMTGD9C"}Fetching a result
Section titled “Fetching a result”The classification_id identifies the job. If you have not received the callback yet, or if your endpoint was unavailable, fetch the result with this identifier:
curl --location 'https://api.dimarc.ai/v2/turns/01K74Z3Q8RVN5XW2B6JHMTGD9C' \--header 'x-api-key: <your_api_key>'| Status | Body |
|---|---|
| 200 | The final event, identical to the one sent to the callback (status: "success" or "error"); for a successful synchronous job, its response body |
| 422, 502, 504 | Failed synchronous job: the status code and error body of its original response |
| 202 | { "status": "running", "turn_id": "…" } — processing has not finished, or its result is still being delivered; retry in a few seconds |
| 404 | turn_not_found — unknown or expired identifier, or one that belongs to another organization |
The result stays available for at least 7 days.
Result (Callback and Webhook)
Section titled “Result (Callback and Webhook)”When the classification is complete, the result is sent to the callback URL.
The callback is called with a POST carrying the same JSON body as the event. If your organization has configured a webhook for this event, the request carries the x-dimarc-signature: sha256=… header, to be verified with that webhook’s secret; with no webhook configured, it is unsigned. Each attempt waits 10 s at most; on 429, 5xx or a network error, delivery is retried after 1 s, 10 s, then 60 s. A delivery can arrive twice, so deduplicate on your side.
The same result is also available via the classification.completed event if you have configured an organization webhook — useful for centralizing delivery without depending on the per-request callback.
On success
Section titled “On success”{ "status": "success", "classification_id": "01K74Z3Q8RVN5XW2B6JHMTGD9C", "data": { "source_name": "document-batch.pdf", "mode": "document", "segments": [ { "start": 1, "end": 3, "label": "invoice", "title": "Invoice #2024-001", "confidence": 0.92 } ], "discovered_classes": [], "pages_count": 3 }, "metadata": { "filename": "document-batch.pdf", "duration": 4.12, "tokens_consumed": 1, "thread_id": "01J..." }}On error
Section titled “On error”{ "status": "error", "classification_id": "01K74Z3Q8RVN5XW2B6JHMTGD9C", "code": "agent_timeout", "error": "Agent response timed out", "detail": { "http_status": 504 }}detail is an object — http_status is a number. code carries the real machine code for the error (see the error codes table).
Limitations and Considerations
Section titled “Limitations and Considerations”- Supported format: PDF only
- Maximum file size: 36 MB (
413 file_too_largebeyond that, before any processing, in synchronous and asynchronous mode alike) - Processing deadline: 120 s synchronous, 5 min asynchronous. Beyond that,
504 agent_timeout(or astatus: "error"event in asynchronous mode); the document must then be resent. In asynchronous mode, a job interrupted by an outage is replayed once while its deadline runs - Large documents: beyond 5 min of processing (several hundred pages), split the PDF into batches of 30 to 50 pages, one asynchronous call per batch, then reassemble the segments by shifting
startandendby the batch offset - Classes: no limit on their number; keep descriptions short, they are injected into every model call.
options.systemis capped at 4000 characters - Concurrency: at most 4 jobs per organization, synchronous and asynchronous alike — an asynchronous call holds its place until processing actually ends, not until the HTTP response, and releases it as soon as the result is stored, without waiting for
callbackretries. Beyond that,429 concurrent_limit_exceededwithRetry-After; nothing is queued, retry once a job completes. If the engine is saturated,429 queue_saturatedwithRetry-After: retry after that delay - Rate: 100 requests per minute per key,
Retry-Afteron 429
Support and assistance
Section titled “Support and assistance”For any questions regarding the Classification API, contact our support team at contact@dimarc.fr