How to Generate PDFs from a Template with the ImaginePDF API

Mark a few fields as variables with the lightning-bolt icon, then generate filled PDFs on demand through the ImaginePDF REST API.

Jagadeesh
Jagadeesh
June 26, 20268 min read

In the previous guide we designed a certificate: a title, a recipient's name, a course, a date, all laid out and looking right. But every value on it is fixed. Hand it to a hundred graduates and you'd be editing the same file a hundred times.

The fix is to treat the design as a template: mark the handful of fields that change (the name, the course, the date) as variables, then let the ImaginePDF API fill them in. One design, one call per PDF, any number of certificates.

This guide does exactly that. We'll mark two or three fields as variables in the editor, then generate a filled PDF over the REST API. A certificate is a nice place to start because it's almost all text, but the same flow works for any design.

From a template to many filled PDFs
Mark the fields that change as variables, then fill them through the API: one design, any number of PDFs.

Mark a field as a variable

Open your certificate in the visual editor and click the field you want to make fillable, say the recipient's name. A small toolbar appears above it. The lightning-bolt (⚡) button is the one you want; its tooltip reads Make Dynamic.

Click it and the field changes: it picks up a dashed orange outline, and a little badge appears above it with a name you can type into. That name is the variable; call it recipient_name. That's the whole gesture: select, click the bolt, name it.

The lightning-bolt button makes a field dynamic
Select a field, click the lightning-bolt (⚡) button to make it dynamic, then name the variable. The field turns into a dashed orange box.

A "dynamic" field is just a field whose text comes from outside the design. The styling you set (font, size, color, position) stays exactly as you designed it; only the words get swapped in at generation time.

Name two or three fields

Do the same for the other parts that change. For a certificate that's usually just:

  • recipient_name: who it's for
  • course_name: what they completed
  • date: when

Pick names you'll recognize later, because these become the field names in your API call. Use letters, numbers, and underscores; no spaces. Every field you mark shows up in the Variables panel on the right, so you can see the full list at a glance, rename one, or remove it.

Keep it to the few fields that genuinely change. Everything else (the heading, the seal, the signature line) stays baked into the design.

The Variables panel listing the bound fields
Every field you mark shows up in the Variables panel: the full list of names your API call will fill.

Open the Generate-via-API panel

With your variables named, click API in the editor's top bar. The Generate via API panel slides out with everything you need to make the call:

  • the endpoint, already pointing at this design
  • a ready-to-copy snippet in cURL, JavaScript, or Python
  • the field names it expects, the same ones you just created
The Generate via API panel
The API panel hands you the endpoint, a copy-paste snippet, and the exact field names this design expects.

The design is addressed by its ID, which you'll see in the endpoint (and in the editor URL, after ?design=). There's nothing to publish first; any saved design can be generated.

Create an API key

The call authenticates with an API key. If you don't have one yet, open Settings → API Keys in your dashboard and create one. It looks like pc_live_…, it's tied to your workspace, and it's shown only once, so copy it somewhere safe. You'll send it on the X-API-Key header.

If you already set one up for the Claude plugin, the same key works here.

Fill the fields and generate

Now the call itself. Take the cURL snippet from the panel and fill in your values, one entry per variable, keyed by the name you gave it:

curl -X POST 'https://api.imaginepdf.com/api/v1/designs/YOUR_DESIGN_ID/generate' \
  -H 'X-API-Key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "data": {
    "recipient_name": "Jane Doe",
    "course_name": "Advanced TypeScript",
    "date": "26 June 2026"
  }
}'

The response hands back a link to the finished PDF:

{
  "status": "success",
  "data": {
    "filename": "certificate.pdf",
    "downloadUrl": "https://files.imaginepdf.com/..."
  },
  "error": null
}

Open downloadUrl and there's your certificate, with Jane's name, course, and date dropped into the exact spots you marked. The JavaScript and Python tabs in the panel make the same call if you'd rather not use cURL; they read the link straight off data.downloadUrl.

Request values filling the template fields
Each value in the request lands in the field you named it for: same design, different words.

One design, many PDFs

That's the payoff. The design stays put; only the data changes. Call the endpoint again with a different name and course and you get another certificate, identical in every way except the words you chose to vary:

{
  "data": {
    "recipient_name": "John Smith",
    "course_name": "Intro to Rust",
    "date": "26 June 2026"
  }
}

A single design now backs every certificate you'll ever send: no redrawing, no fragile layout code, just a clean call with the values that change. Open it in the visual editor any time to adjust the look, or revisit the design guide to build your next template from scratch.

Related guides