Aller au contenu
FR
On this page

API reference

Base: https://dokkraft.blocsland.com/api/v1 — authentication Authorization: Bearer dfk_… on every endpoint. Responses are JSON (Content-Type: application/json), except streamed PDFs.

Identifiers used in URLs are the public_id (template, folder), not internal ids.

Creation idempotency

The four creation POSTs (single documents and batches) accept an Idempotency-Key header — a unique value per intent, e.g. a UUID generated on your side. If a network timeout makes you replay the POST with the same key and the same payload, you receive the first call's response (Idempotent-Replayed: true) instead of a numbered duplicate — the memory lasts 24 h. With download=true, the replay re-serves the PDF of the document created by the first call.

Response Meaning
First call's response + Idempotent-Replayed: true Identical intents — no duplicate created
422 idempotency_key_reused Same key with a different payload — a key carries a single intent, generate a new one
409 idempotency_in_progress A call with this key is still running — retry in a moment

POST /templates/{public_id}/pdf

Generates a PDF without saving anything: the template body is rendered with the passed variables.

Parameter Type Description
data object Variable values ({"client.name": "ACME"})
references object Linked records by id ({"client": "42"}) — resolved as in document mode
tableData array Table rows
download boolean true → attachment, otherwise inline stream

Response: PDF (application/pdf).

POST /templates/{public_id}/documents

Creates a numbered, archived document ("Unfiled" root, or the folder argument), with its PDF.

Parameter Type Description
name string Document name (default Document API)
date string Issue date (Y-m-d)
folder string Archiving folder public_id
data, references, tableData object / array Variables, registries, table rows
download boolean Return the PDF instead of JSON
async boolean true → the PDF goes to the queue: the 201 responds as soon as the number is reserved (pdfStatus: "queued"), poll GET /documents/{id} then fetch the PDF — or declare a webhook to be notified instead. Without async, rendering is synchronous (~2 s median, the request waits for the PDF)

201 response: the document record (integrator contract, id = public_id — chainable with GET /documents/{id}/pdf).

{
  "id": "01HXXXX-public-id",
  "name": "ACME invoice",
  "numero": "INV-2026-0042",
  "status": "emis",
  "templateId": "tmpl_01HYYYY",
  "folderId": null,
  "date": "2026-09-22",
  "amount": 1250.0,
  "pdfStatus": "ready",
  "pdfUrl": "/api/v1/documents/01HXXXX-public-id/pdf",
  "emittedAt": "2026-09-22T10:15:00+00:00"
}

Idempotency: an Idempotency-Key header is accepted — see the dedicated section at the top of this page.

Errors: 422 async combined with download (incompatible — one responds without the PDF, the other waits for synchronous rendering), 422 missing required fields ({message, errors} format — see Errors), 503 pdf_busy when the synchronous render pool is saturated (Retry-After: 5 header — retry or switch to async=true, which takes no slot).

Template required fields: variables and tracking dimensions marked required in the schema must resolve to a non-empty value, otherwise 422 — but a folder/workspace cascade, a schema default, a formula or the dedicated date satisfy the requirement: data is only necessary for what is not pre-filled (error keys detailed in Errors). This rule applies to single POSTs and to every batch item.

POST /folders/{public_id}/documents

Same as the previous endpoint, but the folder is the entry point: its template (linked locally or inherited from an ancestor), its registry cascade and variables apply automatically.

Parameter Type Description
name, date string As above
data, references, tableData object / array Cascade overrides
download boolean Return the PDF instead of JSON
async boolean As above

Errors: 404 unknown folder (or outside the key's workspace), 422 no linked template or async combined with download, 422 missing required fields and 503 pdf_busy — same contracts as the previous endpoint (the folder's cascade can on its own satisfy the required fields).

POST /templates/{public_id}/documents/batch

Batch generation (asynchronous). Creates several documents at once and immediately replies 202: documents are emitted outside the request, their PDFs rendered on the queue. Track progress with GET /batches/{batch_id} — this is the way to go as soon as you need more than a handful of documents.

Parameter Type Description
items array (1–50) One object per document: name, date, folder, data, references, tableData — the same fields as the single endpoint
folder string Default archiving folder public_id (each item may override it)

Response 202: the batch resource.

{
  "id": "4e7c9a52-…",
  "status": "pending",
  "total": 2,
  "counts": { "queued": 2, "emitted": 0, "failed": 0 },
  "items": [
    { "position": 0, "status": "queued", "document": null }
  ]
}

Limits: 50 items per batch, 2 active batches (pending/processing) per workspace, 10 batches/minute. The monthly documents quota is consumed per actually emitted document — the fast-fail 429 quota_exceeded carries remaining and required when fewer documents remain than items requested.

Errors: 422 validation (malformed items, unknown folder), 429 batch_limit_reached (too many active batches) or quota_exceeded (document quota pre-flight).

POST /folders/{public_id}/documents/batch

Same as above, but the folder is the entry point: its template (linked locally or inherited from an ancestor) and cascade apply to every item.

GET /batches/{batch_id}

Batch status (integrator polling). Each call counts against the api_calls quota — polling every 2-3 s is plenty. An active batch with no update for 15 min (lost server-side job) is picked up automatically: just keep polling. The batch.completed webhook removes the need to poll — see Webhooks.

Response 200: the full batch resource. status goes pending → processing → completed (all emitted), partial (at least one failure) or failed. Each item carries its document (number, pdfStatus, pdfUrl) as soon as it is emitted; a failed item never blocks the others — its error explains why.

GET /documents/{public_id}

A single document created via the API — the same format as the single POST response (id, numero, pdfStatus, pdfUrl, …). 404 when the document belongs to another workspace.

GET /documents/{public_id}/pdf

The document's PDF, streamed (?download=true for an attachment). Companion to batch mode: the file only exists after the queued render.

Response Meaning
200 The PDF (application/pdf stream)
202 + Retry-After: 5 Render in progress — poll again (or receive a webhook as soon as it is ready)
409 pdf_draft / pdf_failed / pdf_missing Draft (no PDF), failed render or missing file
410 pdf_expired PDF purged by the plan's retention (regenerate from the app)

POST /embed/sessions

Creates a studio-in-iframe session: exchanges the API key for a signed URL to load into your product.

Parameter Type Description
template_id string public_id of the template to edit
allowed_domains array Allowed origins (1 to 10) — https://app.example.com
ttl_minutes integer Lifetime (5 to 1440, default 120)
permissions object variables (frozen|editable), ai, save, export_pdf

201 response: { "url", "token", "expires_at", "permissions" }.

DELETE /embed/sessions/{token}

Revokes an embed session: the iframe stops working immediately (leaked key, end of contract…). Answers 200 {"revoked": true} even for an unknown or already-revoked token — same answer in every case, no enumeration possible.

GET /templates/{public_id}/schema

No authentication. Variable schema of the template (generation fields, referenced registries) — handy to build a dynamic form on the integrator side.