API Reference
All DokJet v1 endpoints. Authentication: X-API-Key header on every request.
Generate a PDF from a DokJet template identified by template_id. Returns the PDF binary stream (sync) or a task_id (async).
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| template_id | string | required | Template identifier (e.g. invoices/invoice). See GET /v1/templates. |
| data | object | required | Template variables. Unknown keys are silently ignored. |
| options | object | optional | Rendering options. See options object below. |
| goDokMode | boolean | optional | Enable AI optimization (+1 Dok). With attached file: +2 Doks. Default: false. |
| async_mode | boolean | optional | false (default): returns PDF. true: returns a task_id (HTTP 202). |
| return_type | string | optional | binary (default) | url. Sync mode only. |
| webhook_url | string (uri) | optional | URL called via POST JSON when the job completes. Async mode only. |
| metadata | object | optional | Free key-value object returned in /v1/status and the webhook. |
options object
| Parameter | Type | Description |
|---|---|---|
| paper | string | A4 | A3 | A5 | Letter | Legal. Default: A4 |
| orientation | string | portrait | landscape. Default: portrait |
| scale | float | Zoom factor. Default: 1.0 |
| margin_top / bottom / left / right | float | Margins in inches. |
| header_html | string | HTML shown in header of every page (inline styles required). Free. |
| footer_html | string | HTML shown in footer of every page. Free. |
| omit_backgrounds | boolean | Disable CSS backgrounds. Free. |
| pdf_format | string | PDF/A-1a | PDF/A-1b | PDF/A-2b | PDF/A-3b. Free. |
| password | string | AES encryption. Free on paid plans. Blocked on Free plan (HTTP 403). |
| compress | boolean | qpdf compression. +1 Dok. |
| factur_x | boolean | Force PDF/A-3b and prepare Factur-X. +1 Dok. |
| embed_files | string[] | URLs of files to embed as invisible attachments. +1 Dok (flat fee). |
| attachments | string[] | PDF URLs to merge. +1 Dok per file. |
Code examples
curl -X POST https://dokjet.ptitlabo.xyz/v1/generate \ -H "X-API-Key: dk_live_••••••••••••" \ -H "Content-Type: application/json" \ -d '{ "template_id": "invoices/invoice", "data": { "client": "Acme Corp", "total": "€1 240" }, "options": { "paper": "A4", "compress": true }, "return_type": "url" }'
const res = await fetch('https://dokjet.ptitlabo.xyz/v1/generate', { method: 'POST', headers: { 'X-API-Key': 'dk_live_••••••••••••', 'Content-Type': 'application/json' }, body: JSON.stringify({ template_id: 'invoices/invoice', data: { client: 'Acme Corp', total: '€1 240' }, options: { paper: 'A4', compress: true }, return_type: 'url', }), }); const data = await res.json();
$ch = curl_init('https://dokjet.ptitlabo.xyz/v1/generate'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => ['X-API-Key: dk_live_••••••••••••', 'Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode([ 'template_id' => 'invoices/invoice', 'data' => ['client' => 'Acme Corp', 'total' => '€1 240'], 'options' => ['paper' => 'A4', 'compress' => true], 'return_type' => 'url', ]), ]); $data = json_decode(curl_exec($ch), true);
import requests data = requests.post( 'https://dokjet.ptitlabo.xyz/v1/generate', headers={'X-API-Key': 'dk_live_••••••••••••'}, json={ 'template_id': 'invoices/invoice', 'data': {'client': 'Acme Corp', 'total': '€1 240'}, 'options': {'paper': 'A4', 'compress': True}, 'return_type': 'url', } ).json()
Response
application/pdf — PDF binaryapplication/json — {url, credits_left, response_time_ms}{task_id, status, check_status_url}Convert raw HTML directly to PDF, without a DokJet template. Ideal for layouts you fully control client-side.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| html | string | required | Complete standalone HTML document (<html>, <head>, <body>). |
| css | string | optional | Additional CSS injected into <head>. |
| options | object | optional | Same options object as /v1/generate. |
| goDokMode | boolean | optional | true by default on this endpoint. Pass false for 1 Dok instead of 2. |
| async_mode | boolean | optional | Default: false (sync). |
| return_type | string | optional | binary | url. Sync mode. |
| webhook_url | string | optional | Async mode only. |
| metadata | object | optional | Free object returned in the webhook. |
curl -X POST https://dokjet.ptitlabo.xyz/v1/transform \ -H "X-API-Key: dk_live_••••••••••••" \ -H "Content-Type: application/json" \ -d '{ "html": "<html><body><h1>Hello World</h1></body></html>", "goDokMode": false, "return_type": "url" }'
const res = await fetch('https://dokjet.ptitlabo.xyz/v1/transform', { method: 'POST', headers: { 'X-API-Key': 'dk_live_••••••••••••', 'Content-Type': 'application/json' }, body: JSON.stringify({ html: '<html><body><h1>Hello World</h1></body></html>', goDokMode: false, return_type: 'url', }), });
$data = json_decode( file_get_contents('https://dokjet.ptitlabo.xyz/v1/transform', false, stream_context_create(['http' => [ 'method' => 'POST', 'header' => "X-API-Key: dk_live_••••••••••••\r\nContent-Type: application/json\r\n", 'content' => json_encode([ 'html' => '<html><body><h1>Hello</h1></body></html>', 'goDokMode' => false, 'return_type' => 'url', ]), ]]) ), true );
import requests data = requests.post( 'https://dokjet.ptitlabo.xyz/v1/transform', headers={'X-API-Key': 'dk_live_••••••••••••'}, json={ 'html': '<html><body><h1>Hello World</h1></body></html>', 'goDokMode': False, 'return_type': 'url', } ).json()
Generate a PDF from a pre-configured Studio endpoint identified by its slug. The endpoint configuration (template, options) applies automatically. data values override defaults.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
| slug | string | Studio endpoint slug. See GET /v1/endpoints. |
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| data | object | optional | Variables to inject. Override endpoint defaults. |
| options | object | optional | Override the endpoint rendering options. |
| goDokMode | boolean | optional | Override the endpoint goDokMode parameter. +1 Dok. |
| async_mode | boolean | optional | Default: false. |
| webhook_url / return_type / metadata | — | optional | Same as /v1/generate. |
curl -X POST https://dokjet.ptitlabo.xyz/v1/studio/mes-factures \ -H "X-API-Key: dk_live_••••••••••••" \ -H "Content-Type: application/json" \ -d '{ "data": { "client": "Acme Corp", "total": "€1 240" } }'
const res = await fetch('https://dokjet.ptitlabo.xyz/v1/studio/mes-factures', { method: 'POST', headers: { 'X-API-Key': 'dk_live_••••••••••••', 'Content-Type': 'application/json' }, body: JSON.stringify({ data: { client: 'Acme Corp', total: '€1 240' }}), });
$ch = curl_init('https://dokjet.ptitlabo.xyz/v1/studio/mes-factures'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => ['X-API-Key: dk_live_••••••••••••', 'Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode([ 'data' => ['client' => 'Acme Corp', 'total' => '€1 240'], ]), ]);
import requests data = requests.post( 'https://dokjet.ptitlabo.xyz/v1/studio/mes-factures', headers={'X-API-Key': 'dk_live_••••••••••••'}, json={'data': {'client': 'Acme Corp', 'total': '€1 240'}} ).json()
Submit multiple PDF jobs in a single request. Exclusively asynchronous.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| endpoint | string | required | generate | transform | {slug}. Endpoint type applied to all entries. |
| entries | array | required | Array of payloads. Each entry follows the corresponding endpoint schema. Max 3 (Free) / 10 (Pro+). |
| async_mode | boolean | optional | Must be true or omitted. Passing false → HTTP 400. |
| webhook_url | string | optional | Default webhook for all entries (overridable per entry). |
Webhook payload (per job)
{ "task_id": "job_a1b2c3d4e5f6g7h8", "status": "completed", "download_url": "https://dokjet.ptitlabo.xyz/upload/.../doc.pdf", "metadata": {} }
curl -X POST https://dokjet.ptitlabo.xyz/v1/batch \ -H "X-API-Key: dk_live_••••••••••••" \ -H "Content-Type: application/json" \ -d '{ "endpoint": "generate", "webhook_url": "https://your-app.com/webhooks/dokjet", "entries": [ { "template_id": "invoices/invoice", "data": { "client": "Acme" } }, { "template_id": "invoices/invoice", "data": { "client": "Beta Corp" } } ] }'
const res = await fetch('https://dokjet.ptitlabo.xyz/v1/batch', { method: 'POST', headers: { 'X-API-Key': 'dk_live_••••••••••••', 'Content-Type': 'application/json' }, body: JSON.stringify({ endpoint: 'generate', webhook_url: 'https://your-app.com/webhooks/dokjet', entries: [ { template_id: 'invoices/invoice', data: { client: 'Acme' }}, { template_id: 'invoices/invoice', data: { client: 'Beta Corp' }}, ], }), }); const { batch_id, tasks } = await res.json();
// Using Guzzle $response = $client->post('https://dokjet.ptitlabo.xyz/v1/batch', [ 'headers' => ['X-API-Key' => 'dk_live_••••••••••••'], 'json' => [ 'endpoint' => 'generate', 'webhook_url' => 'https://your-app.com/webhooks/dokjet', 'entries' => [ ['template_id' => 'invoices/invoice', 'data' => ['client' => 'Acme']], ['template_id' => 'invoices/invoice', 'data' => ['client' => 'Beta Corp']], ], ], ]);
import requests result = requests.post( 'https://dokjet.ptitlabo.xyz/v1/batch', headers={'X-API-Key': 'dk_live_••••••••••••'}, json={ 'endpoint': 'generate', 'webhook_url': 'https://your-app.com/webhooks/dokjet', 'entries': [ {'template_id': 'invoices/invoice', 'data': {'client': 'Acme'}}, {'template_id': 'invoices/invoice', 'data': {'client': 'Beta Corp'}}, ], } ).json()
Response
{batch_id, count, tasks[]}
Returns the state of a job created in async mode. Lifecycle: pending → processing → completed | failed.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
| task_id | string | task_id returned by a generation endpoint in async mode. |
curl https://dokjet.ptitlabo.xyz/v1/status/job_a1b2c3d4e5f6g7h8 \ -H "X-API-Key: dk_live_••••••••••••" → 200 OK { "task_id": "job_a1b2c3d4e5f6g7h8", "status": "completed", "download_url": "https://dokjet.ptitlabo.xyz/upload/.../doc.pdf" }
const poll = async (taskId) => { let status; do { await new Promise(r => setTimeout(r, 3000)); const res = await fetch(`https://dokjet.ptitlabo.xyz/v1/status/${taskId}`, { headers: { 'X-API-Key': 'dk_live_••••••••••••' }, }); ({ status } = await res.json()); } while (status === 'pending' || status === 'processing'); return status; };
$status = 'pending'; while (in_array($status, ['pending', 'processing'])) { sleep(3); $r = json_decode(file_get_contents( 'https://dokjet.ptitlabo.xyz/v1/status/' . $taskId, false, stream_context_create(['http' => [ 'header' => "X-API-Key: dk_live_••••••••••••\r\n" ]])), true); $status = $r['status']; }
import time, requests def poll(task_id): while True: time.sleep(3) r = requests.get( f'https://dokjet.ptitlabo.xyz/v1/status/{task_id}', headers={'X-API-Key': 'dk_live_••••••••••••'} ).json() if r['status'] not in ('pending', 'processing'): return r
Returns the full catalog of DokJet templates usable in POST /v1/generate via their template_id.
curl https://dokjet.ptitlabo.xyz/v1/templates \ -H "X-API-Key: dk_live_••••••••••••" → [{ "id": "invoices/invoice", "label": "Invoice", "category": "invoices", "orientation": "portrait" }, ...]
const templates = await fetch('https://dokjet.ptitlabo.xyz/v1/templates', { headers: { 'X-API-Key': 'dk_live_••••••••••••' }, }).then(r => r.json());
$templates = json_decode(file_get_contents( 'https://dokjet.ptitlabo.xyz/v1/templates', false, stream_context_create(['http' => [ 'header' => "X-API-Key: dk_live_••••••••••••\r\n" ]]) ), true);
templates = requests.get( 'https://dokjet.ptitlabo.xyz/v1/templates', headers={'X-API-Key': 'dk_live_••••••••••••'} ).json()
Returns all Studio endpoints in your workspace. Use their slug with POST /v1/studio/{slug}.
→ 200 OK [{ "name": "Mes factures", "slug": "mes-factures", "type": "template", "express": false, "variables": ["client", "total", "invoice_number"] }]
Returns the Dok balance for your account and the name of the active plan.
curl https://dokjet.ptitlabo.xyz/v1/credits \ -H "X-API-Key: dk_live_••••••••••••" → 200 OK { "credits_left": 42, "plan": "Free" }