Jobs and pipelines
Every run is a job. Short ones can wait in the request; long ones run in the background while you poll or get a callback.
Sync or async
| Route | Success | Use it for |
|---|---|---|
POST /v1/tools/:slug | 201 with the file; 202 with the job after 60 s | Small files and quick tools |
POST /v1/tools/:slug/jobs | 201 with the job at once | Large files, OCR, video, anything slow |
curl -X POST "https://api.sadafiles.com/v1/tools/pdf-to-word/jobs" \
-H "X-API-Key: $SADAFILES_API_KEY" \
-F "files[]=@report.pdf"Job lifecycle
A job moves from queued to running and ends as done, failed, cancelled or expired. Ids are UUIDs. Inputs, outputs and the per-job key are purged by expiresAt, at most 24 hours later.
{
"id": "de01bc4a-0686-400b-a594-20f031191629",
"status": "running",
"tool": "pdf-to-word",
"steps": [
"pdf-to-word"
],
"runtime": "server",
"progress": {
"percent": 40,
"stepIndex": 0,
"stepCount": 1
},
"inputCount": 1,
"inputBytes": 182044,
"queuedAt": "2026-11-01T16:31:37.714Z",
"expiresAt": "2026-11-02T16:31:37.708Z"
}Job endpoints
| Route | Scope | Does |
|---|---|---|
GET /v1/jobs/:id | jobs:read | Status and progress |
GET /v1/jobs/:id/result | jobs:read | Download the result, as often as you like until it expires |
POST /v1/jobs/:id/continue | jobs:write, tools:run | Run more steps on the output without uploading again |
POST /v1/jobs/:id/cancel | jobs:write | Stop a queued or running job |
DELETE /v1/jobs/:id | jobs:write | Purge inputs, outputs and the key now (204) |
Pipelines
Send up to 32 steps in the steps field. Each step's output feeds the next, and the whole chain is checked before it starts; a bad link returns PIPELINE_INCOMPATIBLE. Add ?async=1 to get the job back straight away (202).
curl -X POST "https://api.sadafiles.com/v1/pipeline" \
-H "X-API-Key: $SADAFILES_API_KEY" \
-F "files[]=@photo.jpg" \
-F 'steps=[{"tool":"resize-image","options":{"width":1200}},{"tool":"compress-image","options":{"quality":80}}]' \
-o result.jpgWeigh up what each tool takes and returns on its endpoint page. The optional output field is JSON like steps, so quote the value in a form field: -F 'output="zip"'. It takes single, zip or json-urls.
Batches
POST /v1/batches takes up to 500 files plus a tool (with options) or steps, and creates one job per file. GET /v1/batches/:id reports progress and GET /v1/batches/:id/result returns a ZIP of everything that finished.
curl -X POST "https://api.sadafiles.com/v1/batches" \
-H "X-API-Key: $SADAFILES_API_KEY" \
-F "files[]=@one.jpg" \
-F "files[]=@two.jpg" \
-F "tool=compress-image"Safe retries
Send an Idempotency-Key header on tool and pipeline runs. If a network error makes you retry, the same key returns the existing job instead of creating a second one.
Live progress
Polling works everywhere. For live updates, connect with Socket.IO to the /jobs namespace, passing your key as auth.apiKey, then emit subscribe with { id }. You receive job.progress, job.completed, job.failed and job.deleted, with metadata only. The key needs jobs:read.

