Skip to content

The email format

Every Flyanote email is one JSON document. The editor, the API, AI drafts, and the compiler all read and write the same format, so an email you build in one works in the others. The document says what the email holds; your brand kit says how it looks. We turn the two into HTML that works across email clients.

This page describes version 1.1. Versions before 1.0 are drafts and may still change. The tables, limits, and errors below are generated from the format itself.

The schema

The format is published as a JSON Schema (draft 2020-12). Point your validator or your editor at it, and set schema_version in every document. The schema checks a document's structure: its fields, types, lengths, and patterns. The rules across fields, such as unique ids or a table's cells, run when you save or validate, and each refusal is one of the error codes below, so a document the schema accepts can still be refused. A few checks need your account, such as whether a brand kit token or an uploaded image exists.

Under llm/ are the flatter profiles an AI model writes, a whole draft (.draft) or a change to one (.patch). They have versions of their own, and each says which version of the format it expands into. index.json lists every version and its files.

The document

A document has a schema_version, a meta object, optional settings, and its sections, top to bottom. Every object is closed: a property the format doesn’t have is an error, never ignored. Names are snake_case.

The document

An email, as the editor, the API, and AI write it. This schema checks its structure: shapes, types, lengths, and patterns. The rules across properties (ids, widths, a table’s cells, the footer, loop scopes, and Liquid) are the API’s validation, whose error codes are listed at https://flyanote.com/docs/email-format, so a document this schema accepts may still be refused.

PropertyTakes
schema_version (required)"1.1"
meta (required)Meta
settingsSettings
sections (required)a list of up to 100: ColumnsSection, GridSection, HeroSection or HtmlSection

meta

PropertyTakes
subject (required)text, up to 200 characters
preheadertext, at least 1 and up to 200 characters
lang (required)text, up to 35 characters
dirone of "ltr" or "rtl"
category (required)one of "transactional" or "marketing"
variablesa list of up to 500: text, up to 300 characters
provenanceProvenance

category sets the rules. Marketing mail gets the footer the law requires, with your organization’s name, its postal address, and an unsubscribe link, plus the unsubscribe headers inboxes look for. Transactional mail, like a receipt, has no unsubscribe link, and shows your name and address unless its footer block turns them off. variables is worked out on every save from the merge tags the email uses; anything you send there is replaced.

settings

PropertyTakes
widtha whole number from 480 to 700
brandtext. The brand kit this email uses, by its id (kit_…). Absent, the email follows the account’s default brand, whichever that is when it’s built.
palettetext. One of the brand kit’s palettes, by id. Absent, main.
themetext. One of the palette’s themes: light (its colors as they stand), dark (its dark values), or the id of one of its themes. Absent, light.
kit_versiona whole number from 1 to 9,007,199,254,740,991. The version of the brand kit this email was made against: one pin covers the brand, its palette, and its theme. Needs brand, since a version means nothing without its kit. Absent, the email follows the kit’s newest version.
backgroundColor
content_backgroundColor
colorColor
link_colorColor
link_underlinetrue or false
font_headingFont
font_bodyFont
mobilean object with h1, h2, h3, body, button, footer, side_padding and buttons_full_width
darkan object with background, content_background, color and link_color

Sections

A section is a full-width band of the email. Its kind says what it is: columns side by side, a grid of items, a hero over a background image, or your own HTML.

columns section

PropertyTakes
kind (required)"columns"
id (required)an id
labeltext, at least 1 and up to 60 characters
provenanceProvenance
columns (required)a list of up to 4: Column
widthsa list of up to 4: a whole number from 15 to 100
mobilean object with stack and reverse
styleSectionStyle

grid section

PropertyTakes
kind (required)"grid"
id (required)an id
labeltext, at least 1 and up to 60 characters
provenanceProvenance
per_row (required)one of 2, 3 or 4
mobilean object with per_row
gapSpacing
items (required)a list of up to 24: GridItem
styleSectionStyle

