Skip to content

Template tags

A tag is a movable name for a published version. Render what it names by adding it as an @ suffix — report@production. Moving the tag changes what renders without changing the request. See Versions & Tags for how versions and tags fit together.

A tag is 1–64 characters of lowercase letters, digits and single hyphens. It cannot be all digits, because that would be a second spelling of @<number>, and live and latest are reserved.

Point a tag at a version

PUT
/v2/templates/{templateId}/tags/{tag}

Names a published version, so it can be identified by name rather than by number. Setting a tag the template already holds moves it to the version in the request. Sending the same version again succeeds unchanged.

Authorizations

BearerAuth

Your Papermill API key, sent as Authorization: Bearer <key>.

Type
HTTP (bearer)
or
ApiKeyHeader

Your Papermill API key. Equivalent to the bearer form.

Type
API Key (header: x-api-key)

Parameters

Path Parameters

templateId*
Type
string
Required
Min Length
1
Max Length
128
Pattern
"^(?!__.*__$)[A-Za-z0-9_-]+$"
tag*
Type
string
Required
Min Length
1
Max Length
64

Request Body

application/json
JSON
{
  
"version": 0
}

Responses

Tag set

application/json
JSON
{
  
"tag": "string",
  
"version": 0
}

Playground

Authorization
Variables
Key
Value
Body

Samples

List a template's tags

GET
/v2/templates/{templateId}/tags

Every tag the template holds and the version each one names, ordered by name. has_more is true when the template holds tags beyond the ones returned; send the last tag back as start_after to continue.

Authorizations

BearerAuth

Your Papermill API key, sent as Authorization: Bearer <key>.

Type
HTTP (bearer)
or
ApiKeyHeader

Your Papermill API key. Equivalent to the bearer form.

Type
API Key (header: x-api-key)

Parameters

Path Parameters

templateId*
Type
string
Required
Min Length
1
Max Length
128
Pattern
"^(?!__.*__$)[A-Za-z0-9_-]+$"

Query Parameters

start_after
Type
string
Min Length
1
Max Length
64

Responses

Tags held

application/json
JSON
{
  
"tags": [
  
  
{
  
  
  
"tag": "string",
  
  
  
"version": 0,
  
  
  
"updated_at": "string",
  
  
  
"updated_by": {
  
  
  
  
"id": "string",
  
  
  
  
"name": "string",
  
  
  
  
"email": "string"
  
  
  
}
  
  
}
  
],
  
"has_more": true
}

Playground

Authorization
Variables
Key
Value

Samples

Read one tag

GET
/v2/templates/{templateId}/tags/{tag}

The version a tag names, and who last moved it there.

Authorizations

BearerAuth

Your Papermill API key, sent as Authorization: Bearer <key>.

Type
HTTP (bearer)
or
ApiKeyHeader

Your Papermill API key. Equivalent to the bearer form.

Type
API Key (header: x-api-key)

Parameters

Path Parameters

templateId*
Type
string
Required
Min Length
1
Max Length
128
Pattern
"^(?!__.*__$)[A-Za-z0-9_-]+$"
tag*
Type
string
Required
Min Length
1
Max Length
64

Responses

The tag

application/json
JSON
{
  
"tag": "string",
  
"version": 0,
  
"updated_at": "string",
  
"updated_by": {
  
  
"id": "string",
  
  
"name": "string",
  
  
"email": "string"
  
}
}

Playground

Authorization
Variables
Key
Value

Samples

List a tag's history

GET
/v2/templates/{templateId}/tags/{tag}/history

Every recorded change to a tag, newest first: which version it was pointed at, which it named before, when, and by whom. A tag is a pointer that gets overwritten, so this is where earlier moves are kept. History survives removing the tag. The most recent changes are the ones returned, and has_more is true when the tag has been moved more times than fit — there is no way to page further back, so treat it as a depth limit rather than a cursor.

Authorizations

BearerAuth

Your Papermill API key, sent as Authorization: Bearer <key>.

Type
HTTP (bearer)
or
ApiKeyHeader

Your Papermill API key. Equivalent to the bearer form.

Type
API Key (header: x-api-key)

Parameters

Path Parameters

