Templates
A body written once, sent many times.
Templates tools
| Tool | What it does |
|---|---|
| listTemplates | Every template on the active connection, with what each one expects. |
| getTemplate | One template by id or slug, with its published keys and its newest version. |
| createTemplate | Store a body, optionally publishing it so it can be sent immediately. |
| previewTemplate | Render one with values supplied, without sending it. |
| sendWithTemplate | Send a message built from a template, with props filled in. |
| getTemplateVersion | Read an older version, body included, without restoring it. |
| updateTemplate | Edit a template. A body edit lands in the draft, not in what sends. |
| publishTemplate | Publish the draft, which is what makes an edit reach the next message. |
| duplicateTemplate | Copy one into a new template, so a redesign leaves the live one alone. |
| replaceTemplateContent | Swap the body for a starter design or for another template. |
| restoreTemplateVersion | Copy an older version forward into the draft. |
| deleteTemplateVersion | Remove one revision. The live one and the draft are refused. |
| deleteTemplate | Delete a template and every version of it. |
| listTemplateStarters | The starter designs that ship with the product. |
| getTemplateStarter | One starter in full, with the document it would seed. |
| getTemplateAnalytics | Sends, opens and clicks for a template, broken down by version. |
| listTemplateSends | The individual messages a template sent, with opens and clicks. |
| listTemplateImages | The images uploaded for templates, newest first, each with the public url to put in a template. |
| uploadTemplateImage | Upload an image for templates in base64 and get its public url, fitted to a size every mail client shows. |
| listTemplateVersions | The versions of one template, newest first, a page at a time, with the one sends resolve to and the draft being edited. |
| renderTemplate | Render a design that is not saved yet, html or a block document with values, to check it before it is saved. |
| designTemplate | Design a new template from a brief. A designer builds it from every block the editor has and saves it as a draft. |
| editTemplateDesign | Change what a block template looks like or says from instructions, and leave the rest alone. The change lands in the draft. |
Templates belong to the CONNECTION, so these act on whichever mailbox setActiveConnection last named, and a template a colleague wrote is one of them.
A draft cannot be sent. previewTemplate renders one, sendWithTemplate refuses it with template_not_published, and that asymmetry is the point: a body nobody has published is a body nobody has approved.
Props are checked strictly on the way out. An unknown key or a missing required one refuses the send outright rather than mailing a blank where the order number should be, the one failure nothing downstream would report.
designTemplate and editTemplateDesign spend one AI action each and can take up to a minute. An image a client limited to some addresses cannot reach is left out, and the answer names it. In the app’s chat, both ask first unless you asked for them.
Reference
listTemplatesgetTemplatecreateTemplatepreviewTemplatesendWithTemplategetTemplateVersionupdateTemplatepublishTemplateduplicateTemplatereplaceTemplateContentrestoreTemplateVersiondeleteTemplateVersiondeleteTemplatelistTemplateStartersgetTemplateStartergetTemplateAnalyticslistTemplateSendslistTemplateImagesuploadTemplateImagelistTemplateVersionsrenderTemplatedesignTemplateeditTemplateDesign
listTemplates
Email templates on the active connection: a stored subject and body that a send fills in and reuses. Newest change first unless you sort otherwise. Reports whether each has a published version, which is what a send resolves to. A draft cannot be sent. Use search rather than listing everything and reading the names yourself: it matches the name, the slug, the description and the published subject. Use getTemplate for one in detail, including which version number is the published one.
Inputs
statusstring- One of
"draft""active""archived" searchstring- Up to 200 characters
sortstring- One of
"updated-newest""updated-oldest""created-newest""created-oldest""name""name-reversed" limitnumber- Default
25 cursorstring
Also available in
- API
GET /templates- TypeScript
nextmail.templates.list()nextmail.templates.listAll()nextmail.templates.iterate()- Python
templates.list()templates.list_all()templates.iterate()- Ruby
templates.listtemplates.list_alltemplates.iterate- PHP
templates->listtemplates->listAlltemplates->iterate- Go
Templates.ListTemplates.ListAllTemplates.Iterate- Java
templates().listtemplates().listAlltemplates().iterate- C#
Templates.ListAsyncTemplates.ListAllAsyncTemplates.IterateAsync
getTemplate
One template in detail, by id (tpl_…) or by slug: its subject, its engine, every prop and slot it declares, and its versions. Read this before sending. The props it lists are exactly the keys sendWithTemplate will accept, and it accepts no others: an unknown key is refused and a missing required one is refused, rather than sent as a blank.
Inputs
idstringRequired
Also available in
- API
GET /templates/{id}- TypeScript
nextmail.templates.get()- Python
templates.get()- Ruby
templates.get- PHP
templates->get- Go
Templates.Get- Java
templates().get- C#
Templates.GetAsync
createTemplate
Create a template and, by default, publish it so it can be sent. Give it ONE of: html (markup you rendered yourself, which is sanitised once, when published); document (the whole block design the visual editor uses, with every block kind, Section/Row/Column layout, styles, fonts and preview text, checked as it goes in, with every problem listed at once); or blocks (a quick flat list of Heading/Text/Button/Link/Img/Hr with no styling). Declare a prop for every value that changes per message and write {{key}} where it goes, in the subject or the body; a required prop missing at send time is refused rather than sent blank. Slots are the same mechanism for values the AUTHOR fills, with a default that renders when nobody overrides it. Start from a design rather than from nothing where you can: listTemplateStarters names the ones that ship with the product, and passing one as starter seeds the subject and the body. updateTemplate edits a template afterwards, publishTemplate makes an edit live, and deleteTemplate removes one.
Inputs
namestringRequired- 1 to 100 characters
descriptionstring- Up to 500 characters
subjectstringstarterstring- Up to 64 characters
htmlstringdocumentRecord<string, any> | stringThe whole block design the editor uses: {"preview": "...", "style": {...}, "fonts": [...], "body": [blocks], "props": [...], "slots": [...]}. A block is {"kind", "id", "style", "align", ...}: Section, Container, Row and Column hold children (a Row holds only Columns); Heading, Text, Markdown, Button, Link, CodeBlock and CodeInline hold text; Button and Link take href; Img takes src, alt, width and height; Hr is a divider. style is camelCase CSS. getTemplateVersion and getTemplateStarter return complete documents to copy the shape from.
blocksobject[]kindstringRequired- One of
"Heading""Text""Button""Link""Img""Hr" textstringhrefstringsrcstringaltstring
propsobject[]keystringRequiredlabelstringkindstring- One of
"text""url""image" requiredbooleandefaultstring- Can be null
slotsobject[]keystringRequiredlabelstringkindstring- One of
"text""url""image" defaultstring
publishboolean- Default
true
Also available in
previewTemplate
Render a template without sending it, so you can check your work first. Returns the subject and the body AS TEXT. The HTML a recipient would receive is a whole email document and is not readable here; the REST preview endpoint returns it if you need it. Lenient where a send is strict: a prop you left out is rendered blank and reported back, rather than refusing. Anything reported as unfilled WILL be refused by sendWithTemplate, so this is the cheap way to find out.
Inputs
idstringRequiredversioninteger- More than 0
propsRecord<string, any>slotsRecord<string, any>
Also available in
sendWithTemplate
Send a message built from a stored template. THIS SENDS IMMEDIATELY. There is no confirmation step and no approval prompt on this server. Nothing asks the person before the mail leaves, exactly as sendEmail here does not. Call previewTemplate first and read what it renders; that is the only check there is. It is also not idempotent: calling it twice sends twice, because deduplication is keyed to an API key and an MCP session has none. Omit version to send whatever is published now, or pin one. Props must match exactly what getTemplate lists. An unknown key or a missing required one is refused rather than sent as a blank. Name from: there is no default sender, so a send without one is refused; listWorkspaceMembers names the addresses and whole domains you reach. Set cancellableForSeconds to hold the message briefly; cancelEmail can stop it until that time runs out.
Inputs
idstringRequiredtoobject[]Required- At least one item
emailstringRequirednamestring
ccobject[]emailstringRequirednamestring
bccobject[]emailstringRequirednamestring
replyToobjectemailstringRequirednamestring
fromstringversioninteger- More than 0
propsRecord<string, any>slotsRecord<string, any>subjectstringcancellableForSecondsinteger- At least 0At most 900Default
0 tagsRecord<string, string>trackOpensbooleantrue adds an open pixel to this message and false leaves it out. Left out, the setting of the address it is sent from decides, and that is off unless the address turned it on. Set it only when the user asks to track or not to track.
trackClicksbooleantrue sends the links in this message through the tracking domain to count clicks and false leaves every link as written. Left out, the setting of the address it is sent from decides, and that is off unless the address turned it on. A link whose text is itself an address is never rewritten.
getTemplateVersion
One version of a template WITH ITS BODY, named by template id or slug and the version number getTemplate lists. This is the only way to read what an older version holds without changing anything. restoreTemplateVersion also reveals a body, but it moves the draft to do it, so reading version 3 that way costs you whatever you were editing. Read it here first, compare it with the draft, and restore only if you meant to. An html template comes back as the markup that was submitted, before the publish-time sanitiser; a blocks template comes back as its block tree. A long body is cut off at the end and says so.
Inputs
idstringRequiredversionintegerRequired- More than 0
Also available in
- API
GET /templates/{id}/versionsGET /templates/{id}/versions/{version}- TypeScript
nextmail.templates.listVersions()nextmail.templates.listAllVersions()nextmail.templates.iterateVersions()nextmail.templates.getVersion()- Python
templates.list_versions()templates.list_all_versions()templates.iterate_versions()templates.get_version()- Ruby
templates.list_versionstemplates.list_all_versionstemplates.iterate_versionstemplates.get_version- PHP
templates->listVersionstemplates->listAllVersionstemplates->iterateVersionstemplates->getVersion- Go
Templates.ListVersionsTemplates.ListAllVersionsTemplates.IterateVersionsTemplates.GetVersion- Java
templates().listVersionstemplates().listAllVersionstemplates().iterateVersionstemplates().getVersion- C#
Templates.ListVersionsAsyncTemplates.ListAllVersionsAsyncTemplates.IterateVersionsAsyncTemplates.GetVersionAsync
updateTemplate
Edit a template that already exists. Two kinds of field, and they behave differently. name, slug, description and status are metadata: they change in place and create no version. subject, html, blocks, props and slots are the BODY: the edit lands in the draft, and when the template has nothing left to edit (its head is published) a new draft numbered one higher is minted. Either way nothing a live send resolves moves until publishTemplate is called, which is what makes it safe to edit a template that is sending right now. Give one of html, document (the whole block design, every block kind and style, as getTemplateVersion returns it) or blocks (a flat list with no styling), never several. A field you leave out keeps what the head already had, so an edit to the subject alone keeps the body; props and slots, when sent, replace the whole list. Sending blocks replaces the block list and nothing else: the page settings the editor holds alongside it (preview text, web fonts, the Tailwind switch and the page style) are carried over from the version you are editing, so a template designed in the app does not lose its look to an edit made here. Read getTemplate first: the props it lists are what sends already pass, and dropping one makes those sends fail.
Inputs
idstringRequirednamestring- 1 to 100 characters
slugstring- 1 to 64 characters
descriptionstring- Up to 500 characters
statusstring- One of
"active""archived" subjectstringhtmlstringdocumentRecord<string, any> | stringThe whole block design the editor uses: {"preview": "...", "style": {...}, "fonts": [...], "body": [blocks], "props": [...], "slots": [...]}. A block is {"kind", "id", "style", "align", ...}: Section, Container, Row and Column hold children (a Row holds only Columns); Heading, Text, Markdown, Button, Link, CodeBlock and CodeInline hold text; Button and Link take href; Img takes src, alt, width and height; Hr is a divider. style is camelCase CSS. getTemplateVersion and getTemplateStarter return complete documents to copy the shape from.
blocksobject[]kindstringRequired- One of
"Heading""Text""Button""Link""Img""Hr" textstringhrefstringsrcstringaltstring
propsobject[]keystringRequiredlabelstringkindstring- One of
"text""url""image" requiredbooleandefaultstring- Can be null
slotsobject[]keystringRequiredlabelstringkindstring- One of
"text""url""image" defaultstring
expectedVersioninteger- More than 0
Also available in
publishTemplate
Publish a template's draft, which is what makes an edit reach the next message sent. Until this runs, sends keep resolving whatever was published before, so an edit nobody publishes changes nothing a recipient sees. Compiling happens here: a body that does not render is refused now, for you, rather than later for somebody reading their mail, and nothing is published when that happens. Publishing also sets the template back to active, so it reactivates an archived one. Calling it when the draft is already the published version returns it unchanged. Call previewTemplate first and read what it renders, and pass the version you read as expectedVersion so a draft somebody saved since is refused rather than published.
Inputs
idstringRequiredexpectedVersionintegerThe version getTemplate reported for the draft you checked.
More than 0
Also available in
duplicateTemplate
Copy a template into a new one: the same subject, body, props and slots, as a separate template with its own id and slug. The copy starts as a DRAFT whatever the source had published, so it cannot send until somebody publishes it, and nothing links the two afterwards. This is the safe way to try a redesign of a template that is sending in production: copy it, edit the copy, and leave the live one alone. It copies the HEAD, which is the unpublished draft when there is one. Leave name out and the source name is reused with a number appended.
Inputs
idstringRequirednamestring- 1 to 100 characters
Also available in
replaceTemplateContent
Throw away a template's design and put a starter design, or another template's design, in its place. The template keeps its id, slug, name, description and status, and live sends keep resolving the published version until somebody publishes, but the body it replaces is GONE unless that body had been published, in which case it is still in the version list. Name exactly one source: starter (a slug from listTemplateStarters) or fromTemplateId (another template here, whose published design is copied). The new design brings its own props and slots and replaces the declarations wholesale, so sends passing the old props can start being refused. Read the result before publishing. Over MCP this runs as soon as you call it, with nothing to confirm it.
Inputs
idstringRequiredstarterstring- Up to 64 characters
fromTemplateIdstringexpectedVersioninteger- More than 0
Also available in
restoreTemplateVersion
Bring an older version's body back as the current draft, which is how an edit somebody regrets is undone. The old version stays where it is in the list; its subject, body, props and slots are copied forward. A published head mints the next version, a draft head is overwritten, and nothing live moves until publishTemplate runs, so the restore is itself reversible until then. getTemplate lists the version numbers. Restoring the version that is already the head is refused, because it would do nothing.
Inputs
idstringRequiredversionintegerRequired- At least 1
expectedVersioninteger- More than 0
deleteTemplateVersion
Delete one version of a template and leave the template itself alone. It is for tidying a long version history, not for changing what sends. Three versions are refused: the live one, because sends resolve it; the head, because that is the draft being edited (restore an older version first and the old head becomes deletable); and the only version a template has, where deleteTemplate is the tool. Mail already sent is untouched, since a send keeps what it rendered, but anything pinning this version number starts failing and the number is never reused. There is no undo. Over MCP it runs as soon as you call it.
Inputs
idstringRequiredversionintegerRequired- At least 1
Also available in
deleteTemplate
Delete a template and every version of it, permanently. There is no undo and no trash. Mail already sent from it is unaffected, because each send stores the body it rendered, but anything still sending against this id or slug starts failing. When you are not certain nobody points at it, use updateTemplate with status archived instead: that takes it out of the way and is reversible. Over MCP this runs as soon as you call it, with nothing to confirm it.
Inputs
idstringRequired
Also available in
listTemplateStarters
The starter designs that ship with the product: ready-made bodies with a subject and their own props and slots. These are the same designs the web editor offers, not workspace data, so the list is the same for everybody. Pass a slug from here as starter to createTemplate to begin from one, or to replaceTemplateContent to re-skin a template that exists. Reach for one before writing a body by hand: a starter is a designed email, and blocks you invent are not.
Inputs
Takes no input.
Also available in
- API
GET /templates/startersGET /templates/starters/{slug}- TypeScript
nextmail.templates.listStarters()nextmail.templates.getStarter()- Python
templates.list_starters()templates.get_starter()- Ruby
templates.list_starterstemplates.get_starter- PHP
templates->listStarterstemplates->getStarter- Go
Templates.ListStartersTemplates.GetStarter- Java
templates().listStarterstemplates().getStarter- C#
Templates.ListStartersAsyncTemplates.GetStarterAsync
getTemplateStarter
One starter design in full, by the slug listTemplateStarters reports: its subject, its props and slots, and the whole document it would seed, page settings and web fonts included. Passing the slug as starter to createTemplate or replaceTemplateContent does the same seeding in one call and is the shorter route. Read it here when you want to change the design BEFORE it becomes a template, or to see what a starter actually looks like rather than guessing from its name. A long document is cut off at the end and says so.
Inputs
slugstringRequired- Up to 64 characters
Also available in
- API
GET /templates/startersGET /templates/starters/{slug}- TypeScript
nextmail.templates.listStarters()nextmail.templates.getStarter()- Python
templates.list_starters()templates.get_starter()- Ruby
templates.list_starterstemplates.get_starter- PHP
templates->listStarterstemplates->getStarter- Go
Templates.ListStartersTemplates.GetStarter- Java
templates().listStarterstemplates().getStarter- C#
Templates.ListStartersAsyncTemplates.GetStarterAsync
getTemplateAnalytics
How a template has actually performed: how many messages it sent in the window, how many of those were tracked at all, and how many were opened and clicked, with the same figures per version so a redesign can be compared with what it replaced. Rates are over what was TRACKED, never over everything sent, because a message sent with tracking off can never report an open and counting it would make every rate look worse than it is. The gap between sends and tracked is that mail, not missing data. Lifetime figures ignore the window.
Inputs
idstringRequireddaysinteger- At least 1At most 365Default
30
Also available in
listTemplateSends
The individual messages a template sent, newest first, rather than the totals getTemplateAnalytics reports. Each row names its recipients, the version that rendered it, where it was sent from, and whether it was opened or clicked. This is the tool for "who got the October one" and for finding the send behind a complaint. Filter by version to compare a redesign against what it replaced, or by opened and clicked to pull out the people worth following up. A message sent with tracking off reports no opens and no clicks; that is absent data, not a zero, and each row says which it is.
Inputs
idstringRequireddaysinteger- At least 1At most 365Default
30 searchstring- Up to 200 characters
versioninteger- More than 0
openedbooleanclickedbooleanpageinteger- At least 1Default
1
Also available in
listTemplateImages
The images uploaded for templates in this workspace, newest first, each with the public url to put in a template. Pass the cursor from the last line to read the next page.
Inputs
limitinteger- At least 1At most 120
cursorstring- 1 to 128 characters
Also available in
- API
GET /templates/images- TypeScript
nextmail.templates.listImages()nextmail.templates.listAllImages()nextmail.templates.iterateImages()- Python
templates.list_images()templates.list_all_images()templates.iterate_images()- Ruby
templates.list_imagestemplates.list_all_imagestemplates.iterate_images- PHP
templates->listImagestemplates->listAllImagestemplates->iterateImages- Go
Templates.ListImagesTemplates.ListAllImagesTemplates.IterateImages- Java
templates().listImagestemplates().listAllImagestemplates().iterateImages- C#
Templates.ListImagesAsyncTemplates.ListAllImagesAsyncTemplates.IterateImagesAsync
uploadTemplateImage
Upload an image for templates, the way the template editor does, and get the public url to use in a template. Pass the picture in base64 as image, with its type: image/png, image/jpeg, image/webp, image/gif, image/svg+xml, up to 5 MB. It is fitted into 1200 by 1800 pixels and stored in a form every mail client shows.
Inputs
imagestringRequiredThe image in base64, or as a data: URL.
1 to 7000000 characterscontentTypestringRequiredThe type of the image: image/png, image/jpeg, image/webp, image/gif, image/svg+xml.
1 to 100 characters
Also available in
listTemplateVersions
The versions of one template, newest first, a page at a time, as the version history of the template editor lists them: each one’s number, whether it is a draft or published, its engine, its subject and when it was published. Name the template by id (tpl_…) or slug. Says which version sends resolve to and which is the draft being edited. getTemplateVersion reads the body of one of them.
Inputs
idstringRequired- 1 to 128 characters
limitinteger- At least 1At most 100
cursorstring
Also available in
- API
GET /templates/{id}/versionsGET /templates/{id}/versions/{version}- TypeScript
nextmail.templates.listVersions()nextmail.templates.listAllVersions()nextmail.templates.iterateVersions()nextmail.templates.getVersion()- Python
templates.list_versions()templates.list_all_versions()templates.iterate_versions()templates.get_version()- Ruby
templates.list_versionstemplates.list_all_versionstemplates.iterate_versionstemplates.get_version- PHP
templates->listVersionstemplates->listAllVersionstemplates->iterateVersionstemplates->getVersion- Go
Templates.ListVersionsTemplates.ListAllVersionsTemplates.IterateVersionsTemplates.GetVersion- Java
templates().listVersionstemplates().listAllVersionstemplates().iterateVersionstemplates().getVersion- C#
Templates.ListVersionsAsyncTemplates.ListAllVersionsAsyncTemplates.IterateVersionsAsyncTemplates.GetVersionAsync
renderTemplate
Render a template design that is not saved, as the preview of the template editor does, without saving or sending anything. Give ONE of html (markup) or document (the whole block design), the subject, the props and slots it declares, and values to fill them with. Every {{key}} the subject or body uses has to be declared, as a save requires. Returns the subject and the body AS TEXT, and names every declared key left without a value. Use it to check a design before createTemplate or updateTemplate saves it. previewTemplate renders a saved template instead.
Inputs
subjectstring- Up to 998 characters
htmlstring- Up to 1000000 characters
documentRecord<string, any> | stringThe whole block design the editor uses: {"preview": "...", "style": {...}, "fonts": [...], "body": [blocks], "props": [...], "slots": [...]}. A block is {"kind", "id", "style", "align", ...}: Section, Container, Row and Column hold children (a Row holds only Columns); Heading, Text, Markdown, Button, Link, CodeBlock and CodeInline hold text; Button and Link take href; Img takes src, alt, width and height; Hr is a divider. style is camelCase CSS. getTemplateVersion and getTemplateStarter return complete documents to copy the shape from.
propsobject[]keystringRequiredlabelstringkindstring- One of
"text""url""image" requiredbooleandefaultstring- Can be null
slotsobject[]keystringRequiredlabelstringkindstring- One of
"text""url""image" defaultstring
valuesobjectpropsRecord<string, any>slotsRecord<string, any>
Also available in
designTemplate
Design a new email template and save it. Use this whenever the user asks you to create, make, build or design a template or an email design, whatever it is for: a newsletter, a launch, a welcome series, a receipt, an event invite. A designer builds it from every block the editor has (sections, rows and columns, headings, text, rich text, buttons, images, dividers, code), with a full palette, type and spacing, and it opens in the visual editor fully editable. Put everything the user asked for in the brief. It takes up to a minute. It is saved as a draft unless the user asked for it to go live, and a draft cannot be sent until publishTemplate. Never write template blocks yourself for this; describe what you want in the brief.
Inputs
namestringRequiredA short name for the template.
1 to 100 charactersbriefstringRequiredEverything the design must hold and look like: what it is for and who reads it, the sections in order, the words (the user's own text word for word when they gave it, otherwise what to say), brand colours and fonts, the tone, links, and which values change per recipient. Be specific and complete.
Not emptydescriptionstringOne line about what it is for.
Up to 500 charactersstarterstringA starter design to build on, by slug from listTemplateStarters, only when the user asked for one or it clearly fits.
Up to 64 charactersimageFileIdsstring[]Files to place in the design, like a logo, a product photo or a banner: the fileId of an image the user attached in this chat, or one listFiles found. Each becomes a mail safe image in the template.
publishbooleantrue only when the user asked for it to be live right away.
Defaultfalse
editTemplateDesign
Change the design or content of an existing template: restyle it, change colours, fonts or spacing, rewrite or translate its copy, add, move or remove sections, swap an image, fix a link, or redesign it completely. A designer applies the change to the real block tree and leaves everything else alone. Use it for every change to what a template looks like or says, from one word to a redesign. The change lands in the draft: live sends keep using the published version until publishTemplate. It takes up to a minute.
Inputs
idstringThe template to change, by id (tpl_...) or slug. Leave it out only when the user has a template open and means that one.
1 to 128 charactersinstructionsstringRequiredWhat to change, with every detail the user gave: the words, colours, which section. Quote the user's own text word for word.
Not emptyimageFileIdsstring[]Files to place in the design, like a logo, a product photo or a banner: the fileId of an image the user attached in this chat, or one listFiles found. Each becomes a mail safe image in the template.
expectedVersioninteger- More than 0
Google Workspace