hero section

One column over a background image.

PropertyTakes
kind (required)"hero"
id (required)an id
labeltext, at least 1 and up to 60 characters
provenanceProvenance
blocks (required)a list of up to 8: TextBlock, ImageBlock, ButtonBlock, DividerBlock, SpacerBlock or LogoBlock
style (required)HeroStyle

html section

A whole section of the customer’s own HTML with Liquid.

PropertyTakes
kind (required)"html"
id (required)an id
labeltext, at least 1 and up to 60 characters
provenanceProvenance
html (required)text, at least 1 and up to 100,000 characters
styleHtmlSectionStyle

A column

PropertyTakes
id (required)an id
blocks (required)a list of up to 50: TextBlock, ImageBlock, ButtonBlock, DividerBlock, SpacerBlock, SocialBlock, LogoBlock, FooterBlock, HtmlBlock, RepeatBlock or TableBlock
styleColumnStyle

Blocks

Blocks hold the content, and a block’s type says what it is. Columns take every block. Hero sections take text, image, button, divider, spacer and logo. Grid items and repeats take text, image, button, divider and spacer. A repeat can’t hold another repeat. The footer block goes in the last section, at most once.

text block

PropertyTakes
type (required)"text"
id (required)an id
provenanceProvenance
lines (required)a list of up to 200: ParagraphLine, HeadingLine, BulletLine, NumberLine or QuoteLine
styleTextStyle

image block

PropertyTakes
type (required)"image"
id (required)an id
provenanceProvenance
src (required)Src
alttext, up to 300 characters
decorativetrue
widthtext
hrefHref
styleImageStyle

button block

PropertyTakes
type (required)"button"
id (required)an id
provenanceProvenance
label (required)text, up to 80 characters
href (required)Href
variantone of "fill" or "outline"
widthtext
styleButtonStyle

divider block

PropertyTakes
type (required)"divider"
id (required)an id
provenanceProvenance
styleDividerStyle

spacer block

PropertyTakes
type (required)"spacer"
id (required)an id
provenanceProvenance
height (required)Spacing
styleSpacerStyle

social block

PropertyTakes
type (required)"social"
id (required)an id
provenanceProvenance
networks (required)a list of up to 12: an object with network and href
icon_styleone of "color", "dark" or "light"
icon_sizetext
styleSocialStyle

html block

The customer’s own HTML with Liquid, linted. Not editable visually.

PropertyTakes
type (required)"html"
id (required)an id
provenanceProvenance
html (required)text, at least 1 and up to 50,000 characters

repeat block

PropertyTakes
type (required)"repeat"
id (required)an id
provenanceProvenance
over (required)text
as (required)text
limita whole number from 1 to 200
blocks (required)a list of up to 10: TextBlock, ImageBlock, ButtonBlock, DividerBlock or SpacerBlock

table block

PropertyTakes
type (required)"table"
id (required)an id
provenanceProvenance
captiontext, at least 1 and up to 300 characters
columns (required)a list of up to 4: an object with align and width
header (required)a list of up to 4: Cell
rows (required)a list of up to 200: TableRow
mobilean object with layout
styleTableStyle

Text

A text block is a list of lines, and each line is a list of spans. A line’s kind is one of p, h1, h2, h3, bullet, number and quote. Lists are flat: consecutive bullet and number lines make one list, a line at level 2 nests under the line before it, and start begins a new numbered list. Consecutive quote lines make one quote. A line with no spans is an empty line.

