Error Handling
Use this page when a Public API request fails before job acceptance, or when an accepted job reaches a terminal failure state.
Error Envelope
Public API errors use a structured JSON envelope:
{
"code": "ERROR_CODE",
"message": "Human-readable explanation."
}
Accepted jobs that later fail keep the job envelope and add a structured
error object:
{
"job_id": "<job_id>",
"status": "failed",
"created_at": "<timestamp>",
"completed_at": "<timestamp>",
"error": {
"code": "FAILED_ROW_THRESHOLD_EXCEEDED",
"message": "The export job exceeded max_failed_row_percent and was aborted.",
"details": {
"failure_class": "threshold_failed",
"input_row_count": 3,
"produced_row_count": 0,
"failed_row_count": 1,
"failed_row_percent": 33.3333,
"max_failed_row_percent": 0
}
}
}
Common Request Errors
| Code | Typical status | What to check |
|---|---|---|
BF_EXPORT_API_KEY_REQUIRED | 401 | Missing auth header or malformed Bearer format |
BF_EXPORT_API_KEY_INVALID | 401 | Wrong key or corrupted secret |
BF_EXPORT_API_KEY_REVOKED | 403 | Key was revoked |
BF_EXPORT_API_KEY_EXPIRED | 403 | Key expired |
BF_EXPORT_API_KEY_INACTIVE | 403 | Account is not currently eligible for API access |
RATE_LIMITED | 429 | Slow down and retry later |
REPEATED_FAILED_JOBS_COOLDOWN | 429 | New create requests are temporarily blocked after repeated failed jobs; honor Retry-After and retry_after_seconds |
HIGH_FAIL_RATIO_COOLDOWN | 429 | New create requests are temporarily blocked after recent failure-heavy usage; honor Retry-After and retry_after_seconds |
INVALID_IDEMPOTENCY_KEY | 400 | Missing or invalid Idempotency-Key on create |
IDEMPOTENCY_KEY_PAYLOAD_MISMATCH | 409 | Same Idempotency-Key was reused for a different effective create payload |
Create-only safeguard cooldowns apply to new POST /v1/bulkfill/export-jobs
requests only. They do not affect status polling, downloads, or webhook
delivery.
Idempotency note:
- front-door auth, security checks, and create-side rate limits run before replay lookup
- same
Idempotency-Key+ same body returns the same logicaljob_idonly after the retry is admitted past those protections X-Request-Idstays tracing-only and may be server-generated when omitted
Common Validation Errors
| Code | Typical status | What to check |
|---|---|---|
INVALID_FILE | 400 | Missing pdf upload |
LEGACY_OVERLAYS_NOT_SUPPORTED | 400 | Remove the legacy overlays field and upload doqlo_file instead |
INCLUDE_SIGNER_INFO_NOT_SUPPORTED | 400 | Remove the public-only unsupported include_signer_info field |
MISSING_DOQLO_FILE | 400 | Missing doqlo_file upload |
MISSING_MAX_FAILED_ROW_PERCENT | 400 | Missing required max_failed_row_percent field |
MALFORMED_DOQLO_FILE | 400 | .doqlo package could not be opened or decoded |
INVALID_MAX_FAILED_ROW_PERCENT | 400 | max_failed_row_percent is not an integer in 0..100 |
INVALID_DATA_INPUT | 400 | Provide exactly one of rows_json or csv_file |
INVALID_ROWS_JSON | 400 | Malformed rows_json JSON |
INVALID_CSV_FILE | 400 | CSV parsing failed |
EMPTY_DATA_INPUT | 400 | No rows were provided |
BATCH_TOO_MANY_ROWS | 422 | Too many rows in one batch |
INVALID_PDF | 422 | Uploaded file is not a valid PDF |
MAX_PDF_PAGES_EXCEEDED | 413 | PDF page count exceeds the current hard limit |
MAX_OVERLAYS_EXCEEDED | 413 | Overlay count exceeds the current hard limit |
FREE_FILE_SIZE_LIMIT_REACHED | 413 | Free-plan file size limit was exceeded |
PAID_FILE_SIZE_LIMIT_REACHED | 413 | Paid-plan file size limit was exceeded |
CLOUD_DELIVERY_MAX_FILE_SIZE_EXCEEDED | 413 | Output package would exceed current Cloud Delivery limits |
UNSUPPORTED_DOQLO_VERSION | 422 | .doqlo package version is unsupported |
INVALID_DOQLO_AUTHENTICITY | 422 | .doqlo package failed authenticity verification |
INVALID_DOQLO_SCHEMA | 422 | Decoded .doqlo payload schema is invalid for package structure or non-code overlays |
MISSING_DOQLO_TEMPLATE_CONFIG | 422 | .doqlo package is missing required Bulk Fill execution config |
BULKFILL_LIMIT_REACHED | 403 | Shared Bulk Fill quota is exhausted |
ACCOUNT_SUSPENDED | 403 | Account is suspended |
Download And Lookup Errors
| Code | Typical status | What to check |
|---|---|---|
INVALID_JOB_ID | 400 | job_id must be a UUID |
EXPORT_JOB_NOT_FOUND | 404 | Job is missing or not owned by the authenticated account |
DELIVERY_NOT_FOUND | 404 | No active downloadable delivery is currently available |
DELIVERY_TEMPORARILY_UNAVAILABLE | 500 | Retry the download later |
FAILED_ROW_THRESHOLD_EXCEEDED | 500 on response-mode create, failed job state afterward | Runtime failed-row threshold was exceeded and the job aborted without a deliverable artifact |
INTERNAL_ERROR | 500 | Unexpected server-side failure |
Webhook-Mode Validation Errors
| Code | Typical status | What to check |
|---|---|---|
INVALID_DELIVERY_MODE | 400 | delivery_mode must be response or webhook |
MISSING_WEBHOOK_URL | 400 | webhook_url is required for webhook mode |
MISSING_WEBHOOK_SECRET | 400 | webhook_secret is required for webhook mode |
INVALID_WEBHOOK_URL | 400 | URL is invalid, non-HTTPS, contains userinfo, or contains secret-bearing query params |
INVALID_WEBHOOK_TARGET | 400 | URL resolves to localhost, private, or otherwise blocked targets |
Failure Classes In Plain Language
- Package or request errors fail hard before the job can run. Examples include
invalid
.doqlo, missing inputs, malformed row data, and unreadable PDFs. - Static and CSV-mapped QR/barcode overlay issues in an uploaded
.doqloare different:- malformed static code settings are skipped at execution time and reported
in
manifest.jsoninstead of failing accepted jobs - blank or semantically invalid static code values are also skipped at execution time
- mapped QR/barcode overlays are allowed to carry blank template payloads in the package, then resolve from row data at execution time
- blank, missing, or semantically invalid mapped row values skip only that overlay and do not fail the row by themselves
- malformed static code settings are skipped at execution time and reported
in
- Completed jobs can still contain
partialorfailedrows. That is the normal best-effort model, not a contradiction. - Skipped overlays do not make a job fail by themselves. The failed-row threshold is based on failed rows only.
- Threshold-failed jobs are terminal failures. They expose no ZIP artifact and do not debit quota.
What To Check First
- Confirm the auth header and
Idempotency-Keyformat. - Confirm the request includes
pdf,doqlo_file, and exactly one data input:rows_jsonorcsv_file. - If the request fails on
.doqlo, re-export the package from the web Bulk Fill editor and verify the package itself is valid. Submitted-PDF differences are reported inmanifest.json, not as create-time validation failures. - Confirm the webhook target is public HTTPS if you are using webhook mode.
- If the job was accepted, read the job status again with
GET. - If the job completed, inspect
manifest.jsonfor row-levelpartialorfailedresults before treating the whole export as unusable. - If the job failed with
FAILED_ROW_THRESHOLD_EXCEEDED, inspecterror.detailsfor the failed-row counts and your declared threshold. - If the failure is delivery-related, check the webhook or download-specific troubleshooting pages.