Templates

Versioned templates with variables, referenced by `templateKey` (`publiq.templates`).

The templates resource covers a versioned template lifecycle: create (with html/subject/text and variables), fetch, list, preview a saved version and, for the AI builder, render or save from a json-render SPEC.

Method reference

templates.create

templates.create(params) → Promise<Template>

Creates a versioned template from HTML (with interpolated variables). Automatically generates a readable key and the template's first version.

Parameters
ParameterTypeDescription
nameRequiredstringTemplate name. Must be unique within the organization.
htmlRequiredstringTemplate HTML body. May contain {{ variables }} interpolated on send or preview.
subjectOptionalstringDefault subject for the template. May also contain variables.
textOptionalstringPlain-text alternative to html (fallback and better deliverability).
engineOptionalstringRender engine for the variables (e.g. handlebars). If omitted, uses the organization default.

Returns: The created template — includes the auto-generated key and its first version.

const template = await publiq.templates.create({
name: 'welcome-email',
subject: 'Welcome, {{ first_name }}!',
html: '<h1>Hi {{ first_name }}</h1><p>Welcome to {{ company }}.</p>',
text: 'Hi {{ first_name }}, welcome to {{ company }}.',
});
console.log(template.id, template.key); // "tpl_...", "welcome-email"
The key (readable slug, e.g. welcome-email) can be used in Emails (emails.send({ templateKey })) and in Broadcasts (broadcasts.create({ templateId })). Variables use {{ snake_case }} — see Variables.

templates.get

templates.get(id) → Promise<Template>

Fetch a template details by id, including versions[] and the readable key.

Parameters
ParameterTypeDescription
idRequiredstringTemplate ID (returned by templates.create).

Returns: The template with its version history (versions[]) and key. 404 if it does not exist in the organization.

const template = await publiq.templates.get('tpl_123');
console.log(template.key, template.versions.length);
The key returned here is the same one accepted by emails.send({ templateKey }) and broadcasts.create({ templateId }) — see Emails and Broadcasts.

templates.list

templates.list({ limit?, after? }) → Promise<TemplateList>

List the organization templates, newest first, cursor-paginated. Each item is a summary with version_count.

Parameters
ParameterTypeDescription
limitOptionalnumberItems per page (default 20, max 100).
afterOptionalstringCursor: id of the last item on the previous page.

Returns: List envelope { object: "list", data: TemplateSummary[] }. Use the last item id as after on the next call.

const { data } = await publiq.templates.list({ limit: 50 });
// next page:
const next = await publiq.templates.list({ after: data[data.length - 1].id });
Listing is cursor-paginated: iterate by passing the last item id in after until data comes back empty. See Errors & pagination.

templates.preview

templates.preview(id, { version? }) → Promise<TemplatePreview>

Renders a saved template version with its variables resolved, for visual review before sending.

Parameters
ParameterTypeDescription
idRequiredstringTemplate ID.
versionOptionalstringVersion to preview. If omitted, uses the latest version.

Returns: A preview { object: "template_preview", subject, html } with the subject and HTML already rendered.

const preview = await publiq.templates.preview('tpl_123', { version: '2' });
console.log(preview.subject, preview.html);

templates.render

templates.render(params) → Promise<TemplateRender>

Renders a json-render SPEC ({ root, elements, state }) on the fly, without persisting anything — this is the live preview used by the AI builder.

Parameters
ParameterTypeDescription
specRequiredobjectA json-render SPEC — { root, elements, state } — describing the email element tree.

Returns: { object: "template_render", html, text } — rendered result, not saved.

const spec = {
root: 'body',
elements: {
  body: { type: 'container', children: ['heading'] },
  heading: { type: 'text', content: 'Hi {{ first_name }}' },
},
state: {},
};
const rendered = await publiq.templates.render({ spec });
console.log(rendered.html);
render and fromSpec power the AI builder and require the ai_builder plan feature. render is a non-persisting preview; use templates.fromSpec to save the result as a new template version.

templates.fromSpec

templates.fromSpec(params) → Promise<Template>

Renders a json-render SPEC and saves the result as a new template (or new version), with an auto-generated key.

Parameters
ParameterTypeDescription
nameRequiredstringTemplate name. Must be unique within the organization.
specRequiredobjectA json-render SPEC — { root, elements, state } — the same structure used in templates.render.
subjectOptionalstringTemplate subject.

Returns: The template created from the rendered SPEC, with an auto-generated key.

const template = await publiq.templates.fromSpec({
name: 'newsletter-july',
subject: 'Your July newsletter',
spec,
});
console.log(template.key);
fromSpec (Python: from_spec) requires the ai_builder plan feature, same as render. Unlike render, here the result is saved as a template.

Examples show Node, Python and PHP. In Python methods are snake_case (e.g. cancel_run, from_spec) and take a dict; in PHP they are camelCase and take an associative array. Body keys are always camelCase (templateKey, firstName, scheduledAt) — API responses come back in snake_case.

Templates — Publiq Docs