> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.bannerify.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Generate PDFs

> Learn how to generate PDF files, such as invoices and certificates, from a template.

You can render any template as a PDF. This is useful for invoices, receipts, labels, and certificates, where you design the layout once and fill in the details for each customer.

## What a PDF contains

A generated PDF has one page. The page is as wide and as high in points as the canvas is in pixels. Text, shapes, and borders are drawn as vectors, so they stay sharp at any zoom, and a reader can select, copy, and search the text. The PDF embeds the fonts that the text uses, and images keep their own resolution.

A PDF cannot draw the `blur()` and `drop-shadow()` filters. A template that uses them answers `400` with a `BAD_REQUEST` error; remove the filters to render it as a PDF. A blurred box shadow is drawn as a soft vector shadow, so it can look a little different from the PNG of the same template.

The **A4 @72dpi** preset in the editor sets the canvas to 595 by 842, an A4 portrait page. The **A4 @96dpi** and **A4 @300dpi** presets make larger pages (794 by 1123 and 2480 by 3508 points).

Design the canvas for the longest content you expect, because a template does not grow to a second page.

## Generate a PDF

1. Create an API key on the **API Keys** page and copy the template id from the template card menu.
2. Send a `POST` request to `/v1/templates/createPdf` with a JSON body:

```bash theme={null}
curl --request POST \
  --url https://api.bannerify.co/v1/templates/createPdf \
  --header 'Content-Type: application/json' \
  --output invoice.pdf \
  --data '{
    "apiKey": "YOUR_API_KEY",
    "templateId": "tpl_invoice",
    "modifications": [
      { "name": "customer", "text": "Acme Studio" },
      {
        "name": "line-items",
        "columns": ["Item", "Qty", "Total"],
        "rows": [
          { "Item": "Automate plan", "Qty": 1, "Total": "$29.00" }
        ]
      }
    ]
  }'
```

3. Read the response. The body is the PDF file, and the `Content-Type` header is `application/pdf`.

A PDF request takes three fields: `apiKey`, `templateId`, and `modifications`. It has no `format` or `quality` option. [Modifications](/docs/essentials/modifications) explains how to fill text, images, and tables.

## Get a link instead of a file

`POST /v1/templates/createStoredPdf` takes the same body and returns a URL in place of the bytes:

```json theme={null}
{
  "url": "https://images.bannerify.co/files/0b3c1c1e-5d6f-4c52-9e0a-8f6a4c0f2a11.pdf"
}
```

Bannerify saves the file and serves it from its CDN at a public URL. On the Scale and Enterprise plans you can also send an `s3Config` object to save the file to your own S3-compatible bucket. [Storage and notifications](/docs/integrations/storage-and-notifications) lists its fields.

## Use an SDK

The JavaScript, Python, PHP, and Go SDKs have a `createPdf` method that returns the bytes. No SDK wraps `createStoredPdf`, so call that endpoint over REST. [Create images and PDFs](/docs/sdk/js/apis/create-image#create-a-pdf) shows the JavaScript version.

## Quota and errors

Each PDF counts as one generation. [Quota and limits](/docs/account/quota) lists what counts and which limits apply. A failed request returns JSON with an `error` object, and [Errors](/docs/api-reference/errors/introduction) lists the codes.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.