Aller au contenu
FR
On this page

Errors

Every API error follows a single contract: a JSON object with at least an error key.

{ "error": "API key invalid or revoked." }

Exception: Laravel validation rejections (HTTP 422) answer {"message": …, "errors": {…}}, without an error key — see the Template required fields section.

HTTP codes

Code Meaning
400 Declared JSON body but undecodable (non-UTF-8 encoding, invalid JSON)
401 Missing key (Authorization: Bearer dfk_…) or invalid/revoked
403 Feature not included in the plan (see not_in_plan below)
404 Unknown template or folder — or outside the key's workspace (we never reveal the existence of a foreign resource)
409 Conflict: a request with the same Idempotency-Key is still running (idempotency_in_progress) or PDF unavailable on GET /documents/{id}/pdf (pdf_draft, pdf_failed, pdf_missing)
422 Invalid request (Laravel validation) or rejected business parameter
429 Plan API quota reached (api_calls_per_month), active-batch cap or document quota pre-flight
500 The PDF could not be generated (rare — retry or contact support)
503 Synchronous render pool saturated (pdf_busy) — retry after Retry-After or switch to async

Quotas: not_in_plan and quota_exceeded

Quota errors carry an extended payload:

{
  "error": "not_in_plan",
  "metric": "api_calls_per_month",
  "limit": null,
  "plan": "free",
  "message": "The feature \"API calls\" is not included in the FREE plan."
}
  • not_in_plan (HTTP 403): the feature does not exist in the plan — upgrade.
  • quota_exceeded (HTTP 429): the monthly limit is reached — it resets on the next period.

The message key is localised (fr/en) and can be shown as-is to the end user.

Template required fields (422)

Variables and tracking dimensions marked required in the template's schema are enforced at document creation — on single POSTs as well as batches. A missing field answers 422 in the Laravel validation format, without an error key:

{
  "message": "Le champ « Nom » est obligatoire.",
  "errors": {
    "nom": ["Le champ « Nom » est obligatoire."]
  }
}
  • The errors keys are the schema's variable keys (GET /templates/{public_id}/schema); for a required tracking dimension, the key is prefixed with tracking. (tracking.status). A required reference-type variable needs a record that resolves — message « La fiche « … » est obligatoire. ». Messages are worded in French.
  • A value counts as soon as it is resolved non-empty: a folder/workspace cascade, a schema default, a formula or the document's dedicated date satisfy the requirement — providing data is only necessary for what is not pre-filled.
  • With multiple errors, errors lists them all and message carries the first one.
  • The check runs before quota and any write: a 422 reserves no number, creates no document and consumes nothing.

Saturated synchronous render: pdf_busy (503)

Document creations without async render the PDF during the request, and every synchronous render holds a slot from a bounded pool. When the pool is saturated, the call is rejected before anything is created:

{
  "error": "pdf_busy",
  "message": "Le serveur est à pleine capacité de rendu synchrone. Réessayez dans quelques secondes ou utilisez async=true : la réponse part immédiatement et le PDF est rendu par la file (webhook document.pdf_ready si un endpoint est déclaré)."
}

The response carries the Retry-After: 5 header. Retry after 5 seconds, or switch to async=true: the async mode takes no render slot and answers 201 immediately (the PDF follows through the queue — document.pdf_ready webhook or GET /documents/{id} polling).

Best practices

  • Treat 404 and 403 the same way in your integration: do not distinguish "missing resource" from "another workspace's resource".
  • On 429, back off: retrying immediately makes the counter worse.
  • On 400, log the sent body: it is almost always an encoding problem on the client side.

Batch generation: specific errors

The batch endpoints add two payloads to the quota_exceeded contract (HTTP 429):

{
  "error": "batch_limit_reached",
  "limit": 2,
  "message": "You already have 2 batches running. Wait for one to finish or fetch one before creating a new one."
}
{
  "error": "quota_exceeded",
  "metric": "documents_per_month",
  "limit": 2000,
  "remaining": 1,
  "required": 3,
  "message": "Insufficient document quota: 1 remaining this month for 3 requested document(s)."
}
  • batch_limit_reached: too many active batches (pending/processing) in the workspace — wait for a batch to finish (GET /batches/{id}) before creating a new one.
  • quota_exceeded + remaining/required: the quota pre-flight rejected the whole batch rather than emitting part of it — shrink the batch or wait for the next period.

Finally, GET /documents/{public_id}/pdf returns 202 pdf_pending (render in progress, honours Retry-After), 409 (pdf_draft, pdf_failed, pdf_missing) and 410 (pdf_expired) — see the reference.