Skip to main content

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

StatusMeaningWhat you should do
queuedThe job was accepted but has not started processing yetKeep the job_id and poll or wait for a webhook
processingThe job is currently being generatedKeep polling or wait for a webhook
completedThe export artifact is readyRead result.download_url and download the ZIP
failedThe job ended without a usable resultRead 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_percent during 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

  1. Submit POST /v1/bulkfill/export-jobs.
  2. Record the returned job_id.
  3. If the create response is already completed, download immediately.
  4. If the create response is queued or processing, poll GET /v1/bulkfill/export-jobs/{job_id} or wait for a webhook.
  5. 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 logical job_id
  • same Idempotency-Key + different effective body returns 409 IDEMPOTENCY_KEY_PAYLOAD_MISMATCH
  • same Idempotency-Key after 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 optional and used only for request tracing and support correlation, not idempotency. If you omit it, Doqlo generates one and returns it in the response header.

Typical Failure Flow

  1. Submit the create request.
  2. Record the job_id.
  3. Poll or wait for the webhook.
  4. If the job becomes failed, inspect the structured error payload.
  5. 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.

  • response mode returns the result payload inline when the job settles inside the sync wait window.
  • webhook mode omits result from the create response and sends terminal completion or failure to your webhook target.

In both modes:

  • GET /v1/bulkfill/export-jobs/{job_id} stays available
  • GET /v1/bulkfill/export-jobs/{job_id}/download is only valid after completed
  • delivery_mode does not change billing or quota semantics
  • GET and 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 success or partial row
  • manifest.json version 2

manifest.json reports:

  • top-level diagnostics when .doqlo source metadata differs from the submitted PDF
  • summary.produced_rows, success_rows, partial_rows, and failed_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. If you need the basic role of the .doqlo file in this workflow, read What a .doqlo project file is.

Row status rules:

  • success: row PDF produced and no overlays were skipped
  • partial: row PDF produced and at least one overlay was skipped, or zero overlays were applied
  • failed: 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_id values across repeated HTTP retries.
  • A completed job can remain completed even after the active delivery is no longer available. In that case, result.download_url becomes null.
  • Failed jobs stay readable through GET so you can inspect the terminal error state.
  • A completed job can still include partial or failed rows. Use manifest.json to inspect what happened before deciding whether the archive is acceptable for your workflow.
  • Threshold-failed jobs may include error.details with input_row_count, produced_row_count, failed_row_count, failed_row_percent, and max_failed_row_percent.
  • Produced rows and billed rows are different concepts. Completed jobs remain billed by requested rows, while manifest.summary.produced_rows reports the row PDFs that were actually written.