List templates
What a template is
A template is a document design stored under a code you choose. It has two lives at once: a draft you keep editing and a published version your production renders use. Saving does not publish, so an unfinished change cannot reach your customers.
Returns the templates in your workspace together with their published version numbers. You use a template's code when you render.
curl https://api.pdfgine.com/api/v1/templates \
-H "X-PDFgine-Key: $PDFGINE_KEY"
[
{
"templateId": "tpl_eca4c9985ad74913902f0469469936a1",
"code": "invoice",
"name": "Corporate Invoice",
"version": 5,
"publishedVersion": 1,
"publishedAt": "2026-08-23T08:23:21+00:00"
}
]
Page number format
The content of a page-number element is a format: {{ page }} becomes the current page and {{ pages }} the total page count. Write “{{ page }} / {{ pages }}” and the document prints “3 / 12” — with page counters in the PDF and PAGE/NUMPAGES field codes in Word, so both update by themselves when pages are added. When the content holds no placeholder it is ignored and only the page number is printed.
Saving a version
A save carries the version you believe you are editing. If someone else saved in the meantime, the answer is 409 and names the version that is current, so nothing is silently overwritten.
curl -X POST https://api.pdfgine.com/api/v1/templates \
-H "X-PDFgine-Key: $PDFGINE_KEY" \
-H "Content-Type: application/json" \
-d '{
"code": "invoice",
"name": "Corporate Invoice",
"saveMode": "manual",
"expectedVersion": 5,
"changeReason": "Logo moved to the right margin.",
"definition": {
"page": { "size": "A4", "orientation": "portrait" },
"elements": [
{ "type": "text", "text": "Corporate Invoice", "fontSize": 24 }
]
}
}'
HTTP/1.1 409 Conflict
{
"type": "https://pdfgine.dev/problems/template-conflict",
"templateCode": "invoice",
"currentVersion": 6,
"currentDraftRevision": 0
}
expectedVersion is optional but recommended: without it the last writer wins and the earlier change disappears without a trace.
What usually goes wrong
- 409 is not an error to retry blindly. Read currentVersion, take the newer definition, apply your change on top of it, then save again.
- Saving is not publishing. A production render keeps using the last published version until you publish the draft.
- The listing answers at most 200 templates. When more exist the response carries a Link header with rel="next"; follow it instead of assuming the first page is the whole library.
- Reading needs templates:read and saving needs templates:write. A read-only key answers 403 on save, not 401.
- The code is how every other call finds the template. Renaming the template is free; changing its code means a new template.