templateId*
Type
string
Required
Min Length
1
Max Length
128
Pattern
"^(?!__.*__$)[A-Za-z0-9_-]+$"
tag*
Type
string
Required
Min Length
1
Max Length
64

Responses

Recorded changes

application/json
JSON
{
  
"events": [
  
  
{
  
  
  
"action": "string",
  
  
  
"version": 0,
  
  
  
"previous_version": 0,
  
  
  
"at": "string",
  
  
  
"by": {
  
  
  
  
"id": "string",
  
  
  
  
"name": "string",
  
  
  
  
"email": "string"
  
  
  
}
  
  
}
  
],
  
"has_more": true
}

Playground

Authorization
Variables
Key
Value

Samples

Remove a tag

DELETE
/v2/templates/{templateId}/tags/{tag}

Removes a tag, leaving the version it named untouched — versions are never deleted, so anything rendering by that version number keeps working. Anything rendering by the tag stops: <template>@<tag> names nothing once the tag is gone. removed is false when the template was not holding the tag.

Authorizations

BearerAuth

Your Papermill API key, sent as Authorization: Bearer <key>.

Type
HTTP (bearer)
or
ApiKeyHeader

Your Papermill API key. Equivalent to the bearer form.

Type
API Key (header: x-api-key)

Parameters

Path Parameters

templateId*
Type
string
Required
Min Length
1
Max Length
128
Pattern
"^(?!__.*__$)[A-Za-z0-9_-]+$"
tag*
Type
string
Required
Min Length
1
Max Length
64

Responses

Tag removed

application/json
JSON
{
  
"tag": "string",
  
"removed": true
}

Playground

Authorization
Variables
Key
Value

Samples

Example

Promote a version to production, then render through the tag. Every caller sending @production picks up the new version with no change at their end.

shell
set -e
curl -fsS -X PUT "https://api.papermill.io/v2/templates/$TEMPLATE_ID/tags/production" \
  -H "Authorization: Bearer $PAPERMILL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"version": 3}'

curl -X POST "https://api.papermill.io/v2/pdf?template_id=$TEMPLATE_ID@production" \
  -H "Authorization: Bearer $PAPERMILL_API_KEY" \
  -H "Content-Type: application/json" \
  -o report.pdf \
  -d '{"customer": "Acme Co"}'
python
import os
import requests

key = os.environ["PAPERMILL_API_KEY"]
template_id = os.environ["TEMPLATE_ID"]
auth = {"Authorization": f"Bearer {key}"}

requests.put(
    f"https://api.papermill.io/v2/templates/{template_id}/tags/production",
    headers=auth,
    json={"version": 3},
).raise_for_status()

pdf = requests.post(
    "https://api.papermill.io/v2/pdf",
    params={"template_id": f"{template_id}@production"},
    headers={**auth, "Content-Type": "application/json"},
    json={"customer": "Acme Co"},
)
pdf.raise_for_status()

with open("report.pdf", "wb") as f:
    f.write(pdf.content)
javascript
import fs from 'node:fs/promises'

const key = process.env.PAPERMILL_API_KEY
const templateId = process.env.TEMPLATE_ID
const auth = { Authorization: `Bearer ${key}` }

const tagged = await fetch(`https://api.papermill.io/v2/templates/${templateId}/tags/production`, {
  method: 'PUT',
  headers: { ...auth, 'Content-Type': 'application/json' },
  body: JSON.stringify({ version: 3 }),
})
if (!tagged.ok) throw new Error(`${tagged.status} ${tagged.statusText}`)

const pdf = await fetch(`https://api.papermill.io/v2/pdf?template_id=${templateId}@production`, {
  method: 'POST',
  headers: { ...auth, 'Content-Type': 'application/json' },
  body: JSON.stringify({ customer: 'Acme Co' }),
})
if (!pdf.ok) throw new Error(`${pdf.status} ${pdf.statusText}`)
await fs.writeFile('report.pdf', Buffer.from(await pdf.arrayBuffer()))

Rolling back is the same call with the previous version number.

Removing a tag

Deleting a tag leaves the version it named untouched, so anything rendering by that version number keeps working. Anything rendering by the tag stops: report@production names nothing once the tag is gone. Move a tag rather than removing it unless you mean to retire the name.

The history survives removal, so GET …/tags/{tag}/history still answers where the tag pointed and who moved it.