Async Jobs
For large files and long-running operations, use async processing. Submit a job, poll for completion, then download the result. Jobs that exceed sync limits are automatically converted to async.
Auto-Async Thresholds
Requests exceeding these limits are automatically processed as async jobs, even without ?async=true. The response will be a 202 with a job ID instead of the usual result.
| Operation | Sync Limit |
|---|---|
| Text / HTML / Markdown / JSON to PDF | 5 MB input |
| Simple OCR (Tesseract) | 20 pages |
| Advanced OCR (DocTR) | 10 pages |
| Vision OCR (Claude AI) | 3 pages |
Submit an Async Job
https://app.alternapdf.com/api/v1/<any-endpoint>?async=trueAppend ?async=true to any processing endpoint to force async execution. The request body and parameters remain the same as the synchronous version.
Response (202 Accepted)
{
"job_id": "job_abc123def456",
"status": "pending",
"message": "Job queued for processing",
"status_url": "https://app.alternapdf.com/api/v1/jobs/job_abc123def456",
"result_url": "https://app.alternapdf.com/api/v1/jobs/job_abc123def456/result"
}Get Job Status
https://app.alternapdf.com/api/v1/jobs/{job_id}Poll this endpoint to check the current status of a job. Status transitions: pending → processing → complete or failed. A job can also be cancelled.
curl -X GET "https://app.alternapdf.com/api/v1/jobs/job_abc123def456" \
-H "X-API-Key: YOUR_API_KEY"{
"job_id": "job_abc123def456",
"status": "complete",
"created_at": "2024-01-15T10:30:00Z",
"completed_at": "2024-01-15T10:30:45Z",
"result_url": "https://app.alternapdf.com/api/v1/jobs/job_abc123def456/result"
}Download Job Result
https://app.alternapdf.com/api/v1/jobs/{job_id}/resultDownload the result of a completed job. For conversion endpoints this returns the output file (PDF, image, etc.). For OCR and extraction endpoints this returns the JSON result.
curl -X GET "https://app.alternapdf.com/api/v1/jobs/job_abc123def456/result" \
-H "X-API-Key: YOUR_API_KEY" \
--output result.pdfList Jobs
https://app.alternapdf.com/api/v1/jobsQuery Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | Filter by status: pending, processing, complete, failed, cancelled |
limit | integer | No | Max number of jobs to return. Default: 20 |
curl -X GET "https://app.alternapdf.com/api/v1/jobs?status=complete&limit=10" \
-H "X-API-Key: YOUR_API_KEY"{
"jobs": [
{
"job_id": "job_abc123def456",
"status": "complete",
"created_at": "2024-01-15T10:30:00Z",
"completed_at": "2024-01-15T10:30:45Z"
},
{
"job_id": "job_xyz789ghi012",
"status": "complete",
"created_at": "2024-01-15T09:15:00Z",
"completed_at": "2024-01-15T09:16:12Z"
}
],
"total": 2,
"limit": 10
}Cancel a Job
https://app.alternapdf.com/api/v1/jobs/{job_id}Cancel a pending or processing job. Returns 204 No Content on success. Already completed or failed jobs cannot be cancelled.
curl -X DELETE "https://app.alternapdf.com/api/v1/jobs/job_abc123def456" \
-H "X-API-Key: YOUR_API_KEY"
# Returns 204 No Content on successComplete Polling Example
End-to-end example: submit a large OCR job, poll until complete, then download the result.
import requests
import time
API_KEY = "YOUR_API_KEY"
BASE = "https://app.alternapdf.com"
HEADERS = {"X-API-Key": API_KEY}
# Step 1: Submit a large PDF for OCR (async)
with open("large-document-50-pages.pdf", "rb") as f:
files = {"file": ("large-document-50-pages.pdf", f, "application/pdf")}
data = {"output": "simple"}
response = requests.post(
f"{BASE}/api/v1/ocr/extract/advanced?async=true",
headers=HEADERS,
files=files,
data=data,
)
job = response.json()
job_id = job["job_id"]
print(f"Job submitted: {job_id}")
print(f"Status: {job['status']}")
# Step 2: Poll for completion
while True:
status_response = requests.get(
f"{BASE}/api/v1/jobs/{job_id}",
headers=HEADERS,
)
status = status_response.json()
print(f"Status: {status['status']}")
if status["status"] == "complete":
print("Job complete!")
break
elif status["status"] == "failed":
print(f"Job failed")
exit(1)
elif status["status"] == "cancelled":
print("Job was cancelled")
exit(1)
# Wait 2 seconds before polling again
time.sleep(2)
# Step 3: Download the result
result_response = requests.get(
f"{BASE}/api/v1/jobs/{job_id}/result",
headers=HEADERS,
)
result = result_response.json()
print(f"Extracted text ({result['data']['word_count']} words):")
print(result["data"]["text"][:500])const fs = require("fs");
const FormData = require("form-data");
const API_KEY = "YOUR_API_KEY";
const BASE = "https://app.alternapdf.com";
const headers = { "X-API-Key": API_KEY };
// Step 1: Submit a large PDF for OCR (async)
const form = new FormData();
form.append("file", fs.createReadStream("large-document-50-pages.pdf"));
form.append("output", "simple");
const submitResponse = await fetch(
`${BASE}/api/v1/ocr/extract/advanced?async=true`,
{
method: "POST",
headers: { ...headers, ...form.getHeaders() },
body: form,
}
);
const job = await submitResponse.json();
const jobId = job.job_id;
console.log(`Job submitted: ${jobId}`);
// Step 2: Poll for completion
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
while (true) {
const statusResponse = await fetch(`${BASE}/api/v1/jobs/${jobId}`, {
headers,
});
const status = await statusResponse.json();
console.log(`Status: ${status.status}`);
if (status.status === "complete") {
console.log("Job complete!");
break;
} else if (status.status === "failed" || status.status === "cancelled") {
console.error(`Job ${status.status}`);
process.exit(1);
}
await sleep(2000);
}
// Step 3: Download the result
const resultResponse = await fetch(`${BASE}/api/v1/jobs/${jobId}/result`, {
headers,
});
const result = await resultResponse.json();
console.log(`Extracted text (${result.data.word_count} words):`);
console.log(result.data.text.slice(0, 500));