Managing templates via the API
The Flow Templates API lets you manage page and ballot templates programmatically — list, create, update, clone, and more — without using the UI.
All examples below use cURL. Replace YOUR_API_TOKEN with your API key and https://app.example.com with your instance URL.
How fields work
Fields are the core of what makes a template reusable. A template's body_html contains Liquid tags like {{ template.heading }}, and the fields array defines what those tags are — their type, label, default value, and how they appear in the page builder.
When someone creates a page from your template, each field becomes an editable input. The values they enter get substituted into the HTML via Liquid at render time.
Example: a template with fields
Here's a complete template that has a heading, an intro paragraph, and an optional hero image:
Body HTML:
<div class="header">
<h1>{{ template.heading }}</h1>
</div>
<div class="content">
{% if template.hero_image != blank %}
<div class="hero">{{ template.hero_image }}</div>
{% endif %}
<p class="intro">{{ template.intro_text }}</p>
<surveyform></surveyform>
</div>Fields:
[
{
"slug": "heading",
"label": "Page Heading",
"question_type": "text",
"wysiwyg": true,
"default_value": "Take our survey",
"translatable": true,
"show_in_wizard": true
},
{
"slug": "hero_image",
"label": "Hero Image",
"question_type": "image",
"image": true,
"required": false,
"show_in_wizard": true
},
{
"slug": "intro_text",
"label": "Introduction",
"question_type": "paragraph",
"wysiwyg": true,
"default_value": "Thanks for taking the time to fill out our survey.",
"translatable": true
}
]Notice how each field's slug matches a {{ template.slug }} tag in the HTML. The heading field has wysiwyg: true so it can be edited inline in the page builder preview. The hero_image field is optional (required: false) and the HTML uses a Liquid {% if %} block to hide it when empty.
Field properties
Each field requires:
slug— unique identifier, must be snake_case (this is what you reference in HTML as{{ template.slug }})label— display name shown when editingquestion_type— one of:text,url,paragraph,select,checkbox,image
Common optional properties:
default_value— pre-filled value when a page is created from this templatewysiwyg— iftrue, the field is editable directly in the page builder previewsetup— iftrue, shown in the page builder's setup tab instead of the editorshow_in_wizard— iftrue, shown in the initial page creation wizardtranslatable— iftrue, the value can differ across languagesrequired— whether the field must be filled in (default:true)image— iftrue, the value is rendered as an imagedescription— help text shown when editing the fieldoptions— forselectfields, an array of{ "value": "...", "label": "..." }choices
Field types
| Type | Description | Example use |
|---|---|---|
text | Single-line text input | Headings, button labels |
url | Single-line URL input | Links, redirect URLs |
paragraph | Multi-line text input | Intro copy, descriptions |
select | Dropdown with options | Theme picker, layout variants |
checkbox | Boolean toggle | Show/hide optional sections |
image | Image uploader | Hero images, logos |
Using fields in HTML with Liquid
Reference a field value: {{ template.field_slug }}
Conditionally show content based on a checkbox or optional field:
{% if template.show_disclaimer != blank %}
<div class="disclaimer">Terms and conditions apply.</div>
{% endif %}Branch on a select field value:
{% if template.layout == 'wide' %}
<div class="content-wide">...</div>
{% else %}
<div class="content-narrow">...</div>
{% endif %}See the Building page and ballot templates guide for the full HTML/CSS/Liquid reference.
API endpoints
Fetching a template
curl -H "Authorization: Token YOUR_API_TOKEN" \
"https://app.example.com/api/flow_templates/42"Returns the full template including body_html, styles_css, head_html, and fields.
Searching templates
curl -H "Authorization: Token YOUR_API_TOKEN" \
"https://app.example.com/api/flow_templates/search?query=survey"Creating a template
curl -X POST \
-H "Authorization: Token YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
"https://app.example.com/api/flow_templates"Creates a blank template. Use the update endpoint to add content.
Updating a template
This is the main endpoint for setting HTML, CSS, and fields:
curl -X PUT \
-H "Authorization: Token YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"flow_template": {
"name": "Branded Survey",
"styles_css": ".template-body { font-family: Arial; } .header { background: #2c3e50; color: white; padding: 2rem; text-align: center; }",
"body_html": "<div class=\"header\"><h1>{{ template.heading }}</h1></div><div class=\"content\"><surveyform></surveyform></div>",
"fields": [
{
"slug": "heading",
"label": "Page Heading",
"question_type": "text",
"wysiwyg": true,
"default_value": "Take our survey",
"translatable": true
}
]
}
}' \
"https://app.example.com/api/flow_templates/42"Other endpoints are available for cloning, archiving, restoring, and deleting templates — see the API reference for details.
Updated 2 months ago