A span is either text or a field. A text span’s text may hold \n for a line break, but never {{ or {%. A field span fills in a value, such as contact.first_name, with a fallback for when it’s empty and an optional format: date, datetime, number and money. money needs a currency (an ISO 4217 code, or a path to one) and reads the value as a whole number of that currency’s minor units: 1999 with USD shows $19.99. Both kinds take a link, a color, a highlight, a size, and marks: bold, italic, underline, strike, sup and sub.

When you send {{ contact.first_name }} in text, we turn it into a field span for you. Any other Liquid in text is an error.

Values and styles

Most styles take a token from your brand kit, such as brand.primary or space.md, or an exact value, such as a #rrggbb color or 24px. A token follows your kit when it changes; an exact value stays as written. Leave a style out to use the kit’s default. A style that isn’t set on an element comes from its column, then its section, then settings, then your kit.

Every element with a color also takes dark, exact colors for dark mode. Without them, we work out a readable dark version of each color.

Color
A palette token (brand.primary, text.default, extra.<slug>) or an exact color, #rrggbb. No alpha.
Font
font.heading, font.body, or a font family from the catalog. The catalog is checked in context.
PhoneFontSize
A size on phones: whole pixels from 12px to 72px.
PhonePadding
Side padding on phones, whole pixels from 0px to 200px: the left and right padding of each block inside that sets neither side itself.
Hex
An exact color, #rrggbb. Dark overrides take only these.
Href
https:, http:, mailto:, tel:, asset:ast_<id>, kit:website, kit:links/<key>, kit:social/<network>, system:unsubscribe, system:preferences, system:view_online, or a merge tag.
FontSize
A size token (size.body, size.h2) or whole pixels from 10px to 72px.
Path
A data path, such as contact.first_name, data.order.total, or item.name.
Spacing
A space token (space.md) or whole pixels from 0px to 200px.
Src
asset:ast_<id>, an http(s):// address, or a merge tag.
Radius
A radius token (radius.md) or whole pixels from 0px to 200px.

A link is one string, and its scheme says where it goes: a web page (https:), an email address (mailto:), a phone number (tel:), an uploaded file (asset: and the file’s id, asset:ast_…), a link saved in your brand kit (kit:website, kit:links/donate, kit:social/instagram), or one we fill in (system:unsubscribe, system:preferences, system:view_online). A kit link follows your kit when it changes.

  • http: works, with a warning: use https: where you can.
  • javascript:, data:, file:, vbscript:, and relative links are errors.
  • The unsubscribe and preferences links are for marketing mail only.
  • A link can be a merge tag, such as https://example.com/orders/{{ data.order.id }}. A link that’s wholly a merge tag is checked again once it’s filled in.

Merge tags and Liquid

Merge tags fill in each person’s details. They read from contact, account, message, campaign, data (what you send with a transactional email), links, now, and, in your own HTML, brand. Where they may go:

WhereWhat it takes
meta.subject, meta.preheader, an image’s alt, a button’s label, a table’s captionOutput tags: {{ path | filter: value }}, no {% %} tags
href, src, background_image.srcOutput tags, for links and images that differ for each person
Text spansNone: use a field span
A field span’s field and currency, a repeat’s overA path, such as data.order.items, not Liquid
Your own HTML, in an html block or sectionLiquid, with brand too
Styles, ids, settings, and fallbacksNever

A repeat runs its blocks once for each item in a list, naming each one as: a receipt’s line items, say. That name can’t be one of the namespaces above. Transactional mail may read only links.view_in_browser_url from links.

Ids

Every section, column, grid item, and block has an id: sec_, col_, itm_, or blk_, then 8 lowercase letters and digits (Crockford base32, so no i, l, o, or u). An id is unique within its document. The API fills in any you leave out and returns them, so you can change one part of an email later. A copied element gets a new id. Lines, spans, rows, and cells have no ids.

Limits

These limits only stop abuse. The limit that matters is the size of the finished email: see the size checks.

At mostOf
1,000,000bytes in the whole document, as JSON
100sections in an email
50blocks in a column
4columns in a columns section
24items in a grid
6blocks in a grid item
8blocks in a hero
200lines in a text
200spans in a line
5,000characters in a span
10lines in the footer’s note
50,000characters in a custom HTML block
100,000characters in a custom HTML section
4columns in a table
200rows in a table
50spans in a table cell
10blocks in a repeat
200times a repeat runs
12networks in a social block
2,048characters in a link

Versions

schema_version is MAJOR.MINOR. Until 1.0, versions are drafts and may change in place. From 1.0 on, a published version’s schema never changes:

  • Something new, such as a block or a property, is a new minor version. Documents you already have stay valid.
  • Renaming, removing, or tightening anything is a new major version, and we move saved emails forward for you.
  • /schemas/email/v1.json is always the newest 1.x version. Pin an exact version, such as v1.0.json, if you need it never to change.

Error codes never change meaning. A new kind of error gets a new code.

Errors

When a document doesn’t fit the format, each error has a code, a JSON Pointer to where it is in what you sent, the fix, and a docs_url that links to the code’s entry below. Branch on the code. Each entry is at #<code-with-dashes>, such as #color-invalid for color_invalid. Errors from the API itself, such as a missing key, are on API errors.

Structure

The document’s shape: what goes where, what’s required, and what isn’t allowed.

document_too_large: The document is too large

Keep the whole document under 1 MB of JSON. Move long custom HTML into fewer sections, or split the email.

type_invalid: A value has the wrong type

Give this property the type the schema expects, such as a string, a number, an array, or an object.

property_required: A required property is missing

Add the property. The message names it.

property_unknown: A property is not part of the format

Remove the property, or check its spelling. Field names are snake_case, such as content_background.

not_supported_yet: Not supported in this version yet

Remove it. The name is reserved for a later version of the format.

value_invalid: A value is not one of the allowed values

Use one of the values the message lists.

schema_version_unsupported: The schema version is not one this service reads

Set schema_version to the version your document was written for. The message names the current one.

string_too_short: A string is too short

Lengthen the string to at least the minimum the message gives, or remove the property if it is optional.

string_too_long: A string is too long

Shorten the string to at most the maximum the message gives.

array_too_short: A list has too few items

Add items until the list has at least the minimum the message gives.

array_too_long: A list has too many items

Remove items until the list has at most the maximum the message gives.

number_out_of_range: A number is out of range

Use a number inside the range the message gives.

number_not_integer: A number must be whole

Use a whole number, with no decimal part.

Types of element

A section, block, or span with a type or kind the format doesn’t have.

section_kind_unknown: Unknown section kind

Use one of the section kinds the message lists: columns, grid, hero, or html.

block_type_unknown: Unknown block type

Use one of the block types the message lists.

block_not_allowed_here: This block type cannot go here

Move the block into a column, or use a block type this container allows. The message lists them.

line_kind_unknown: Unknown line kind

Use one of p, h1, h2, h3, bullet, number, or quote.

Values

A color, size, or other value that isn’t written the way the format takes it.

color_invalid: Not a color

Use a palette token such as brand.primary or text.default, or an exact color as #rrggbb. Alpha and color names are not supported.

hex_invalid: Not an exact color

Dark overrides take an exact color only, as #rrggbb.

dimension_invalid: Not a valid size

Use a token such as space.md or radius.md, or whole pixels such as 16px, inside the range the message gives.

font_size_invalid: Not a valid font size

Use a size token such as size.body or size.h2, or whole pixels inside the range the message gives.

font_invalid: Not a valid font

Use font.heading or font.body, or the name of a font family from the catalog, such as Georgia.

button_width_invalid: Not a valid button width

Use auto, full, or whole pixels from 1px to 700px.

palette_invalid: Not a valid palette id

Use the id of one of the kit’s palettes, such as main: lowercase letters, digits, and underscores, but not kit, which is reserved.

theme_invalid: Not a valid theme id

Use light, dark, or the id of one of the palette’s themes: lowercase letters, digits, and underscores.

brand_invalid: Not a valid brand id

Use the id of one of the account’s brands as the API gives it (kit_ and 26 lowercase letters and digits), or remove settings.brand to use the default brand.

lang_invalid: Not a language tag

Use a BCP 47 language tag, such as en or pt-BR.

timestamp_invalid: Not a UTC timestamp

Use an ISO 8601 timestamp in UTC, ending in Z, such as 2026-10-06T14:02:11Z.

pointer_invalid: Not a JSON Pointer

Use a JSON Pointer relative to the element, such as /alt.

currency_invalid: Not a currency

Use an ISO 4217 code such as USD, or a path to one in the data, such as data.order.currency.

Where a link goes and where an image comes from.

src_invalid: Not a valid image source

Use an uploaded image (asset:<id>), a full web address (https:// is best), or a merge tag such as {{ data.image_url }}.

Text and merge tags

The text model: lines, spans, marks, and the merge tags inside them.

span_text_liquid: Merge tags in text must be field spans

Replace the tag with a field span, such as { "field": "contact.first_name", "fallback": "friend" }. Liquid tags ({% %}) are allowed only in custom HTML.

liquid_tag_not_allowed: Liquid tags are not allowed here

Use only output tags such as {{ data.order.number }} here. Tags like {% if %} are allowed only in custom HTML.

liquid_not_allowed: Liquid is not allowed here

Remove the {{ }} or {% %}. This field is plain text.

path_invalid: Not a valid data path

Write a path such as contact.first_name or data.order.total: a namespace, then names joined by dots, with no brackets.

path_case_invalid: A name under contact, account, message, campaign, links, or brand has a capital letter

Write names under our namespaces in lowercase, as contact.first_name, in a field and in Liquid alike. Names under data, and under a repeat’s variable, may use any case.

path_root_unknown: A path starts with an unknown name

Start the path with contact, account, message, campaign, data, links, or now, or with the variable of a repeat that contains it.

loop_variable_reserved: A loop variable shadows a namespace

Pick another name, such as item. contact, account, message, campaign, data, links, now, brand, and forloop are taken.

field_currency_without_money: A currency is set on a field that isn’t money

Set format to money, or remove the currency.

field_money_without_currency: A money field has no currency

Set currency to an ISO 4217 code such as USD, or a path to one in the data, such as data.order.currency.

Rules across properties

Rules that look at more than one property at once, such as unique ids and the footer.

marks_conflict: Superscript and subscript together

Keep either sup or sub on this span, not both.

line_level_orphan: A nested list line has no list above it

Put a bullet or number line before it, or remove level: 2.

line_start_nested: A nested list line cannot restart numbering

Remove start from this line. Only a top-level number line can start a new list.

widths_invalid: Column widths don’t fit the columns

Give one width per column, in whole percents that add up to 100, or remove widths for equal columns.

table_cells_mismatch: A table row has the wrong number of cells

Give every row, and the header, one cell per table column. Use an empty cell ({ "spans": [] }) for a blank.

image_alt_missing: An image has no alt text

Describe the image in alt, or set decorative: true if it carries no meaning.

image_alt_conflict: An image has alt text and is marked decorative

Remove alt from a decorative image, or remove decorative: true.

image_width_required: An image from outside needs a width

Set width, such as 300px. Images from an address or a merge tag can’t be measured when the email is built.

background_fallback_missing: A background image has no fallback color

Set background as well. It shows when images are off, and it’s what contrast is checked against.

background_image_size_required: A hero background from outside needs its size

Set background_image.width and height in pixels, or use an uploaded image (asset:<id>).

id_invalid: Not a valid id

Use the element’s prefix (sec_, col_, itm_, or blk_) and 8 lowercase Crockford base32 characters, or leave the id out and let the API fill it in.

id_duplicate: Two elements share an id

Give the copy a new id, or leave its id out and let the API fill one in.

kit_version_without_brand: A kit version is pinned without its brand

Set settings.brand to the kit the version belongs to, or remove settings.kit_version to follow the kit’s newest version.

Custom HTML

HTML you write yourself, in an html block or section, checked when it’s saved. The message gives the line and column inside the HTML.

html_parse: The custom HTML can’t be read as part of an email

Write the HTML that goes inside <body>: no <html>, <head>, <body>, or doctype, no NUL or other character HTML doesn’t allow, nothing nested over 100 deep, no tag with over 100 attributes, and no formatting tag such as <b> or <a> left open.

html_unsafe: The custom HTML holds something email can’t safely carry

Remove it, or use what the message suggests instead: a link instead of a form or frame, an <img> instead of a CSS or background image, plain HTML instead of SVG.

html_style: The custom HTML has a <style> tag

Put styles on each element (style="…") instead.

html_layout_escape: The custom HTML could move things out of its section

Remove position, transform, z-index, float, negative margins, computed sizes (calc and the like), custom properties, CSS escapes, and @import. Lay things out with tables and widths instead.

html_css: The custom HTML uses CSS email can’t carry

Use the properties and values the message suggests, written plainly in each element’s style attribute.

html_color: A color in the custom HTML can’t adapt to dark mode

Write each color as #rrggbb (such as #1a73e8), #rgb, rgb(), or a color name, one per declaration, in color, background-color, background, or a border.

html_alt_missing: An image in the custom HTML has no alt text

Describe the image in alt="…", or write alt="" if it’s only decoration.

html_liquid_unsafe: A merge tag sits where the custom HTML can’t hold it safely

Put merge tags in text, in quoted alt, title, and aria-label attributes, and in links and image sources. Brand colors, fonts, and sizes may also go in a style.

html_liquid_unbalanced: A Liquid tag opens and closes in different elements

Close every element you open inside an {% if %} or {% for %} before its next {% else %} or end tag.

html_conditional: An Outlook conditional comment isn’t one Flyanote can keep

Write <!--[if mso]> … <![endif]--> with plain tags inside, close each element it opens in a later one beside it, and pair each <!--[if !mso]><!--> with <!--<![endif]-->.

Drafts from a model

A draft or patch from an AI model. The pointer points into what the model wrote, not the document.

llm_ref_unknown: A block points at a section that isn’t there

Set at.section to the ref of one of the sections, or to a ref an earlier insert_section op created.

llm_ref_duplicate: Two sections share a ref

Give each section its own ref, one that no element in the email already has as its id.

llm_target_unknown: An op targets an id that isn’t in the email

Use the id of an element the email has, as the projected email shows it.

llm_target_invalid: An op targets the wrong kind of element

replace_lines takes a text block; set_block takes a block; delete and move take a block or a section; after takes a block, column, grid item, or section id.

llm_table_repeat_columns: An edit changes the columns of a table that repeats a row

Keep the table’s columns as they are: it repeats a row per item, which the projected email doesn’t show. A person can change its columns in the editor.

llm_preheader_conflict: A set_meta op both removes the preheader and sets one

Set clear_preheader to true with preheader "" to remove it, or give the new preheader with clear_preheader false.

llm_draft_empty: The draft has nothing in it but a footer

Write the email: at least one block other than the footer.

llm_field_unused: A field is set where it doesn’t apply

Each field says the block types, ops, or spans it applies to. Give it its unset value everywhere else ("", "kit", 0, false, or [], as it says), and put what you meant in the field that applies, such as button_width for a button or after for insert_block.

The brand kit

The kit’s colors, fonts, logo, and links. The pointer points into the kit as you sent it.

kit_main_palette_missing: The first palette isn’t main

Make the first palette the one with id main. Every kit has it, and documents fall back to it.

kit_palette_duplicate: Two palettes share an id

Give each palette its own id.

kit_extra_duplicate: Two extra colors share a slug

Give each extra color in a palette its own slug.

kit_dark_edited_invalid: An edited dark color isn’t there

List in dark_edited only colors the palette has, each with its dark value set in dark, or remove the entry to have the dark value generated.

kit_theme_reserved: A theme uses a reserved id

Give the theme another id. light is the palette’s own colors and dark its dark values, so a theme can’t take either.

kit_theme_duplicate: Two themes in a palette share an id

Give each theme in a palette its own id.

font_fallback_invalid: Not a font fallback list

List font names separated by commas, without quotes, ending in serif, sans-serif, or monospace, such as Helvetica, Arial, sans-serif.

kit_too_large: The brand kit is too large

Keep the brand kit under 64 KiB of JSON: fewer palettes, extra colors, or saved links, or a shorter description.

Your account’s kit, images, and fonts

What the document asks of your account: a token, image, font, or saved link it doesn’t have.

palette_unknown: The kit has no such palette

Use the id of one of the kit’s palettes, or remove settings.palette to use main.

theme_unknown: The palette has no such theme

Use light, dark, or the id of one of the palette’s themes, or remove settings.theme to use light.

token_unknown: The kit has no such color

Use a color the palette has, add it to the kit as an extra color, or use an exact color such as #b5462b.

font_unknown: The font isn’t in the catalog

Use a family from the font catalog, such as Georgia or Arial, spelled as the catalog spells it. In a document, font.heading and font.body use the kit’s fonts.

asset_not_found: The file isn’t in this account

Use a file uploaded to this account, or a full https:// address.

kit_logo_missing: The kit has no logo

Add a logo to the brand kit, or remove the logo block.

subject_empty: The email has no subject

Write a subject before you publish or send: it’s what a recipient sees first in their inbox.

button_label_empty: A button has no label

Write the button’s label, such as Read more or View your order, or remove the button.

liquid_namespace_whole: A whole namespace is read

Name each field you use, such as contact.first_name, not contact on its own or a loop over it. Flyanote sends a template only the fields it names.

variables_too_many: The email reads too many fields to list

Read at most 500 different fields, each named in at most 300 characters.

Liquid

Merge tags and Liquid that won’t run. Health checks and the API share these codes.

liquid_syntax: The Liquid doesn’t parse

Check the tag at the line and column given: a {{ needs its }}, and every {% if %} or {% for %} its end tag.

liquid_template_too_large: The Liquid is too long

Shorten this text. The message gives the limit.

liquid_tag_unknown: Not a Liquid tag Flyanote has

Use if, unless, case, for, assign, capture, comment, or raw. include and render aren’t available.

liquid_filter_unknown: Not a Liquid filter Flyanote has

Use one of the filters in the merge tag reference, such as fallback, format_money, or localize_date.

liquid_filter_argument_invalid: A filter has the wrong arguments

Give the filter the arguments the merge tag reference lists for it.

liquid_dynamic_lookup: A field is looked up by another value

Name each field directly, such as contact.first_name, not contact[key]. Flyanote sends a template only the fields it names.

liquid_name_reserved: A Liquid variable uses a reserved name

Pick another name for the variable. contact, account, message, campaign, data, links, now, brand, and forloop are taken.

liquid_loop_too_deep: Loops nest too deep

Nest loops at most two deep.

liquid_nesting_too_deep: Tags nest too deep

Nest fewer tags inside each other. The message gives the limit.

liquid_range_too_large: A range is too large

Use a range with fewer numbers. The message gives the limit.

liquid_range_bound_too_large: A range starts or ends too far from zero

Keep the first and last numbers of a range between -9007199254740991 and 9007199254740991.

liquid_brand_not_allowed: Brand values work only in custom HTML

Remove the brand value here, or use the kit’s token in the element’s style instead.

liquid_brand_in_tag: A brand value is used in a tag

Output brand values only, as in {{ brand.colors.primary }}, not inside {% if %} or other tags.

liquid_brand_mixed: A brand value is mixed with data

Output the brand value on its own, in a separate {{ }} from any contact or data field.

liquid_brand_unknown: The kit has no such brand value

Check the spelling against the brand values your kit has, such as brand.colors.primary, brand.fonts.body, or brand.links.<key>.url.