Developers
Pro APIPro plan only
The same tools as on the website, driven from your code. The API is included in the Pro plan and shares your account's quotas.
API version 1, currently opening: the endpoints described here are stable in principle, but some details may still change. Changes will be announced on this page.
The Pro API gives you the same tools as the website: conversions, compression, OCR, merging, and the AI assistant features. A job always runs in four steps: you create it, upload the files, start it, then fetch the result (by polling or through a webhook).
Every request uses HTTPS and returns JSON. Files never go through the API itself: they're sent straight to private storage through short-lived signed URLs.
Authentication
Create a key from your account (API section). It starts with efp_live_ and is shown only once: we only keep a fingerprint of it. Send it in the Authorization header of every request.
Treat this key like a password: never in browser-side code, never in a public repository. You can revoke it at any time; a revoked key stops working immediately.
Authorization: Bearer efp_live_XXXXXXXXXXXXXXXXAvailable tools
Each tool is referenced by its identifier, the same as in our registry. Tools that run in the browser on the website run on our servers when called through the API. Each tool's parameters mirror the options on its page.
| Identifier | Tool | Family | Output |
|---|---|---|---|
| merge | Merge PDF | Classic | |
| split | Split PDF | Classic | PDF / ZIP |
| rotate | Rotate PDF | Classic | |
| delete-pages | Delete PDF pages | Classic | |
| organize | Organize PDF pages | Classic | |
| crop | Crop PDF | Classic | |
| watermark | Add a watermark | Classic | |
| add-image | Add an image to PDF | Classic | |
| page-numbers | Add page numbers | Classic | |
| sign | Sign PDF | Classic | |
| edit | Edit PDF | Classic | |
| compress | Compress PDF | Classic | |
| compress-image | Compress image | Classic | JPG / PNG / WebP |
| ocr | OCR: make a PDF searchable | Classic | PDF / TXT |
| pdf-to-word | PDF to Word | Classic | DOCX |
| pdf-to-excel | PDF to Excel | Classic | XLSX |
| pdf-to-powerpoint | PDF to PowerPoint | Classic | PPTX |
| pdf-to-jpg | PDF to JPG | Classic | JPG / ZIP |
| pdf-to-png | PDF to PNG | Classic | PNG / ZIP |
| pdf-to-text | PDF to text | Classic | TXT |
| word-to-pdf | Word to PDF | Classic | |
| excel-to-pdf | Excel to PDF | Classic | |
| powerpoint-to-pdf | PowerPoint to PDF | Classic | |
| jpg-to-pdf | JPG to PDF | Classic | |
| png-to-pdf | PNG to PDF | Classic | |
| html-to-pdf | HTML to PDF | Classic | |
| protect | Protect PDF | Classic | |
| unlock | Unlock PDF | Classic | |
| metadata | PDF metadata | Classic | |
| ai-chat | Chat with your PDF | AI | Réponses citées / Cited answers |
| ai-summarize | Summarize PDF | AI | Texte / DOCX / PDF |
| ai-translate | Translate PDF | AI | PDF / DOCX |
| ai-ocr | Smart OCR | AI | DOCX / Markdown / PDF |
| ai-extract | Extract data | AI | XLSX / CSV / JSON |
| ai-fill | Assisted form filling | AI | |
| ai-rewrite | Rewrite and proofread | AI | |
| ai-generate | Generate a document | AI |
Create a job
Declare the tool, its parameters and the list of files (name, size in bytes, MIME type). Your account limits are checked at this point: if one is exceeded, the response explains which. Quota is only consumed for good if the job succeeds.
curl -X POST "https://eflypdf.com/api/v1/jobs" \
-H "Authorization: Bearer efp_live_XXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{
"tool": "compress",
"params": { "mode": "recommended" },
"files": [{ "name": "rapport.pdf", "size": 2483021, "mime": "application/pdf" }]
}'{
"jobId": "4f6c1d2e-8a0b-4c7e-9d51-2b8f0e3a9c10",
"uploads": [
{ "path": "…/4f6c1d2e…/0-rapport.pdf", "signedUrl": "https://…", "token": "…" }
]
}Upload the files
Send each file to its signed URL, in list order. These URLs expire quickly: upload right after creating the job. Every file is virus-scanned before processing.
curl -X PUT "<signedUrl>" \
-H "Content-Type: application/pdf" \
--data-binary @rapport.pdfStart and track the job
Once the files are uploaded, start the job. It moves through queued, running, then succeeded or failed. Poll it at a reasonable interval (every 2 to 5 seconds) or, better, subscribe to webhooks.
API jobs get the Pro plan's high priority in the queue.
curl -X POST "https://eflypdf.com/api/v1/jobs/4f6c1d2e-8a0b-4c7e-9d51-2b8f0e3a9c10/start" \
-H "Authorization: Bearer efp_live_XXXXXXXXXXXXXXXX"curl "https://eflypdf.com/api/v1/jobs/4f6c1d2e-8a0b-4c7e-9d51-2b8f0e3a9c10" \
-H "Authorization: Bearer efp_live_XXXXXXXXXXXXXXXX"{
"id": "4f6c1d2e-8a0b-4c7e-9d51-2b8f0e3a9c10",
"tool": "compress",
"status": "succeeded",
"progress": 100,
"error": null,
"expiresAt": "2026-10-21T15:00:00Z"
}Download the result
The download endpoint answers with a redirect to a temporary signed URL. The result stays available for your plan's retention period, then it's deleted automatically along with the source files.
curl -L "https://eflypdf.com/api/v1/jobs/4f6c1d2e-8a0b-4c7e-9d51-2b8f0e3a9c10/download" \
-H "Authorization: Bearer efp_live_XXXXXXXXXXXXXXXX" \
-o resultat.pdfSigned webhooks
Register an HTTPS URL in your account and choose the events (job.done, job.failed). Each delivery carries the X-Signature header: t is the Unix timestamp, v1 the hex HMAC-SHA256 signature of the string "t.raw_body" computed with the webhook secret.
Always verify the signature and reject stale messages. Reply with a 2xx code within 10 seconds; on failure, delivery is retried several times with increasing delays. The same event may arrive twice: deduplicate on its id.
POST https://votre-serveur.example/webhooks
X-Signature: t=1792335600,v1=5f2b…c9e1
Content-Type: application/json
{
"event": "job.done",
"jobId": "4f6c1d2e-8a0b-4c7e-9d51-2b8f0e3a9c10",
"tool": "compress",
"status": "done",
"errorCode": null,
"createdAt": "2026-10-19T15:00:00Z"
}import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(rawBody: string, header: string, secret: string, toleranceSec = 300) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false;
const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
const given = Buffer.from(parts.v1 ?? "", "hex");
return given.length === 32 && timingSafeEqual(given, Buffer.from(expected, "hex"));
}Quotas and limits
The API has no separate quota: it uses exactly the same counters as your Pro account on the website (AI pages, translation words, file size, batches). The values below are read from our live configuration.
Rate limiting protects the service: beyond the allowed number of requests per minute, the response is 429. Wait a few seconds before retrying.
| Limit | Value (Pro plan) |
|---|---|
| Maximum file size | 1 GB |
| Files per run (batch) | 100 files |
| Operations per day | Unlimited |
| AI pages | 2,000 AI pages per month |
| Translation | 500,000 words per month |
| Document size for chat | 2,000 pages |
| Documents open in chat | 10 documents |
| Assistant model | Fast or advanced (×20 AI pages) |
| Requests per minute (per account) | 120 |
Errors
Errors use the usual HTTP codes: 400 (invalid request), 401 (missing or revoked key), 402 (plan limit reached), 404 (unknown job), 429 (rate or daily quota), 503 (assistant temporarily unavailable: nothing is counted). Limit refusals carry an explicit code.
HTTP/1.1 402 Payment Required
{
"error": "limit",
"refused": { "code": "AI_PAGES_EXHAUSTED", "max": 2000, "current": 2000, "resetAt": "2026-11-03T00:00:00Z", "upgradeTo": null }
}