Template Authoring Tools
These tools let an AI client read your workspace's Templates, write new ones and publish new versions of existing ones. They fall into three groups:
- Discovery — what a template document may contain and what your workspace lets it name. These mirror the Schema routes and
GET /v3/workspace. - Templates — reading, archiving, permissions, copying, creating and versioning templates, and moving running checklists onto a new version. These mirror the Templates routes.
- Drafts — a template document stored while it is still being written, changed a piece at a time and committed when it is ready. These mirror Drafts.
Every template write takes a template document: one JSON object describing the whole template — its settings, tags, permissions, parameters, tasks, fields, conditions and notifications. The format is documented once, in Template Documents; this page says what each tool does with it.
How to Read This Page
Every tool acts on the workspace your API key belongs to, as the member (or the workspace) the key acts as. There is no workspace argument. See Connecting.
- The Read/Write column in the summary table says whether a tool can change anything.
- Annotations are the hints a tool publishes to your client:
readOnlyHint,destructiveHintandidempotentHint. A hint a tool does not declare is left out of its definition, and the MCP specification tells a client to assume the cautious default in that case — that the tool may write, may be destructive and is not idempotent. See Tool Annotations. idempotencyKeyappears on the write tools that accept it. It is optional and at most 255 characters. If a call times out or its answer is lost, send it again with the same key and the same arguments: the first call's answer comes back, markedcheckflow.io/idempotentReplayin the result's_meta, instead of the work happening twice. The same key with different arguments is refused withCONFLICT, and so is a retry while the first call is still running. See Idempotency.- Refusals come back as an ordinary tool result with
isErrorset.structuredContentcarries the v3 error body —code,message,requestId,fieldand, for a template document,violations— and the text block summarises it, listing up to three violations. See Errors and How It Works. - A tool that returns nothing, such as a delete, answers with a result that is not flagged
isErrorand carries no data.
The six format discovery tools (every discovery tool except get_workspace_info), validate_template, validate_template_draft and get_commit_status are charged to the cheap rate-limit budget; every other tool on this page uses the standard budget. See Rate Limits.
How a Model Authors a Template
The tool descriptions and the server's standing instructions steer a model through the same loop. Knowing it helps when you write a prompt or read a transcript.
- Learn the names.
get_workspace_inforeturns the members, groups, tags and templates a document may name. Most authoring refusals are names that do not resolve, and this one call prevents them. - Read the guide once.
get_authoring_guideexplains, in prose, what to put in a document — including things a schema cannot say, such as that a task has no description and its instructions go in aTextfield. The same text is offered as the MCP resourcetemplate_authoring_guide(checkflow://guides/template-authoring,text/markdown), so you can attach it to a conversation instead. - Read the format.
get_template_schemagives the document envelope.list_content_typeslists the nineteen field types;describe_content_typeunfolds the one the model has chosen.list_condition_operatorsandlist_due_date_scenarioscover conditional logic and due dates. - Compose, then validate.
validate_templatechecks a document without writing anything. A document with problems is still a successful call: the model readsvalid,errorCount,warningCountand theviolations, fixes the document and validates again. - Publish.
- For a small template,
create_templatetakes the whole valid document in one call. - For anything larger, the model starts a draft with
create_template_draft, builds it up withapply_draft_operations,update_template_draftorreplace_template_draft— every answer carries the draft's current validation — checks it withvalidate_template_draft, then callscommit_template. The commit answersqueued; the model pollsget_commit_statusuntil it sayscommittedorfailed, and keeps therefMapthe committed answer carries.
- For a small template,
- Changing an existing template. The model does not compose a version document by hand. It seeds a draft with
create_template_draftandfromTemplateKey(the commit then publishes the next version), or callsexport_template, changes what is wrong and sends the result tocreate_template_version. Running checklists stay on their version untilupgrade_checklistsmoves them.
Tool Summary
| Tool | What it does | Read/Write |
|---|---|---|
get_authoring_guide | Returns the template authoring guide as markdown | Read |
get_template_schema | Returns the template document format as JSON Schema | Read |
list_content_types | Lists the nineteen field types and whether each can be tested by a condition | Read |
describe_content_type | Returns one field type's schema, an example and its condition operators | Read |
list_condition_operators | Lists the operators and effects a condition may use | Read |
list_due_date_scenarios | Lists the due date rules, directions and scenarios | Read |
get_workspace_info | Returns the members, groups, tags, templates and time zone a document may use | Read |
list_templates | Lists the workspace's templates | Read |
get_template | Returns one template with its tasks and fields | Read |
list_template_versions | Lists every version of one template | Read |
export_template | Writes a template out as a template document | Read |
set_template_archived | Archives or restores a template | Write |
list_template_permissions | Lists who can see and run a template's checklists | Read |
set_template_permissions | Replaces a template's permission set | Write |
validate_template | Checks a template document without writing anything | Read |
copy_template | Duplicates a template | Write |
create_template | Creates a template from a document | Write |
create_template_version | Publishes a new version of a template | Write |
list_checklist_upgrades | Lists running checklists that are not on a given version | Read |
upgrade_checklists | Queues running checklists to be rebuilt on a version | Write |
create_template_draft | Starts a draft | Write |
list_template_drafts | Lists the workspace's live drafts | Read |
get_template_draft | Returns one draft and its current validation | Read |
replace_template_draft | Replaces a draft's whole document | Write |
update_template_draft | Applies a JSON Merge Patch to a draft | Write |
apply_draft_operations | Adds, changes, removes or moves nodes in a draft | Write |
validate_template_draft | Checks a draft without writing anything | Read |
commit_template | Queues a draft to be written as a template | Write |
get_commit_status | Reports how a draft's commit is going | Read |
delete_template_draft | Deletes a draft | Write |
Discovery Tools
The seven tools below describe the template document format and the names your workspace lets a document use. Six of them return the same answer in every workspace; get_workspace_info is the one that is about your workspace. All seven are read-only.
get_authoring_guide
Returns the guide to writing a CheckFlow template, in prose: the order to work in, what tasks and fields are, how to choose between the nineteen field types, how conditions and due dates are written, and how to publish. The description tells the model to read it once before composing its first template document, because the schema tools say what a document may contain and the guide says what to put in one. The guide is around fifteen kilobytes of markdown and ends with a complete worked example that validates in any workspace.
If your client has already attached the template_authoring_guide resource, the model does not need to call this tool.
This tool takes no parameters.
- Returns: an object with
format(markdown) andcontent(the guide's text). See Schema. - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/schema/guide. - Example prompt: "Before you build anything, read CheckFlow's guide to writing templates."
get_template_schema
Returns the template document format as JSON Schema: settings, tags, permissions, parameters, tasks, fields and conditions. The model reads it before composing a document for create_template, create_template_version or a draft.
Fields appear here folded up, as the properties every field has, rather than as a union of all nineteen types — that union would be around a hundred kilobytes. describe_content_type is the same schema unfolded for one type. The schema is generated from the declarations the document reader validates against, so a property it lists is one the write tools accept. What it cannot say is what your workspace contains; that is get_workspace_info.
This tool takes no parameters.
- Returns: the JSON Schema of the template document. See Schema.
- Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/schema/document. - Example prompt: "What can a CheckFlow template document contain?"
list_content_types
Lists every type a field may be, each with a one-line summary and isTestable — whether conditional logic can branch on it. A field's type decides every other property it may carry, and the types are not guessable: ShortText and LongText are separate types, DropDown and MultiChoice differ by how many answers they take, and Members is an assignee picker. Eight of the nineteen types are testable, so a field that something else depends on should be one of those. For what each type is in the app, see Control Types.
This tool takes no parameters.
- Returns: an object with
types, an array oftype,summaryandisTestable. - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/schema/content-types. - Example prompt: "Which field types can I use on a template task, and which ones can drive conditional logic?"
{
"types": [
{
"type": "ShortText",
"summary": "One line of text the checklist's user types -- a name, a reference, a serial number.",
"isTestable": true
},
{
"type": "FileUpload",
"summary": "Files the checklist's user uploads -- receipts, photographs, a signed form. To hand them files instead, use a File field.",
"isTestable": false
}
]
}
The example shows two of the nineteen entries.
describe_content_type
Returns one field type in full: its JSON Schema, a complete example field and the operators a condition may test it with. The description tells the model to call this at the moment it chooses a type, because this is the only place a field's own properties — its label, a regex, a drop-down's items, a table's columns — are written down. A value outside the range the schema gives is one the document will be refused for. The example is ready to put into a task's fields array once its ref and label are changed.
A type that does not exist is refused, naming the nearest real one.
| Name | Type | Required | Description |
|---|---|---|---|
type | string | Yes | The content type, spelled as list_content_types spells it. Matched without regard to case. |
- Returns: an object with
type,summary,isTestable,operators(an array of operator names),schema(the type's JSON Schema) andexample(a complete field of this type). - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/schema/content-types/{type}. - Example prompt: "Show me every property a DropDown field can have."
list_condition_operators
Lists what a condition may say. A condition shows or hides a task or a field when a field's answer satisfies a test; these are the tests. Four work on any testable field and four comparisons only apply to dates. needsValue says whether an operator takes a value — has-no-value and has-any-value do not, and sending one is refused rather than ignored.
Pass contentType to ask about one type. A type that cannot be tested is not an error: the answer has isTestable false, an empty operator list and testableTypes beside it so the model can pick another. A word that names no type at all is refused.
The description also warns the model about ordering: a field's rules run in order each time its answer changes, and nothing returns to hiddenByDefault by itself, so a show or hide rule needs a reset rule ahead of it on the same field — has-any-value with the opposite effect. The authoring guide shows the pattern. See Conditional Logic for how conditions behave in a checklist.
| Name | Type | Required | Description |
|---|---|---|---|
contentType | string | No | Narrow the answer to one field type. Omit for every operator. |
- Returns: an object with
operators(each withoperator,needsValueanddatesOnly),testableTypesandeffects(show,hide). WithcontentType, alsotypeandisTestable. - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/schema/condition-operators?contentType=…. - Example prompt: "Which condition operators can I use on a Date field?"
{
"operators": [
{ "operator": "is", "needsValue": true, "datesOnly": false },
{ "operator": "is-not", "needsValue": true, "datesOnly": false },
{ "operator": "has-no-value", "needsValue": false, "datesOnly": false },
{ "operator": "has-any-value", "needsValue": false, "datesOnly": false },
{ "operator": "is-greater-than", "needsValue": true, "datesOnly": true },
{ "operator": "is-greater-than-or-equal-to", "needsValue": true, "datesOnly": true },
{ "operator": "is-less-than", "needsValue": true, "datesOnly": true },
{ "operator": "is-less-than-or-equal-to", "needsValue": true, "datesOnly": true }
],
"testableTypes": ["Date", "DropDown", "EmailInput", "LongText", "MultiChoice", "ShortText", "Website", "Members"],
"effects": ["show", "hide"]
}
list_due_date_scenarios
Lists everything a task's due date can be written with: the rules, the two directions and the scenarios. A due date is a rule plus, for some rules, something to count from — anchor on each rule says what kind of node that is (a task, a date field or a parameter), and is absent where the rule needs none. takesDirection says whether the rule can fall before its anchor; sending direction on a rule that does not take one is refused rather than ignored. The scenarios are a fixed vocabulary of calendar points, because that is what the scheduler evaluates. See Dynamic Due Dates for how due dates behave in a checklist.
This tool takes no parameters.
- Returns: an object with
rules(each withrule,anchorwhen it has one, andtakesDirection),directionsandscenarios. - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/schema/due-dates. - Example prompt: "How can I make a template task fall due two days before a date the user enters?"
{
"rules": [
{ "rule": "checklist-start-date", "takesDirection": false },
{ "rule": "previous-task-completed", "takesDirection": false },
{ "rule": "date-control", "anchor": "field", "takesDirection": true },
{ "rule": "task-completed", "anchor": "task", "takesDirection": false },
{ "rule": "parameter", "anchor": "parameter", "takesDirection": true }
],
"directions": ["before", "after"],
"scenarios": ["next-weekday", "next-monday", "first-day-of-next-month", "last-weekday-of-month", "last-day-of-quarter", "first-weekday-of-next-year"]
}
The example shows six of the twenty scenarios.
get_workspace_info
Returns the names your workspace lets a document use: its members, groups, tags and templates, and the time zone a date with no zone is read in. The schema tools say what a document may say; this says what it may name. A task's assignTo resolves against the members and groups here, a tags entry against the tags, and a Linked Checklist field's template against the templates — this is the same read the template writer makes, so a name in this answer is a name that resolves.
The description tells the model to send a member's name, which is the text the resolver matches on, and to fall back to the member's email address when name is absent (a member recorded with a surname and no first name). The answer is not paged, because a name missing from one page could not be read as the name not existing. The model is told to read it again rather than hold it across a long session.
This tool takes no parameters.
- Returns: an object with
teamId,teamName,region,timeZone,members,groups,tags(names) andtemplates(each withkeyandname). See The Workspace Object. - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/workspace. - Example prompt: "Who is in my CheckFlow workspace, and what tags do we already use?"
Template Tools
The thirteen tools below read and write templates. There is no update_template, rename_template or delete_template: a template's name and description belong to a version, so renaming one means publishing a new version, and nothing in CheckFlow deletes a template because checklists already running from it would lose what describes them. Archiving is the reversible alternative.
list_templates
Lists the workspace's templates — what a checklist can be started from. The description calls it the right first call before create_checklist or create_schedule. By default the answer has one row per template at its latest version, with archived templates left out, and all of them come back at once.
Each row carries the template's key and version, and the model is told to keep both: every version answers to the same key, so two reads of one key can return different content once somebody publishes. Rows carry name, description, version, isArchived, createdDateTime and createdBy (who published that version, absent when that person has left the workspace), and no tasks.
| Name | Type | Required | Description |
|---|---|---|---|
includeAllVersions | boolean | No | Return every version of every template rather than one row each. Default false. For one template's history, list_template_versions is the better call. |
includeArchived | boolean | No | Include archived templates. Default false. This is how an archived template's key is found again. |
- Returns: the standard list envelope (see Pagination) holding Template objects.
- Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/templates. - Example prompt: "Which templates do we have in CheckFlow?"
get_template
Returns one template with its tasks and their fields, at the latest version or at the version named. This is the shape a checklist is started against: every task and field carries its key, name and type, which is what create_checklist, set_task_fields and a webhook scope need. It is not the authoring shape — a field's configuration is not here, and export_template is the tool for that.
Some configuration is included because it is enforced when a field is answered: a Date field's mode (date, time or date and time), a Short Text field's regex and regexMessage, a Members field's selectionMode, and, for a field that reads its choices from a Data Set, its dataSet (the Data Set, view and display field by key and by name). Comparing latestVersion with version tells the model whether what it holds is current.
| Name | Type | Required | Description |
|---|---|---|---|
templateKey | string | Yes | The template's key, from list_templates. |
version | integer | No | The version to read, 1 or greater. Omit for the latest. A version that was never published is refused. |
- Returns: a Template Detail object, with its tasks and fields.
- Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/templates/{key}. - Example prompt: "What tasks and fields are in the Invoice Review template?"
list_template_versions
Lists every version of one template, newest first, with who published each and when. It is the only way to find out that versions other than the latest exist. An archived template still answers here. All versions come back at once.
| Name | Type | Required | Description |
|---|---|---|---|
templateKey | string | Yes | The template's key, from list_templates. |
- Returns: the standard list envelope holding Template Version objects.
- Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/templates/{key}/versions. - Example prompt: "Who has published versions of the Employee Onboarding template, and when?"
export_template
Writes a stored template out as the template document that would have made it: every field's configuration, every condition, every due date rule, and the permissions, tags and task and field ids. Anything it returns is accepted by create_template_version, which makes "read it, change one part, send it back" the way to edit a template. The description tells the model to start here before writing any version document, because a version composed by hand from the tool schema omits the field properties the schema does not show — and omits permissions and tags, which a version document removes by leaving them out.
A field that reads its choices from a Data Set comes back with a dataSet naming the Data Set, view and field, and no items. The document carries no key and no version.
| Name | Type | Required | Description |
|---|---|---|---|
templateKey | string | Yes | The template's key, from list_templates. |
version | integer | No | The version to export. Omit for the latest. Exporting an older version and sending it to create_template_version is how a template is rolled back — the old content is published as a new version. |
- Returns: a template document. See Template Documents.
- Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/templates/{key}/document. - Example prompt: "Export the Supplier Onboarding template so we can add a task to it."
set_template_archived
Moves a template into the Library's archive, or takes it back out. An archived template is left out of list_templates unless asked for, cannot start new checklists and cannot be scheduled; checklists already running from it carry on. It archives every version at once and is reversible. It sets the state asked for rather than toggling, so archiving an archived template succeeds and changes nothing.
| Name | Type | Required | Description |
|---|---|---|---|
templateKey | string | Yes | The template's key, from list_templates. |
isArchived | boolean | Yes | true to archive, false to restore. Required rather than defaulted, so neither direction happens by accident. |
- Returns: the Template Detail object.
- Annotations:
destructiveHintfalse,idempotentHinttrue. - REST equivalent:
POST /v3/templates/{key}/archiveto archive,DELETE /v3/templates/{key}/archiveto restore. - Example prompt: "Archive the old Supplier Onboarding template."
list_template_permissions
Lists who can see and run the checklists made from a template. These rules are about checklists, not about the template itself — none of them lets anybody edit the template, which is a matter of role. An empty list is a real answer: only Administrators see this template's checklists. The description tells the model to read this before set_template_permissions.
| Name | Type | Required | Description |
|---|---|---|---|
templateKey | string | Yes | The template's key, from list_templates. |
- Returns: the standard list envelope holding Template Permission objects, each with
assigneeType,assigneeId,nameandpermission. - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/templates/{key}/permissions. - Example prompt: "Who can run checklists from the Invoice Review template?"
set_template_permissions
Replaces a template's whole permission set. There is no way to add a single rule, so the model is told to call list_template_permissions first and send back the rules to keep alongside the ones it is changing — anything left out is removed. An empty array is allowed and leaves only Administrators seeing the checklists. Every assignee is checked against your workspace before anything is written.
| Name | Type | Required | Description |
|---|---|---|---|
templateKey | string | Yes | The template's key, from list_templates. |
permissions | array of objects | Yes | The complete set of rules, each assigneeType, assigneeId and permission. assigneeType is AllUsers, TeamMember or Group. AllUsers takes no assigneeId, and sending one is refused; TeamMember and Group need one, from list_members or list_groups. permission is RunAndView, ViewOnly, RunAndViewAssigned or ViewAssignedOnly. Naming the same assignee twice is refused. name is ignored. An empty array removes every rule. |
- Returns: the standard list envelope holding the permission rows as stored.
- Annotations:
destructiveHinttrue,idempotentHinttrue. - REST equivalent:
PUT /v3/templates/{key}/permissions. - Example prompt: "Let the Finance Team run Invoice Review checklists, and keep everyone who already has access."
validate_template
Checks a template document without writing anything. A document with problems is still a successful call — the violations are the answer, not an error — so the model reads valid, errorCount, warningCount and violations. The description calls it the working loop: compose, validate, fix, validate, create. It is also the only way to see warnings, because create_template accepts a document that has them and never mentions them.
Each violation has a path into the document (for example $.tasks[2].fields[1].regex), a code, a message, a severity of error or warning, and often a hint. Because a field's own properties do not appear in the tool's schema, the violations are how the model finds out whether it wrote them correctly.
| Name | Type | Required | Description |
|---|---|---|---|
document | object | Yes | The template document to check, in the shape create_template takes. |
templateKey | string | No | The template this document would become a new version of. Omit to check it as a new template. It changes the answer: a version is checked against what the stored template already has, so a task or field id the template does not own is found here. A key that names nothing is refused. |
- Returns: a Validation Result object with
valid,errorCount,warningCountandviolations. - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
POST /v3/templates/validate(with?forTemplate=for a version). - Example prompt: "Check this template document for problems before we publish it."
copy_template
Duplicates a template, and everything in it, as a template of its own. This is the way to copy a template: sending an export to create_template is refused, because a document carries no stored file behind an Image, Video or read-only File field. Here the template is read on the server, so the copy gets every part of it.
The copy has its own key, and so does every task, field, parameter and rule in it. Every condition, due date anchor, task tag, parameter binding, Data Set link, dynamic value binding and {{content.x}} token is repointed at the copy's own nodes, so nothing reaches back into the original. Images, videos and read-only files are shared rather than duplicated. An archived template can be copied, and the copy is live. A key acting as a member needs Edit on the Library folder the template is in; an Administrator key or a workspace key may copy anything.
| Name | Type | Required | Description |
|---|---|---|---|
templateKey | string | Yes | The key of the template to copy, from list_templates. |
name | string | Yes | The copy's name. It may match the original's. |
description | string | No | The copy's description. Omit to keep the original's; send an empty string for none. |
idempotencyKey | string | No | Retries this call safely. See How to Read This Page. |
- Returns: the new template's Template Detail object.
- Annotations:
destructiveHintfalse. - REST equivalent:
POST /v3/templates/{key}/copy. - Example prompt: "Make a copy of Employee Onboarding called Contractor Onboarding."
create_template
Creates a template from a document in one call — its tasks, their fields, the conditions that show and hide them, the rules that make them due and the custom notifications. The description tells the model to run validate_template first. A document with errors is refused with TEMPLATE_INVALID, and the refusal carries every violation with its path rather than stopping at the first. Nothing is written unless all of it is written, tags included.
Array order is display order: tasks appear in the order listed and so do fields within a task. Cross-references are refs — words the author chooses for a task or field and points at from a condition or a due date — and exist only inside the document. An id on any node is refused, because ids come from an export and describe a template that already exists: to duplicate that template, use copy_template; to publish a new version of it, use create_template_version.
A field's own configuration — a label, a regex, a drop-down's items, a table's columns — is written flat beside ref and type, and does not appear in the tool's published schema; describe_content_type documents it. A Dropdown, Multi-Choice, Sub-Tasks or Table field may read from a Data Set instead of listing items, by giving a dataSet (see Data Set Tools). A field filled in for the user carries valueFrom.
| Name | Type | Required | Description |
|---|---|---|---|
document | object | Yes | The template document. Only name and tasks are needed; settings, tags, permissions, parameters, conditions and notifications are optional. |
idempotencyKey | string | No | Retries this call safely. See How to Read This Page. |
- Returns: the new template's Template Detail object.
- Annotations:
destructiveHintfalse. - REST equivalent:
POST /v3/templates. - Example prompt: "Create a template called Invoice Review with tasks to check the supplier, match the purchase order and approve payment."
create_template_version
Publishes a new version of an existing template. The version number is assigned by the server. Checklists already running carry on against the version they were started from; new checklists use this one, and upgrade_checklists moves the running ones on.
The tool is marked destructive for one reason: permissions and tags are stored once per template rather than once per version, so a document that leaves them out removes them — from every version, including ones somebody else published. The description tells the model not to compose a version by hand, but to call export_template, change the part that is wrong and send the result back, keeping the id on every task and field it means to keep. An archived template is refused; restore it with set_template_archived first.
| Name | Type | Required | Description |
|---|---|---|---|
templateKey | string | Yes | The template to add a version to, from list_templates. |
document | object | Yes | The new version in full. Keep the id on every task and field that is the same as before; a task or field without one is new, and answers already given do not belong to it. Carry permissions, tags and each field's dataSet even when they are not changing — a field that keeps its id and drops its dataSet becomes a fixed list, and the answer warns about it. |
idempotencyKey | string | No | Retries this call safely. See How to Read This Page. |
- Returns: the Template Detail object at the new version.
- Annotations:
destructiveHinttrue. - REST equivalent:
POST /v3/templates/{key}/versions. - Example prompt: "Add a 'Check bank details' task after the first task of Supplier Onboarding and publish it as a new version."
list_checklist_upgrades
Lists a template's running checklists that are not on a given version — the latest unless version says otherwise — newest first, each with the version it is on beside the target. Archived checklists are left out, and so is a checklist the background worker is part-way through rebuilding, which makes this list the way to watch an upgrade land: a checklist leaves it when its rebuild finishes.
| Name | Type | Required | Description |
|---|---|---|---|
templateKey | string | Yes | The template's key, from list_templates. |
version | integer | No | The version to compare against, 1 or greater. Omit for the latest. An older version lists the checklists a rollback would touch. |
pageSize | integer | No | How many to return, 1 to 100. Any other value is read as 50. |
after | string | No | The nextCursor from the previous page. |
- Returns: the standard list envelope holding Upgrade Candidate objects, each with
key,name,url,status,startDateTime,versionandtargetVersion. - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/templates/{key}/upgrades. - Example prompt: "Which running Invoice Review checklists are still on an old version?"
upgrade_checklists
Queues running checklists to be rebuilt on a version of their template — the latest unless version says otherwise — carrying across every answer that still has somewhere to go. This is the same background worker as the app's own update button, and it can take minutes for a template with thousands of checklists, so the answer says what was queued and list_checklist_upgrades shows it landing.
A named checklist that is not in your workspace, or was started from another template, refuses the whole call. One already on the version, or archived, is left alone and reported under skipped. The tool is marked destructive because a rebuild is only undone by another upgrade; an older version is accepted, which is how a rollout is undone. The key needs to be one that may edit the template.
| Name | Type | Required | Description |
|---|---|---|---|
templateKey | string | Yes | The template's key, from list_templates. |
checklistKeys | array of strings | No | The checklists to move, by key, from list_checklist_upgrades. At most 500. Send this or all, not both. |
all | boolean | No | true to move every checklist list_checklist_upgrades would show. Send this or checklistKeys, not both. |
version | integer | No | The version to move them to, 1 or greater. Omit for the latest. |
- Returns: an Upgrade Result object with
templateKey,templateName,version,queued,checklistKeysandskipped(each withchecklistKeyandreason). - Annotations:
destructiveHinttrue,idempotentHinttrue. - REST equivalent:
POST /v3/templates/{key}/upgrades. - Example prompt: "Move every running Invoice Review checklist onto the latest version."
Draft Tools
A draft is a template document stored while it is still wrong. It has no page in the app, appears in nobody's Library, starts no checklists and notifies nobody. Unlike every other write, a draft write stores an invalid document and reports what is wrong with it; only commit_template refuses an invalid document. Drafts expire 30 days after their last change.
Every draft answer carries revision. Send it back as ifRevision on the next write to be refused with CONFLICT, rather than to overwrite, when somebody else has changed the draft in between. update_template_draft and apply_draft_operations are conditional even without it; replace_template_draft and commit_template are conditional only when it is sent. A draft that has been committed cannot be edited.
The Draft object returned by the draft tools has key, name, revision, basedOnTemplateKey (when seeded), document, validation (the same shape validate_template returns), applied (after operations), committedTemplateKey, committedVersion and committedDateTime (once committed), createdDateTime, updatedDateTime and expiresDateTime. See The Draft Object.
create_template_draft
Starts a draft. The description recommends it for anything larger than a handful of tasks, because it keeps the half-built template somewhere other than the model's own context. There are three ways to start: send nothing for an empty draft, a document you already have, or fromTemplateKey to seed it from an existing template.
Seeding exports the template into the draft and records the lineage, so committing the draft publishes a new version of that template rather than a second template with the same name. The description calls this the safe way to change an existing template, because the export carries the permissions, tags and task and field ids a hand-written version would drop. An empty draft is invalid, and its validation says so.
| Name | Type | Required | Description |
|---|---|---|---|
document | object | No | A template document to start from. Omit for an empty draft. Cannot be sent with fromTemplateKey. |
fromTemplateKey | string | No | A template to seed from, from list_templates. Makes the eventual commit a new version of that template. To copy a template's content without the lineage, send its export as document instead. |
fromVersion | integer | No | The version to seed from. Omit for the latest. Refused without fromTemplateKey. |
idempotencyKey | string | No | Retries this call safely. See How to Read This Page. |
- Returns: the Draft object, with its document,
revisionandvalidation. - Annotations:
destructiveHintfalse. - REST equivalent:
POST /v3/drafts. - Example prompt: "Start a draft of the Employee Onboarding template so we can rework the IT tasks."
list_template_drafts
Lists the workspace's live drafts, most recently changed first, without their documents. Expired drafts are not listed. Committed drafts are, for the seven days they are kept, carrying committedTemplateKey and committedVersion. The description tells the model to check this before starting a draft for something that may already be half-written.
This tool takes no parameters.
- Returns: the standard list envelope holding Draft objects without
document. - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/drafts. - Example prompt: "Are there any template drafts in progress?"
get_template_draft
Returns one draft: its document and what is wrong with it as it stands. The validation is worked out at the time of the call, so it accounts for a member who has since left or a seed template that has since gone. Reading does not extend the 30-day expiry.
| Name | Type | Required | Description |
|---|---|---|---|
draftKey | string | Yes | The draft, from create_template_draft or list_template_drafts. |
- Returns: the Draft object.
- Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/drafts/{key}. - Example prompt: "Show me the current state of the onboarding draft and what is still wrong with it."
replace_template_draft
Replaces a draft's whole document: what is stored afterwards is exactly what was sent, and anything left out is removed. The description reserves it for when the model is holding the entire document anyway — apply_draft_operations changes one task without resending the rest, and update_template_draft changes the name, description, settings, tags or permissions without resending any tasks. The document is not checked before it is stored; the answer says what is wrong with it.
| Name | Type | Required | Description |
|---|---|---|---|
draftKey | string | Yes | The draft to replace. |
document | object | Yes | The whole template document. |
ifRevision | integer | No | The revision you last read. Optional here; send it to be refused with CONFLICT if somebody else has written since. |
- Returns: the Draft object with its new
revisionandvalidation. - Annotations:
destructiveHintfalse,idempotentHinttrue. - REST equivalent:
PUT /v3/drafts/{key}(the revision goes inIf-Match). - Example prompt: "Replace the draft with this corrected document."
update_template_draft
Changes part of a draft's document with a JSON Merge Patch (RFC 7386): an object shaped like the document naming only what changes. Three rules apply — an object recurses, so {"settings":{"displayComments":false}} changes one switch; a null removes the member it names; and everything else replaces, arrays included. Because a tasks array in the patch replaces every task, the description limits this tool to the name, description, settings, tags and permissions, and sends the model to apply_draft_operations for anything inside tasks, fields, parameters, conditions or notifications.
A property the document has no word for is dropped rather than stored, so the model is told to read the document in the answer rather than assume the patch landed. The patch argument is the one free-form object on this page: its schema says only "object", because the difference between a member left out and a member sent as null is what the format rests on.
| Name | Type | Required | Description |
|---|---|---|---|
draftKey | string | Yes | The draft to change. |
patch | object | Yes | The merge patch, carrying only the members that change. |
ifRevision | integer | No | The revision you last read. Without it, the patch is checked against the revision the request itself read. |
- Returns: the Draft object with its new
revisionandvalidation. - Annotations:
destructiveHintfalse,idempotentHinttrue. - REST equivalent:
PATCH /v3/drafts/{key}(the revision goes inIf-Match). - Example prompt: "Rename the draft to Employee Onboarding (2026) and tag it q3-audit."
apply_draft_operations
Changes the parts of a draft a patch cannot reach — one task of forty, a field on it, a parameter, a condition, a notification. Operations are applied in order and all-or-nothing: if one is refused, none of the ones before it is stored, and the refusal names which operation and why.
There are nineteen operations:
| Node | Operations |
|---|---|
| Task | add_task, update_task, remove_task, move_task |
| Field | add_field, update_field, remove_field, move_field |
| Parameter | add_parameter, update_parameter, remove_parameter |
| Condition | add_condition, update_condition, remove_condition |
| Notification | add_notification, update_notification, remove_notification |
| Document | set_settings, set_permissions |
Nodes are addressed by ref. Give a ref on an add and a condition in the same call can point at it; leave it out and one is made up and reported back in applied. A ref is unique across the whole document. Removals do not cascade: a removed task leaves conditions pointing at nothing, and those arrive as violations on the answer. The tool is not idempotent — the same add sent twice adds two nodes — which is why it takes an idempotencyKey.
| Name | Type | Required | Description |
|---|---|---|---|
draftKey | string | Yes | The draft to change. |
operations | array of objects | Yes | The operations, applied in order. Each has op and ref. task names the owning task — required by add_field, and on move_field moves the field to another task. after or before (not both) places a task or field among its siblings; there is no index, and before the first node is how to say "first". A move must give one of them. value is the new node on an add_, a merge patch on an update_, the whole new value on set_settings and set_permissions, and not taken by remove_ and move_. |
ifRevision | integer | No | The revision you last read. Without it, the operations are checked against the revision the request itself read. |
idempotencyKey | string | No | Retries this call safely. See How to Read This Page. |
- Returns: the Draft object with its new
revision,validationandapplied(each entry theopand therefit acted on or created). - Annotations:
destructiveHintfalse,idempotentHintfalse. - REST equivalent:
POST /v3/drafts/{key}/operations. - Example prompt: "In the onboarding draft, add a Short Text field for the laptop serial number to the 'Order the laptop' task."
validate_template_draft
Checks a draft as it stands without writing anything — the same validation every draft answer carries, asked for on its own. The description recommends it before commit_template when a draft has been sitting for a while, because the answer is about now: an assignee a task named may have left. A draft with problems is still a successful call. It does not extend the expiry.
| Name | Type | Required | Description |
|---|---|---|---|
draftKey | string | Yes | The draft to check. |
- Returns: a validation result with
valid,errorCount,warningCountandviolations. - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
POST /v3/drafts/{key}/validate. - Example prompt: "Is the onboarding draft ready to publish?"
commit_template
Turns a draft into a template. This is the gate: a document with errors is refused with TEMPLATE_INVALID, every violation is named, and the draft is left exactly as it was so it can be fixed and committed again. The draft decides what is made — a draft seeded with fromTemplateKey publishes the next version of that template, and any other draft makes a new template. That is why the tool is marked destructive: a version publish rewrites the permissions and tags stored once per template.
The writing is queued rather than done while the model waits, because a large template can take longer to write than a request may last. The answer's status is queued (or running); the model then calls get_commit_status until it says committed or failed. Calling commit_template again is safe — a second call answers the same receipt with isReplay true rather than making a second template, and the draft is kept for seven days after it commits so this stays true. The committed answer carries refMap, which maps the document's refs to the real task and field keys; the model is told to keep it.
| Name | Type | Required | Description |
|---|---|---|---|
draftKey | string | Yes | The draft to commit. |
ifRevision | integer | No | The revision you last read. Send it to be refused with CONFLICT rather than publish a template built from somebody else's edit. |
- Returns: a commit receipt with
status(queued,running,committedorfailed),templateKey,version,isNewTemplate,isReplay,queuedDateTime,committedDateTime,errorandrefMap, each present when it applies. See The Commit Object. - Annotations:
destructiveHinttrue,idempotentHinttrue. - REST equivalent:
POST /v3/drafts/{key}/commit. - Example prompt: "Publish the onboarding draft."
commit_template takes no idempotencyKey. It is safe to retry on its own terms: a repeated commit answers with the existing receipt.
get_commit_status
Reports how a draft's commit is going, or how it went. The model calls it after commit_template answers queued or running, a second or two apart, until status is committed or failed.
committedcarriestemplateKey,versionandrefMap.failedcarrieserror.codeanderror.message, anderror.violationswhen the document stopped being valid between being accepted and being written — for example, something it named was deleted in the meantime. The model fixes the draft and commits again.COMMIT_INTERRUPTEDas the error code means the attempt may have written a template before it stopped. The description tells the model to look in the Library for a template made from this draft before committing again.notStartedmeans nobody has committed this draft; it is not an error.
It does not extend the draft's expiry.
| Name | Type | Required | Description |
|---|---|---|---|
draftKey | string | Yes | The draft whose commit you are waiting on. |
- Returns: the commit receipt described under
commit_template. - Annotations:
readOnlyHinttrue,idempotentHinttrue. - REST equivalent:
GET /v3/drafts/{key}/commit. - Example prompt: "Has the onboarding template finished publishing?"
delete_template_draft
Deletes a draft. Nothing brings it back, and its document exists nowhere else unless it was committed. A committed draft can be deleted too, which gives up the seven-day receipt but not the template it made. Deleting a draft that is already gone is refused with DRAFT_NOT_FOUND rather than answered as a second success. Drafts expire on their own after 30 days, so there is no need to tidy up.
| Name | Type | Required | Description |
|---|---|---|---|
draftKey | string | Yes | The draft to delete. |
idempotencyKey | string | No | Retries this call safely. See How to Read This Page. |
- Returns: nothing.
- Annotations:
destructiveHinttrue,idempotentHintfalse. - REST equivalent:
DELETE /v3/drafts/{key}. - Example prompt: "Throw away the onboarding draft — we won't use it."
A deleted draft cannot be recovered. If it was never committed, its document is gone.
Related Pages
- Template Documents — the full template document format every authoring tool reads and writes.
- Drafts — the REST routes behind the draft tools, including
If-Matchand the commit's 202 flow. - Data Set Tools — where the names come from when a Dropdown or Table field reads from a Data Set.
- Template Versioning — how versions behave for the people running checklists in the app.
- How It Works — how tool results, refusals and idempotency keys work across the whole MCP server.