Endpoint Group: Jobs
Base group: /convert/job
Endpoints
GET /convert/job/{id}: get job status (JobStatusResponse)GET /convert/job/{id}/download: download output filePOST /convert/job/{id}/cancel: cancel queued/running jobDELETE /convert/job/{id}: delete completed/failed/canceled job (returns409if still queued or running — cancel first)
Output files expire 1 hour after job completion. After expiry, download returns 410 Gone. To clean up immediately after downloading, call DELETE /convert/job/{id}.
Success responses
| Endpoint | Success status | Response body |
|---|---|---|
GET /convert/job/{id} | 200 OK | JobStatusResponse |
GET /convert/job/{id}/download | 200 OK | File stream |
POST /convert/job/{id}/cancel | 202 Accepted | Empty body, Location header → /convert/job/{id} |
DELETE /convert/job/{id} | 204 No Content | Empty body |
Status response example
{
"id": "019c56457340753ba9441d7b4e6516a0",
"status": "Succeeded",
"progress": {
"percent": 100,
"phase": null
},
"metrics": {
"inputBytes": 10333959,
"outputBytes": 10335712,
"creditCost": 1
},
"error": null,
"output": {
"fileName": "document.jpg",
"contentType": "image/jpeg",
"fileCount": 1
}
}
The output object is null for jobs that are still queued, running, failed, canceled, or whose artifacts have expired.
Download response headers
The download endpoint sets standard HTTP headers for the output file:
Content-Type— MIME type of the output (e.g.image/jpeg,application/zip)Content-Disposition—attachment; filename="..."with the output filename
For multi-output jobs (e.g. PDF-to-JPG with multiple pages), the download returns a ZIP archive containing all output files.
| Outputs | Content-Type | Filename pattern |
|---|---|---|
| Single | Actual MIME type | Original stem + target extension |
| Multiple | application/zip | convert.fast-{conversion}-{stem}-{count}-outputs.zip |
Tip: Always use
output.fileNamefrom the status response to set your download filename — don't assume the extension matchestargetFormat. Multi-output converters produce ZIP archives, and future converters may produce different output formats than expected.
Examples
API_KEY="fast_prod_your_key_here"
JOB_ID="019c56457340753ba9441d7b4e6516a0"
# status (use output.fileName for the download -o argument)
RESPONSE=$(curl -sS "https://api.tools.fast/convert/job/${JOB_ID}" \
-H "X-Fast-Api-Key: $API_KEY")
FILENAME=$(echo "$RESPONSE" | jq -r '.output.fileName')
# download using the filename from status
curl -sS "https://api.tools.fast/convert/job/${JOB_ID}/download" \
-H "X-Fast-Api-Key: $API_KEY" \
-o "./${FILENAME}"
# cancel
curl -sS -X POST "https://api.tools.fast/convert/job/${JOB_ID}/cancel" \
-H "X-Fast-Api-Key: $API_KEY"
# delete
curl -sS -X DELETE "https://api.tools.fast/convert/job/${JOB_ID}" \
-H "X-Fast-Api-Key: $API_KEY"$ApiKey = "fast_prod_your_key_here"
$JobId = "019c56457340753ba9441d7b4e6516a0"
$headers = @{ "X-Fast-Api-Key" = $ApiKey }
# status (use output.fileName for the download OutFile argument)
$job = Invoke-RestMethod "https://api.tools.fast/convert/job/$JobId" `
-Headers $headers
# download using the filename from status
Invoke-RestMethod "https://api.tools.fast/convert/job/$JobId/download" `
-Headers $headers -OutFile "./$($job.output.fileName)"
# cancel
Invoke-RestMethod -Method Post "https://api.tools.fast/convert/job/$JobId/cancel" `
-Headers $headers
# delete
Invoke-RestMethod -Method Delete "https://api.tools.fast/convert/job/$JobId" `
-Headers $headersErrors
See Errors for the full error reference.
| Status | Code | Endpoint | Cause |
|---|---|---|---|
401 | api_key.invalid_or_ip_not_allowed | all | Invalid API key |
403 | jobs.forbidden | all | Job owned by another user |
404 | jobs.not_found | all | Job ID does not exist |
409 | jobs.not_ready | download | Job still processing |
409 | jobs.not_cancellable | cancel | Job already completed/failed |
409 | jobs.not_deletable | delete | Job still queued or running — cancel first |
410 | jobs.expired | download | Output artifacts cleaned up |
Example — job not found:
{
"error": "jobs.not_found",
"detail": null
}
Example — download before job finishes:
{
"error": "jobs.not_ready",
"detail": "Job is still processing or waiting to start."
}