Documents API
Generate and download trade documents.
Generate Documents
Starts document generation for one or more document types. Returns job IDs for polling.
POST /api/v1/shipments/:id/generate
Request Body
{
"document_types": ["COMMERCIAL_INVOICE", "PACKING_LIST"]
}
Available Document Types
| Type | Description |
|---|---|
COMMERCIAL_INVOICE | Commercial invoice |
PACKING_LIST | Packing list |
BILL_OF_LADING | Bill of lading |
CERTIFICATE_OF_ORIGIN | Certificate of origin |
PROFORMA_INVOICE | Proforma invoice |
DANGEROUS_GOODS | Dangerous goods declaration |
AIR_WAYBILL | Air waybill |
Response
{
"jobs": [
{
"job_id": "job_doc_a1b2c3d4",
"document_type": "COMMERCIAL_INVOICE",
"status": "processing"
},
{
"job_id": "job_doc_e5f6g7h8",
"document_type": "PACKING_LIST",
"status": "processing"
}
]
}
Get Document Job
GET /api/v1/documents/:jobId
Response (Completed)
{
"job_id": "job_doc_a1b2c3d4",
"document_type": "COMMERCIAL_INVOICE",
"status": "completed",
"download_url": "https://...",
"hash": "sha256:a1b2c3d4e5f6...",
"verification_url": "https://klervex.com/verify/a1b2c3d4e5f6",
"completed_at": "2026-03-31T10:00:05Z"
}
Download Document
GET /api/v1/documents/:jobId/download
Returns the PDF file with Content-Type: application/pdf.
Polling Strategy
Poll every 2 seconds per document job:
async function waitForDocument(jobId) {
for (let i = 0; i < 30; i++) {
const res = await fetch(`/api/v1/documents/${jobId}`, {
headers: { Authorization: `Bearer ${apiKey}` }
});
const job = await res.json();
if (job.status === 'completed') return job;
if (job.status === 'failed') throw new Error(job.error.message);
await new Promise(r => setTimeout(r, 2000));
}
throw new Error('Generation timed out');
}