Skip to main content
This walks you from zero to a PDF. You’ll create an API key, make a single POST request, and get a document back in the response.

1. Create an API key

1

Sign in to the dashboard

Go to app.tipar.dev and sign in with your email. Tipar is passwordless — we send you a magic link, no password to set or forget.
2

Mint a key

Open API keys and create one. The full key is shown once, at creation — copy it now and store it somewhere safe (a secrets manager, your platform’s env vars). Tipar only keeps a hash, so a lost key can’t be recovered, only revoked and replaced.
Keys look like tipar_live_ followed by 32 characters. You send the key as a bearer token on every request to /generate. Full details in Authentication.
Treat the key like a password. It belongs in an environment variable on your server, never in client-side code, a mobile app, or a public repository.

2. Generate your first PDF

The smallest possible request: a one-line template and a single data field. Replace tipar_live_your_key with your real key.
curl https://api.tipar.dev/generate \
  -H "Authorization: Bearer tipar_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "template": { "page": { "content": { "type": "text", "value": "Hello, {{name}}!", "style": { "fontSize": 24, "bold": true } } } },
    "data": { "name": "world" }
  }' \
  --output hello.pdf
You now have hello.pdf on disk. That’s the whole loop: one request in, one PDF out.
A successful response is 200 OK with Content-Type: application/pdf and the raw PDF bytes as the body. There is no JSON wrapper and no job to poll — /generate is synchronous.

3. Render a real document

A single line of text isn’t why you’re here. Here’s a complete one-page invoice — a header, a line-item table that repeats over your data, and a footer. Send this exactly as-is to see it render.
{
  "page": {
    "size": "A4",
    "margin": 40,
    "defaultTextStyle": { "fontSize": 10 },
    "header": {
      "type": "row",
      "items": [
        { "size": { "kind": "relative", "weight": 1 }, "child": { "type": "text", "value": "{{company.name}}", "style": { "fontSize": 18, "bold": true } } },
        { "size": { "kind": "constant", "width": 180 }, "child": { "type": "column", "items": [
          { "type": "text", "value": "INVOICE", "style": { "fontSize": 16, "bold": true }, "align": "right" },
          { "type": "text", "value": "{{invoice.number}} · {{invoice.date}}", "style": { "fontSize": 9, "color": "grey.darken1" }, "align": "right" }
        ] } }
      ]
    },
    "content": {
      "type": "column",
      "spacing": 14,
      "items": [
        { "type": "column", "items": [
          { "type": "text", "value": "Bill to", "style": { "fontSize": 9, "color": "grey.darken1" } },
          { "type": "text", "value": "{{customer.name}}", "style": { "bold": true } },
          { "type": "text", "value": "{{customer.address}}" }
        ] },
        {
          "type": "table",
          "columns": [
            { "kind": "relative", "weight": 5 },
            { "kind": "relative", "weight": 1 },
            { "kind": "relative", "weight": 2 }
          ],
          "header": { "row": [
            { "child": { "type": "text", "value": "Description", "style": { "semiBold": true, "fontSize": 9 } }, "border": { "bottom": 1, "color": "grey.darken1" }, "padding": 5 },
            { "child": { "type": "text", "value": "Qty", "style": { "semiBold": true, "fontSize": 9 }, "align": "right" }, "border": { "bottom": 1, "color": "grey.darken1" }, "padding": 5 },
            { "child": { "type": "text", "value": "Amount", "style": { "semiBold": true, "fontSize": 9 }, "align": "right" }, "border": { "bottom": 1, "color": "grey.darken1" }, "padding": 5 }
          ] },
          "body": {
            "forEach": "invoice.lines",
            "row": [
              { "child": { "type": "text", "value": "{{item.description}}" }, "border": { "bottom": 1, "color": "grey.lighten2" }, "padding": 5 },
              { "child": { "type": "text", "value": "{{item.qty}}", "align": "right" }, "border": { "bottom": 1, "color": "grey.lighten2" }, "padding": 5 },
              { "child": { "type": "text", "value": "{{item.amount}}", "align": "right" }, "border": { "bottom": 1, "color": "grey.lighten2" }, "padding": 5 }
            ]
          }
        },
        { "type": "text", "value": "Total due: {{invoice.total}}", "style": { "bold": true, "fontSize": 13 }, "align": "right" }
      ]
    },
    "footer": {
      "type": "text",
      "value": "{{company.name}} · {{company.email}} · Payable within 14 days",
      "style": { "fontSize": 8, "color": "grey.darken1" },
      "align": "center"
    }
  }
}
Notice the moving parts:
  • {{company.name}}, {{invoice.total}}interpolation tokens, replaced with values from data.
  • The table body uses forEach: "invoice.lines" to render one row per line item. Inside those rows, {{item.description}} refers to the current line. See Tables.
  • Totals are pre-formatted strings ("€87.00"). Tipar does no math — you compute and format values, Tipar lays them out. See why there are no expressions.

Next steps

Learn the template language

Layout, text, tables, images, headers and footers.

Worked examples

Complete, copy-pasteable invoice, receipt, certificate and report templates.

API reference

Every parameter, status code and error of POST /generate.

Handle errors

What 400, 401, 402, 422 and 429 mean and how to react.