GET /v1/templates
Templates are per-account. A brand-new account — including a keyless trial — starts with the starter library already loaded.
GET https://api.galleyrender.com/v1/templatesGET https://api.galleyrender.com/v1/templates/:refDELETE https://api.galleyrender.com/v1/templates/:nameAuthorization: Bearer glr_sk_…GET /v1/templates
Section titled “GET /v1/templates”Lists every template on the account that has not been deleted, ordered by name. Takes no parameters.
Response
Section titled “Response”200 OK, { "object": "list", "data": [...] }. Each entry is the summary form: no schema,
no source.
| Field | Type | Description |
|---|---|---|
object | string | Always template. |
id | string | tpl_…. |
name | string | Lowercase, matches ^[a-z0-9][a-z0-9._-]{0,62}$. |
description | string | null | |
latest_version | number | The highest published version. |
created_at | string | ISO 8601. |
updated_at | string | ISO 8601. Moves when a new version is published. |
curl -sS https://api.galleyrender.com/v1/templates \
-H "Authorization: Bearer $GALLEY_API_KEY" // Node 22+. No dependencies — `fetch` is built in.
const res = await fetch("https://api.galleyrender.com/v1/templates", {
headers: {
authorization: `Bearer ${process.env.GALLEY_API_KEY}`,
},
});
const templates = await res.json();
if (!res.ok) throw new Error(templates.error.message);
console.log(templates); # Python 3.9+. Standard library only.
import json, os, urllib.request
req = urllib.request.Request(
"https://api.galleyrender.com/v1/templates",
headers={"Authorization": f"Bearer {os.environ['GALLEY_API_KEY']}"},
)
templates = json.load(urllib.request.urlopen(req))
print(templates) # No API key. The first call mints a 50-render trial.
curl -sS https://mcp.galleyrender.com/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_templates",
"arguments": {}
}
}' { "object": "list", "data": [ { "object": "template", "id": "tpl_3n8kq1w7v2md", "name": "invoice", "description": "Letter-size invoice with line items, totals, and payment terms.", "latest_version": 1, "created_at": "2026-09-16T13:58:22.410Z", "updated_at": "2026-09-16T13:58:22.410Z" }, { "object": "template", "id": "tpl_8w2mv4k9t1qp", "name": "og-card", "description": "1200x630 social card.", "latest_version": 2, "created_at": "2026-09-16T13:58:22.688Z", "updated_at": "2026-09-16T14:11:09.223Z" } ]}GET /v1/templates/:ref
Section titled “GET /v1/templates/:ref”Reads one version in full, including its JSON Schema and HTML source.
Request
Section titled “Request”| Parameter | In | Description |
|---|---|---|
ref | path | invoice for the latest version, invoice@3 to pin one. invoice@latest is the same as invoice. |
The reference is parsed at the last @, so a name containing dots and dashes is fine.
A version that is not a positive integer is an invalid_request, not a 404.
Response
Section titled “Response”200 OK. The summary fields above, plus:
| Field | Type | Description |
|---|---|---|
version | number | The resolved version number. |
ref | string | name@version. Pin this in anything you ship. |
engine | string | chromium or satori. |
schema | object | JSON Schema (draft 2020-12) for data. {} if the version has none. |
options | object | Default render options for this version. Per-request options are merged over them. |
example | unknown | null | An example payload, if the version ships one. |
source | string | The HTML + Liquid source. |
checksum | string | SHA-256 over engine, source, schema and options. It is the template half of the render cache key. |
message | string | null | The changelog line recorded with the version. |
version_created_at | string | ISO 8601. |
curl -sS https://api.galleyrender.com/v1/templates/invoice@1 \ -H "Authorization: Bearer $GALLEY_API_KEY"{ "object": "template", "id": "tpl_3n8kq1w7v2md", "name": "invoice", "description": "Letter-size invoice with line items, totals, and payment terms.", "latest_version": 1, "created_at": "2026-09-16T13:58:22.410Z", "updated_at": "2026-09-16T13:58:22.410Z", "version": 1, "ref": "invoice@1", "engine": "chromium", "schema": { "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Invoice", "type": "object", "required": ["invoice_number", "issued_on", "seller", "buyer", "line_items"], "additionalProperties": true, "properties": { "invoice_number": { "type": "string", "examples": ["INV-1042"] }, "issued_on": { "type": "string", "format": "date", "examples": ["2026-09-16"] }, "tax_rate": { "type": "number", "minimum": 0, "maximum": 1, "examples": [0.07] } } }, "options": { "page_size": "Letter", "margin": "0.5in", "print_background": true }, "example": { "invoice_number": "INV-1042", "issued_on": "2026-09-16" }, "source": "<html><head><style>@page { size: Letter; margin: 0.5in }</style></head>…", "checksum": "b2f0c8a1d34e5f67…", "message": "starter library", "version_created_at": "2026-09-16T13:58:22.410Z"}Read the schema before rendering a template you have not used. It is the contract for data, and
POST /v1/templates/:ref/validate will check a payload against it for free.
Unknown template
Section titled “Unknown template”{ "error": { "type": "not_found", "message": "Template `invioce` was not found on this account.", "docs_url": "https://galleyrender.com/docs/errors/not_found", "details": { "requested": "invioce", "available_templates": ["invoice@1", "og-card@2", "receipt@1"], "create_url": "https://galleyrender.com/docs/templates#create" } }}details.available_templates holds up to 25 entries, each already in name@version form.
DELETE /v1/templates/:name
Section titled “DELETE /v1/templates/:name”Soft-deletes a template. The row is marked deleted rather than removed.
| Parameter | In | Description |
|---|---|---|
name | path | The template name. A version suffix is accepted and ignored — delete acts on the whole template, not one version. |
curl -sS -X DELETE https://api.galleyrender.com/v1/templates/receipt \ -H "Authorization: Bearer $GALLEY_API_KEY"{ "object": "template", "id": "tpl_1v7mq4k8w2nt", "name": "receipt", "deleted": true}What a soft delete does and does not do:
Stops appearing in GET /v1/templates | yes |
| Can still be rendered | no — POST /v1/render returns not_found |
| Existing renders keep working | yes — stored files and their signed URLs are untouched |
| Version history is destroyed | no — rows are kept |
| The name becomes free again | no |
Errors
Section titled “Errors”| Type | Status | When |
|---|---|---|
authentication_error | 401 | Missing, unknown or revoked key. |
not_found | 404 | No such template on this account, or the template has no such version. |
invalid_request | 400 | The reference is malformed, e.g. invoice@0 or invoice@three. |