The request itself is small enough to paste into a terminal:
```bash curl -X POST https://pdfly.3idhmind.in/api/pdf/generate \ -H "Authorization: Bearer $PDFLY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"documents":[{"title":"Invoice","content":"<h1>Invoice #42</h1><p>Amount: $500</p>"}]}' ```
That is the whole integration for a single document. The response carries the PDF back as base64 in `documents[0].pdf_base64`, decode it and write it to disk. No infrastructure to run, nothing to install, and the free tier needs no card.
## The limits that matter before you hit them
**Five documents per request, not ten.** A batch call takes an array under `documents`, and the cap is 5. Send a sixth and the whole request is rejected with a 400, not truncated to the first five, so check the array length before you send rather than after you get an error.
**500,000 characters per document, not per request.** That is generous for almost anything, a genuinely enormous report would be the only thing to hit it, but it is worth knowing the number is per document, so five documents at the cap combine to 2.5 million characters in one call.
**The whole request body caps near 4.5MB**, which is Vercel's platform limit rather than ours, applied before our code even runs. This mostly matters if you are embedding large inline images as data URIs in the HTML, since those inflate the request size fast.
**60 requests per minute, and it is a real limiter, not a soft guideline.** The 61st request in a minute gets a 429 with a `Retry-After` header telling you exactly how long to wait. Respect that header rather than guessing at a backoff, since it is computed from the actual window remaining.
## Script content, not template content
The API renders with a built-in font that covers Latin scripts, and now also embeds a matching Noto font automatically when your content is Devanagari (Hindi, Marathi, Sanskrit, Nepali) or Arabic script (Arabic, Persian, Urdu), that support landed after this guide was first written, so if you read an older version that said Latin-only, that has changed. Chinese, Japanese, Korean, Hebrew and Thai are still not supported on the API. Sending them gets you a warning in the response rather than silently broken output, and the [browser tool](/text-to-pdf) does not cover them either at the moment.
## What a real integration needs beyond the happy path
The request above works. A script calling it in production needs three things the quick example skips:
1. **Retry on 429, using the header.** A fixed exponential backoff works, but reading `Retry-After` and waiting exactly that long wastes fewer requests than guessing. 2. **Check `response.storage` before assuming the file persists.** If object storage is not configured on our end, `storage.persisted` is false and the file exists only in that response. If it is configured, you also get a `download_url` on our own domain, valid for an hour. 3. **Validate your HTML before sending it, not after the response comes back malformed.** A missing closing tag usually still renders something, just not what you meant, and the API has no way to tell you your markup was wrong when it was still valid enough to parse.
Full field-by-field request and response shapes are on the [API reference](/docs#generate), generated from the same code that runs the endpoint rather than written by hand, so it should not drift from what the server actually does.