How it works
The few rules that apply to every route. Worth five minutes before you build on the API.
The path of a request
- Your request reaches
api.pdfdispatch.com. The gateway checks the key, the plan’s size limit and the requests per minute, and makes sure the account has a PDF left: one of the plan’s PDFs for this period, or credits to pay for one. - It streams the request to the PDF engine: Chromium for HTML, URLs and Markdown; LibreOffice for Office files; a set
of PDF tools for the
/v1/pdf/...routes. - The engine answers, and the gateway streams the answer back to you and records how the request ended.
Your files are worked on in a temporary folder that is removed when the request ends. For billing we keep a record that the request happened (its time, status and sizes), never its content.
One request, one PDF
A request that ends with a 2xx status counts as one PDF. It does not matter how many pages it has, how many
files you uploaded or got back (a split into ten parts, ten Office files in one ZIP), or which route you used. A
screenshot, a merge and a metadata read each count as one.
A request that fails counts nothing: a wrong field (400), a refused URL (403), a page that failed a check
(409), a request that is too big (413), any 429, timeouts and server errors. A webhook request counts when it is
accepted with 204 (see below).
If you can do several steps in one request, do: converting with pdfa=PDF/A-2b and userPassword=... is one PDF;
converting, then sending the result to /v1/pdf/pdfa and /v1/pdf/encrypt is three.
The answer: now, or by webhook
By default the answer is the file. The connection stays open while the PDF is made, and you get it in the body,
with Content-Type and a Content-Disposition: attachment; filename=... header. When a request produces several
files (Office files without merge, a split), you get a ZIP of them.
With a webhook (a Webhook-Url header), the API answers 204 No Content at once, makes the file, and then sends
it to your URL. That frees your client, and it suits job queues. It does not make conversions faster or allow them to
run longer. See Webhooks.
Time limits
- The PDF engine stops a job after 60 seconds and answers
503with a plain-text message. This also applies to webhook jobs. - The gateway stops any request after 65 seconds in total, counted from its arrival: your upload, the conversion
and the download of the answer. It then answers
504with code50410.
Most pages take one to five seconds. Slow ones usually wait for something: large images, many web fonts, a script
that fetches data, or a waitDelay that is longer than it needs to be.
Set your HTTP client’s timeout a little above 65 seconds (we use 70 in the examples), so you see our answer instead of your own timeout.
Request size
The largest request your plan allows is the whole body: all files and fields together, as sent. A request whose
Content-Length is too big is refused before the upload (413, code 41301); a body without a
length is cut off once it passes the limit (code 41310).
| PDFs per month | Largest request | Requests per minute |
|---|---|---|
| 100 (Free) | 5 MB | 10 |
| 500 | 20 MB | 60 |
| 1,000 | 20 MB | 60 |
| 2,500 | 20 MB | 60 |
| 5,000 | 20 MB | 60 |
| 10,000 | 50 MB | 120 |
| 25,000 | 50 MB | 120 |
| 50,000 | 100 MB | 300 |
| 100,000 | 100 MB | 300 |
| 200,000 | 100 MB | 300 |
| 500,000 | 100 MB | 300 |
Files the API fetches for you (downloadFrom) count towards the same limit. Pages and images the browser loads from the
web for a URL or HTML conversion do not.
Request ids
Every answer has an X-Request-Id header, errors included. It is a UUID made by the gateway, also used in our logs,
so it is the fastest way for us to find a request: put it in every message to support, and in your own logs.
For webhook jobs, the same id is in the X-Request-Id header of every call we make to your URLs, and in the
correlationId field of the JSON events. You cannot set it yourself; a header you send is replaced.
Rate limits
Each plan has a number of requests per minute (in the table above). Over it, you get 429 with code
42910 and a Retry-After header with the seconds to wait. The count is per account, not per key.
Retries
400,403,409,413and415fail the same way every time: change the request first.429with42910: wait forRetry-After, then retry. The other429codes need a change on the account.500,502,503and504: retry a couple of times with a growing pause (for example 2, 5, then 15 seconds). A failed request costs nothing.