Jobs #
GET /job/{id} for status and result. GET /job/{id}/webhook-logs for delivery diagnostics.
A job is one extraction attempt against an artifact. Every POST /extract, every POST /batch file, and every POST /artifacts/{id}/rerun
creates a new job.
GET /job/{job_id}
GET /job/{job_id}Returns the live status of a job, plus the result (inline + download URL) when complete.
| Method | Path | Auth | Returns |
|---|---|---|---|
GET | /api/v1/job/{job_id} | HTTP Basic | 200 OK + JobStatusResponse |
curl -u "$DD_KEY:$DD_SECRET" \ https://api.datadistillers.com/api/v1/job/job_8f3c2e1a
Response, while processing:
{
"job_id": "job_8f3c2e1a",
"status": "running",
"created_at": "2026-05-03T09:12:04Z"
}
Response, on success:
{
"job_id": "job_8f3c2e1a",
"status": "success",
"created_at": "2026-05-03T09:12:04Z",
"completed_at": "2026-05-03T09:12:11Z",
"result_download_url": "https://s3.amazonaws.com/…/result.json?X-Amz-…",
"result": {
"invoice_number": "INV-2026-001",
"total": { "value": 1240.00, "currency": "USD" }
}
}
Response, on failure:
{
"job_id": "job_8f3c2e1a",
"status": "failed",
"created_at": "2026-05-03T09:12:04Z",
"completed_at": "2026-05-03T09:12:08Z",
"error": "schema_mismatch: required field 'total' not found"
}
Status values
status | Terminal? | result populated? | error populated? |
|---|---|---|---|
pending | no | no | no |
queued_for_processing | no | no | no |
running | no | no | no |
success | yes | yes | no |
failed | yes | no | yes |
cancelled | yes | no | no |
expired | yes | no | yes |
queued_for_processing is the state the job sits in between
POST /artifacts/{id}/confirm-upload and the worker picking it up.
Stop polling on any terminal status. The job will never transition out of it.
For high-frequency polling without paying for the full result payload, use
GET /artifacts/{id}/status; it returns just
status, processed_at, and error.
GET /job/{job_id}/webhook-logs
GET /job/{job_id}/webhook-logsAll webhook delivery attempts for one job, in attempt order. The first stop when debugging "the job succeeded but my server never got the callback."
| Method | Path | Auth | Returns |
|---|---|---|---|
GET | /api/v1/job/{job_id}/webhook-logs | HTTP Basic | 200 OK + array of delivery log entries |
Query parameters:
| Param | Type | Default | Notes |
|---|---|---|---|
limit | integer | 20 | 1–100 |
offset | integer | 0 | Standard offset pagination |
curl -u "$DD_KEY:$DD_SECRET" \ 'https://api.datadistillers.com/api/v1/job/job_8f3c2e1a/webhook-logs?limit=20'
Each entry shows:
{
"attempt_number": 1,
"event_type": "extraction.completed",
"url": "https://api.example.com/dd-webhook",
"request_headers": { "X-Webhook-Id": "job_8f3c2e1a:extraction.completed", "...": "..." },
"response_status_code": 503,
"response_body": "Service Unavailable",
"is_success": false,
"duration_ms": 412,
"attempted_at": "2026-05-03T09:12:11Z"
}
Look for:
is_success: falsewith a 4xx: your handler rejected the call. Check signature verification logic.is_success: falsewith a 5xx: your handler crashed. Check logs.is_success: falsewithresponse_status_code: 0: connection error or DNS failure. Check the URL is reachable.duration_msclose to the timeout: handler too slow. Push work into a queue and ack quickly.
For aggregate stats (success rate, latency over a window), use
GET /webhooks/{id}/stats.
GET /usage
GET /usageAggregated job/spend summary over a rolling window.
| Method | Path | Auth | Returns |
|---|---|---|---|
GET | /api/v1/usage | HTTP Basic | 200 OK + UsageSummaryResponse |
Query parameters:
| Param | Type | Default | Notes |
|---|---|---|---|
period | enum | 30d | 7d, 30d, or 90d. |
curl -u "$DD_KEY:$DD_SECRET" \ 'https://api.datadistillers.com/api/v1/usage?period=30d'
Response:
{
"period": "30d",
"period_start": "2026-04-03T00:00:00Z",
"period_end": "2026-05-03T00:00:00Z",
"total_jobs": 2841,
"successful_jobs": 2779,
"failed_jobs": 62,
"total_spend": 87.42
}
total_spend excludes in-flight holds. See Billing and usage.
Errors
| Status | Cause |
|---|---|
401 | Auth credentials missing or invalid. |
403 | Job belongs to a different account. |
404 | job_id doesn't exist. |
422 | Path parameter shape invalid. |