Inkspan › Guides › Invoice PDF API

Invoice PDF API

Generating invoices is the most common reason teams add a PDF API. Rather than maintaining a headless browser and a template engine, you send line-item data as JSON and get a branded PDF back.

Invoices are a templating problem, not a rendering problem: one layout, thousands of data variations. Keep the template in your database per tenant and let finance change wording without a deploy.

Example

import requests

r = requests.post(
    'https://api.inkspan.dev/v1/generate/template',
    headers={'X-API-Key': 'ink_live_...'},
    json={
        "template": "<h1>Invoice {{ number }}</h1>{% for i in items %}<p>{{ i.desc }}: ${{ i.amt }}</p>{% endfor %}<h3>Total: ${{ total }}</h3>",
        "data": {
            "number": "INV-1042",
            "items": [
                {
                    "desc": "Pro Plan",
                    "amt": 49
                }
            ],
            "total": 49
        }
    },
)
r.raise_for_status()
with open('document.pdf', 'wb') as f:
    f.write(r.content)

Request parameters

NameTypeRequiredDescription
templatestringyesA Jinja2 template. Supports {{ variables }}, {% for %} loops, {% if %} conditionals, and filters.
dataobjectyesJSON object whose top-level keys become template variables.
filenamestringnoFilename in the response's Content-Disposition.

Response

Returns a PDF as a binary stream with Content-Type: application/pdf and Content-Disposition: attachment; filename=document.pdf. Write the response body straight to disk — do not parse it as JSON.

Things that catch people out

Errors

StatusMeaningFix
401Invalid or missing API keySend your key in the X-API-Key header.
402Monthly quota exceededThe response reports used/quota. Upgrade at inkspan.dev/#pricing.
422Missing or invalid parameterCheck required fields in the table above — the body names the offending field.

Failed requests do not count against your quota; only successful ones are metered.

Frequently asked questions

Is there a free tier?

Yes — 100 documents a month, no card required. Usage-based plans start at $19/month when you outgrow it.

How do I authenticate?

Send your key in the X-API-Key header on every request.

Do failed requests count against my quota?

No. Only successful requests are metered.

Get a free API key →

Full guides for /v1/generate/template: cURL · Python · Node.js · all guides