Artifacts #
List, get, patch, delete, upload, download, status, cancel, rerun. Every endpoint under /artifacts.
The /artifacts/* endpoints cover the full lifecycle of an uploaded file:
listing, metadata, downloads, lightweight status, cancel, rerun, the
confirm-upload signal that tells the backend a presigned upload landed, and
the direct multipart upload form.
GET /artifacts/
GET /artifacts/Paginated list of artifacts owned by the authenticated account.
| Param | Type | Default | Notes |
|---|---|---|---|
page | integer | 1 | 1-based page number. |
size | integer | 50 | Items per page. |
curl -u "$DD_KEY:$DD_SECRET" \ 'https://api.datadistillers.com/api/v1/artifacts/?page=1&size=50'
Returns a Page[ArtifactListResponse]:
{
"items": [
{
"id": "art_b4d8c0f1",
"filename": "invoice-001.pdf",
"artifact_type": "application/pdf",
"artifact_size": 184320,
"status": "completed",
"uploaded_at": "2026-05-03T09:12:04Z",
"confidence": 0.94,
"needs_review": false
}
],
"total": 2841,
"page": 1,
"size": 50,
"pages": 57
}
GET /artifacts/{id}
GET /artifacts/{id}Full record: metadata, status, processing timestamps, the most recent extraction result, and every job ever run against the artifact.
curl -u "$DD_KEY:$DD_SECRET" \ https://api.datadistillers.com/api/v1/artifacts/art_b4d8c0f1
See Artifacts for the response shape.
GET /artifacts/{id}/status
GET /artifacts/{id}/statusLightweight status check for high-frequency polling. Returns just status,
processed_at, and error: no metadata, no extraction result, no job array.
curl -u "$DD_KEY:$DD_SECRET" \ https://api.datadistillers.com/api/v1/artifacts/art_b4d8c0f1/status
{
"id": "art_b4d8c0f1",
"status": "processing",
"processed_at": null,
"status_message": null
}
Prefer this over the full GET /artifacts/{id} when polling at sub-second
intervals. Less bandwidth, less parsing, same source of truth.
PATCH /artifacts/{id}
PATCH /artifacts/{id}Update mutable metadata. Three fields can be patched after upload:
curl -u "$DD_KEY:$DD_SECRET" \
-X PATCH https://api.datadistillers.com/api/v1/artifacts/art_b4d8c0f1 \
-H 'Content-Type: application/json' \
-d '{
"filename": "renamed.pdf",
"description": "Q2 batch, Acme",
"tags": ["fy26", "q2", "acme"]
}'
| Field | Constraints |
|---|---|
filename | Min length 3. |
description | Max length 1000. |
tags | Free-form string array. |
Anything else (size, MIME, status, processing timestamps) is set by the platform and not user-mutable.
DELETE /artifacts/{id}
DELETE /artifacts/{id}Removes the artifact record and its stored files immediately. No soft delete.
curl -u "$DD_KEY:$DD_SECRET" \ -X DELETE https://api.datadistillers.com/api/v1/artifacts/art_b4d8c0f1
Returns 204 No Content on success.
POST /artifacts/{id}/confirm-upload
POST /artifacts/{id}/confirm-uploadThe signal that tells the backend a presigned upload completed. The
platform does not watch the upload bucket for S3 events; until you call
this endpoint the artifact stays in pending_upload and the job is never
enqueued.
When called, the platform:
- Verifies the object exists in S3 under the expected key.
- Flips the artifact status from
pending_uploadtouploaded. - Flips the job status to
queued_for_processing. - Commits, then dispatches the worker to start processing.
curl -u "$DD_KEY:$DD_SECRET" \ -X POST https://api.datadistillers.com/api/v1/artifacts/art_b4d8c0f1/confirm-upload
Returns 200 OK and the updated artifact.
| Status | Meaning |
|---|---|
200 | The artifact moved to uploaded and the job was queued. Repeated calls return 200 without re-queueing. |
404 | artifact_id doesn't exist or belongs to a different account. |
409 | The artifact is past uploaded (already processing, completed, failed, etc.) or the S3 object is missing. |
The endpoint is idempotent: calling it again on an already-confirmed
artifact is safe and will not enqueue duplicate work. Use
POST /artifacts/confirm-batch-upload/{batch_id} to
confirm an entire batch in one call.
POST /artifacts/upload
POST /artifacts/uploadDirect multipart upload, for cases where you'd rather send the file in one shot than do the submit / PUT / confirm three-step.
curl -u "$DD_KEY:$DD_SECRET" \ -X POST https://api.datadistillers.com/api/v1/artifacts/upload \ -F 'file=@./invoice.pdf' \ -F 'retention_policy=30d'
Form fields:
| Field | Required | Notes |
|---|---|---|
file | yes | The file bytes. |
retention_policy | no | One of the RetentionPolicy values. Defaults to 30d. |
Returns 202 Accepted + SingleUploadResponse (the artifact, with status
uploaded). Unlike the presigned-URL flow, the upload bytes and the queue
dispatch happen inline as part of the same request, so you do not need
a separate confirm-upload call after this endpoint.
/artifacts/upload is convenient for one-off scripts but doesn't accept
template_id or extraction_schema; it relies on whatever pipeline
default is set on the API key. New integrations should prefer
/extract (followed by PUT and confirm-upload) for the explicit
template-or-schema selection.
POST /artifacts/request-batch-upload and POST /artifacts/confirm-batch-upload/{batch_id}
POST /artifacts/request-batch-upload and POST /artifacts/confirm-batch-upload/{batch_id}Two-step batch upload. Like the single-file presigned flow, the platform only enqueues work after you confirm — but here one call confirms every file in the batch at once.
# 1. Request URLs
curl -u "$DD_KEY:$DD_SECRET" \
-X POST https://api.datadistillers.com/api/v1/artifacts/request-batch-upload \
-H 'Content-Type: application/json' \
-d '{
"files": [
{ "filename": "a.pdf", "artifact_type": "application/pdf", "artifact_size": 1024 },
{ "filename": "b.pdf", "artifact_type": "application/pdf", "artifact_size": 2048 }
]
}'
# returns batch_id and per-file upload URLs
# 2. PUT every file to its upload URL (concurrently).
# 3. Confirm; queues all uploaded files in one round-trip.
curl -u "$DD_KEY:$DD_SECRET" \
-X POST https://api.datadistillers.com/api/v1/artifacts/confirm-batch-upload/bat_z9y8x7
Confirm is idempotent. Already-confirmed files are skipped; never-uploaded
files stay pending. POST /batch is the friendly
front-door that returns the same shape as request-batch-upload; both
require this confirm call before anything is enqueued.
GET /artifacts/{id}/download
GET /artifacts/{id}/downloadReturns a short-lived presigned URL to download an artifact or its extraction results.
| Param | Default | Notes |
|---|---|---|
file_type | json | One of raw (original file), json (structured result), md (markdown rendering). |
URL=$(curl -s -u "$DD_KEY:$DD_SECRET" \ 'https://api.datadistillers.com/api/v1/artifacts/art_b4d8c0f1/download?file_type=json' \ | jq -r .download_url) curl -s "$URL" > result.json
Response:
{
"download_url": "https://s3.amazonaws.com/…?X-Amz-Signature=…",
"artifact_id": "art_b4d8c0f1",
"filename": "invoice-001.pdf",
"expires_in": 300
}
Don't cache download_url. Re-request on each download.
POST /artifacts/{id}/rerun
POST /artifacts/{id}/rerunQueues a fresh job against an artifact already in S3. Works for any terminal
state: failed, cancelled, or completed.
curl -u "$DD_KEY:$DD_SECRET" \ -X POST https://api.datadistillers.com/api/v1/artifacts/art_b4d8c0f1/rerun
Returns 202 Accepted. A new Job record is created with a fresh job_id;
the prior billing history is preserved on the artifact.
Returns 400 if the artifact's retention policy
already purged the source file.
POST /artifacts/{id}/cancel
POST /artifacts/{id}/cancelCancels an in-flight processing job. Releases held balance, best-effort stops the GPU worker.
curl -u "$DD_KEY:$DD_SECRET" \ -X POST https://api.datadistillers.com/api/v1/artifacts/art_b4d8c0f1/cancel
Returns:
200 OK: cancellation took effect.409 Conflict: job is already in a terminal state.
Errors
| Status | Cause |
|---|---|
400 | Invalid request shape, or rerun against a purged artifact. |
401 | Auth missing or invalid. |
403 | Artifact belongs to a different account. |
404 | artifact_id doesn't exist. |
409 | Cancel against a terminal job, or confirm-upload against an artifact past uploaded / with no object in S3. |
422 | Body or path parameter validation failed. |