Job Lifecycle
Use this page when you need to understand how an accepted export request moves from creation to a terminal result.
What A Job Represents
The Public API is job-based because Bulk Fill exports do not always settle
inside one request window. Once Doqlo accepts a request, the accepted work is
represented by one job_id that you can poll or track by webhook.
Current Job States
| Status | Meaning | What you should do |
|---|---|---|
queued | The job was accepted but has not started processing yet | Keep the job_id and poll or wait for a webhook |
processing | The job is currently being generated | Keep polling or wait for a webhook |
completed | The export artifact is ready | Read result.download_url and download the ZIP |
failed | The job ended without a usable result | Read error.code and error.message, then retry or investigate |
completed means the ZIP artifact exists. It does not require every requested
row to have produced a PDF.
Threshold note:
- Doqlo evaluates
max_failed_row_percentduring runtime, not after the whole batch finishes. - Threshold accounting uses failed rows only.
- When failed rows exceed the declared threshold, the job aborts immediately,
stays
failed, exposes no result artifact, and does not debit quota.
Typical Success Flow
- Submit
POST /v1/bulkfill/export-jobs. - Record the returned
job_id. - If the create response is already
completed, download immediately. - If the create response is
queuedorprocessing, pollGET /v1/bulkfill/export-jobs/{job_id}or wait for a webhook. - When the job becomes
completed, redeem/v1/bulkfill/export-jobs/{job_id}/download.
Create Idempotency
Idempotency-Key identifies one logical create request within a fixed 24-hour
window.
- same
Idempotency-Key+ same effective body returns the current/latest state of the same logicaljob_id - same
Idempotency-Key+ different effective body returns409 IDEMPOTENCY_KEY_PAYLOAD_MISMATCH - same
Idempotency-Keyafter 24 hours is treated as a new request
Front-door auth, security checks, and create-side rate limiting run before
that replay lookup. A retry can still return 429 before Doqlo reaches the
idempotency layer.
X-Request-Id is separate tracing only. If you omit it, Doqlo generates one
and returns it in the response header.
Typical Failure Flow
- Submit the create request.
- Record the
job_id. - Poll or wait for the webhook.
- If the job becomes
failed, inspect the structured error payload. - Fix the request or operational issue, then submit a new request with a new
Idempotency-Key.
Response Mode Versus Webhook Mode
delivery_mode changes how you learn about terminal results. It does not
change the job states.
responsemode returns theresultpayload inline when the job settles inside the sync wait window.webhookmode omitsresultfrom the create response and sends terminal completion or failure to your webhook target.
In both modes:
GET /v1/bulkfill/export-jobs/{job_id}stays availableGET /v1/bulkfill/export-jobs/{job_id}/downloadis only valid aftercompleteddelivery_modedoes not change billing or quota semanticsGETand download redemption do not emit new terminal webhook events- polling and download redemption do not create a new generation charge
What The ZIP Contains
Completed jobs download a ZIP artifact with:
- one produced row PDF for each
successorpartialrow manifest.jsonversion2
manifest.json reports:
- top-level diagnostics when
.doqlosource metadata differs from the submitted PDF summary.produced_rows,success_rows,partial_rows, andfailed_rows- one
row_results[]entry per requested row
Read Reuse .doqlo Project Files Across PDFs for the product rationale and practical examples behind this changed-PDF behavior.
Row status rules:
success: row PDF produced and no overlays were skippedpartial: row PDF produced and at least one overlay was skipped, or zero overlays were appliedfailed: no row PDF was produced
Common partial cases include QR/barcode overlays that were skipped because a
static value was invalid or because a mapped row value was blank, missing, or
invalid for the selected code format.
Important Notes
- A later request can complete immediately from a same-account reuse hit. You
still get a new
job_id. - A same-key replay does not create a new
job_id; it returns the latest state of the original logical job. - The same logical job can still have different tracing
request_idvalues across repeated HTTP retries. - A completed job can remain
completedeven after the active delivery is no longer available. In that case,result.download_urlbecomesnull. - Failed jobs stay readable through
GETso you can inspect the terminal error state. - A completed job can still include
partialorfailedrows. Usemanifest.jsonto inspect what happened before deciding whether the archive is acceptable for your workflow. - Threshold-failed jobs may include
error.detailswithinput_row_count,produced_row_count,failed_row_count,failed_row_percent, andmax_failed_row_percent. - Produced rows and billed rows are different concepts. Completed jobs remain
billed by requested rows, while
manifest.summary.produced_rowsreports the row PDFs that were actually written.
Read Next
- Manifest And Diagnostics for row-level transparency
- Idempotency for the full replay and tracing contract
- Webhooks for terminal event delivery
- Error Handling for failure diagnosis
- Billing And Quota for requested versus produced versus billed rows
- API Reference for field-level details