Guides
Async Polling
When a PDF is too large for synchronous processing or you explicitly request async mode, PDFPipe queues the job and returns a poll URL. This guide explains the flow and shows how to implement it.
When does async processing happen?
Async processing is used when either:
- The PDF file is 10 MB or larger
- You set
"async": truein the request body - You use the batch endpoint (always async)
The API returns 202 Accepted instead of 200, with a pollUrl you can use to check progress.
The async flow
1. Submit the request
curl — async request
curl -X POST https://api.pdfpipe.dev/v1/convert \
-H "Authorization: Bearer pk_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/large-report.pdf",
"format": "json",
"async": true
}'2. Receive the poll URL
202 — Accepted
{
"requestId": "req_01J9X7K2M...",
"status": "pending",
"pollUrl": "/v1/status/req_01J9X7K2M..."
}3. Poll for status
Make GET requests to /v1/status/:requestId every 5 seconds. The status progresses through:
pendingprocessingcomplete
Still processing
{
"requestId": "req_01J9X7K2M...",
"status": "processing",
"format": "json",
"type": "inline",
"createdAt": "2026-02-22T11:00:00.000Z",
"updatedAt": "2026-02-22T11:00:02.500Z"
}Complete — result ready
{
"requestId": "req_01J9X7K2M...",
"status": "complete",
"format": "json",
"type": "inline",
"detectedType": "inline",
"pagesProcessed": 48,
"creditsUsed": 1,
"resultUrl": "https://pdfpipe-results.s3...",
"expiresAt": "2026-02-23T11:00:00.000Z",
"processingDurationMs": 12450,
"createdAt": "2026-02-22T11:00:00.000Z",
"updatedAt": "2026-02-22T11:00:12.450Z"
}4. Handle failures
If the status is failed, the response includes an error object with a code, message, and optional suggestion:
Failed response
{
"requestId": "req_01J9X7K2M...",
"status": "failed",
"format": "json",
"type": "inline",
"error": {
"code": "PROCESSING_ERROR",
"message": "Processing failed. Please retry or contact support.",
"suggestion": "Ensure the URL is publicly accessible and returns a valid PDF."
},
"createdAt": "2026-02-22T11:00:00.000Z",
"updatedAt": "2026-02-22T11:00:08.000Z"
}Polling best practices
- Poll every 5 seconds. Most conversions complete within 10–30 seconds.
- Set a timeout. Stop polling after 5 minutes (60 attempts) and treat it as a failure.
- Check for terminal states. Stop polling when status is
completeorfailed. - Download the result promptly. The
resultUrlis a presigned link that expires based on your tier (1 hour to 7 days).
Full Node.js example
Node.js / TypeScript
async function convertPdf(apiKey: string, pdfUrl: string) {
// 1. Submit the request
const res = await fetch("https://api.pdfpipe.dev/v1/convert", {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ url: pdfUrl, format: "json", async: true }),
});
const data = await res.json();
// 2. If synchronous, return immediately
if (res.status === 200 && data.resultUrl) {
return data;
}
// 3. Poll until complete or failed
const pollUrl = `https://api.pdfpipe.dev/v1/status/${data.requestId}`;
const maxAttempts = 60;
for (let i = 0; i < maxAttempts; i++) {
await new Promise(r => setTimeout(r, 5000));
const poll = await fetch(pollUrl, {
headers: { "Authorization": `Bearer ${apiKey}` },
});
const status = await poll.json();
if (status.status === "complete") return status;
if (status.status === "failed") throw new Error(status.error.message);
}
throw new Error("Polling timed out");
}