Data and recipient
The Data panel defines the customer context an email can use and the recipient it goes to. A purchase follow-up may need both a contact and an order; selecting those inputs makes the relationship explicit for Liquid, Adaptyle and the system that triggers the send.
Open the Data tab beside the email. It shows the expected properties and recipient, followed by a Sample section. The sample’s Edit as JSON control opens the raw values; Hide JSON returns to the record pickers.
The list is a contract. The sending context supplies its expected properties, while maxclicks adds reserved branding data. Each record input needs the identity and fields appropriate to that operation; including a second record does not automatically look it up through the first.
On narrow windows the tabs collapse to icons. Select the Data icon to open the panel over the email, then close it to return to the full canvas.
Example: a confirmation for one customer and order
For a standalone order confirmation, declare a customer contact and an order object. Select the customer row under To. If you name the rows customer and order, the content can use {{ customer.firstName | default: "there" }} and the fields your order schema defines, such as {{ order.total }}.
Pick a real customer and order in Sample and preview the confirmation. The application must provide both inputs for a real send; choosing the customer alone does not find an unrelated order. For a broadcast, the audience provides the one contact input, so reach their purchases through a selected relationship instead.
Tell the email what it needs
Each row on the list is one piece of information, with a key you use in your content: {{ contact.firstName }}, {{ order.total }}. There are two kinds.
| Kind | What it is | How the row reads |
|---|---|---|
| Record | A contact, object, or event record, one or a list of them | The schema's name, with [] after it for a list |
| JSON | Any plain value you pass in: a coupon code, a total, a nested object | JSON |
Click a row to open it. A record shows every field of its schema. A JSON row shows the shape you defined for it.
The first row is always branding, ticked and greyed out, with a note reading "The branding data is added by the system. You do not need to set it in the sample data." That is your brand kit, added for you.
A reference to something that is not on the list renders as nothing at all.
Every editor warns you before that happens: in the visual editors the variable
turns amber, and in the MJML and HTML code editors the expression is
underlined. Both carry the same message, "name" isn't in your data, so this renders empty.
Add a property
Press Add property, beside the sentence above the list. It is there on a template and on a workflow send-email step, and never on a broadcast.
- Property type, placeholder "Pick a schema or JSON…". The dropdown groups your schemas under Contact schemas, Object schemas, and Event schemas, then offers JSON property under Other. Every schema in your space is offered, and the same schema can appear on the list more than once under different keys.
- Key. It is pre-filled from the schema, and you can type your own.
- Array of records, for a record. Off means one record, on means a list.
- Shape, for a JSON property. Paste a sample payload and maxclicks works the shape out, build it by hand, or leave it open to accept anything.
- Add.
Changing Property type after you have typed a key throws the key away and starts the row over. Pick the type first, then name it.
Naming rules
- In Add property, use letters, digits and underscores, starting with a letter or underscore. Spaces become underscores and other symbols are removed when the property is added. The panel previews the result as "Will be normalized to
yourkey". A digit cannot be the first character. branding,skip, andlimitare taken. Using one gives you "Reserved." Expression keywords such asdefault,classandreturnare also refused. Choose a descriptive key such ascustomerTier.- Two rows cannot share a key: "A property with this key already exists."
The pre-filled key comes from the schema and drops any dash, so a schema slugged abandoned-cart suggests abandonedcart. Rename it in the Key field before you press Add if you would rather have something else, because a key cannot be changed afterwards.
Choosing between one and a list
A list is right when the email loops over it, such as the lines on an order. The whole list cannot be the recipient: the final path must resolve to one contact or an email-format value. If it ends at the array itself, validation reports "Recipient path should not point to an array of records, it should point to either a single contact record or an email address value."
Leaving a JSON shape open
An open shape accepts any JSON, which is convenient and costs you the safety net. maxclicks can only warn you about a misspelled variable when it knows the shape, so with an open one {{ payload.tpyo.name }} passes silently and renders empty. Define the shape for anything you will reference by name.
Remove a property
Untick the row. That is the only way, and there is no delete button, no confirmation, and no undo.
Removing a property also removes its expansion selection and clears a recipient pointing to it. Existing Liquid expressions remain in the content but lose their data source, so they can render empty. Review Personalize and Checks and repair those references after changing the model.
There is no rename either. Renaming is removing and adding, with all of the above.
On a standalone template, taking the last property off the list does not stick. Reopen the editor and a property for your space's default contact schema is back, with the recipient pointed at it.
Choose who receives it
To sits at the top of the panel. It is a chain: pick a property, and if it can be opened further, another dropdown appears after a chevron for the next step down.
Only two things qualify as a recipient:
- A single contact record. Not a list, and not an object or event record.
- A value declared as an email address, including an email-format JSON value or a stored email field reached through a record.
The Data path picker lets you navigate the declared data; recipient validation determines whether the final path is usable. Selecting a plain string, object or list does not make it a valid recipient. If there is no eligible row, the code editors say so directly: "No recipient is available yet. Add a contact record property or an email address property to the data representation to pick a recipient."
Leaving it empty gives you "Recipient path is not provided." next to the To row. The blank-looking dash entry at the top of the dropdown is the clear option, and picking it does exactly that.
Contact or bare email address
The two are not interchangeable.
| A contact record | An email address value | |
|---|---|---|
| Consent | Marketing checks the contact's subscription and selected topic | No contact subscription; applicable delivery suppressions still apply |
| Unsubscribe | A personal preferences link, managed for you | No personal link |
| Marketing | Allowed | Refused |
| Reporting | Opens and clicks attach to that contact | Not attached to anyone |
Marketing email can only go to a contact, because it must carry a working unsubscribe link. Point a marketing email at an address value and you get "This is a marketing email, so it can only be sent to a subscribed contact (marketing emails carry a required unsubscribe link). To send to a direct email address, use a transactional email template instead." Marketing or transactional is fixed when the email is created, so the fix is a new email, not a setting.
A recipient path is separate from the expansion ticks used by the content. The picker initially exposes the available record and stored-field structure; an evaluated relationship is not automatically looked up because its name appears in your email. Review the configured path and its validation when using a related contact as the recipient.
In the MJML and HTML code editors there is a second To control in the block above the code, next to From. It sets the same thing but only one level deep, so if your recipient reaches deeper than one step, that control shows nothing selected. Touching it replaces the deeper setting.
Pull in computed values
Open a record row and you see its fields. Stored writable fields are ticked and locked because they travel with the record. Evaluated fields must be requested through expansion. Some resolve an on-demand lookup; others read a published scheduled calculation. Ticking a field requests its configured behavior, not a fresh calculation. An evaluated relationship that returns records opens those records' fields underneath, where you can select further expansions.
This is attribute expansion, and that page covers it properly.
On-demand fields run their configured lookup when expanded. Scheduled Evaluated fields read the publication selected for that execution. An enabled calculation with no complete result or an expired result blocks expansion; it does not silently become an empty merge field. A valid publication with no result for this record can return null. Paused calculations can retain their last published result under that captured policy. Inspect Published value and Data through before relying on the field. Nested lookups add work, and a many-record result expands at most 1,000 records. Select only what the email uses. See freshness and execution snapshots.
Ticks stay editable everywhere, including on a broadcast whose list is otherwise frozen, for as long as the email is still editable.
What each place locks
This is where most confusion starts. The same panel is locked differently depending on what is sending the email.
| Broadcast | Template | Workflow send-email step | |
|---|---|---|---|
| The list | Fixed to the audience contact, reach the rest through selected Evaluated fields | Yours to set | Offered by the step, yours to adopt |
| Add property | Not shown | Shown | Shown |
| To | Locked to the audience contact | Yours to set | Yours to set |
| Evaluated field ticks | Yours, while it is still a draft | Yours | Yours |
A broadcast decides both for you
A broadcast already knows who it is mailing, so the list is one row for the audience contact, named after that schema (a Learner audience gives you learner), and the recipient is that contact. The property checkboxes are disabled, there is no Add property, and To is read-only. The sentence above the list says the properties come from the sending context.
The initial broadcast key is generated from the schema slug, replacing separators with underscores: abandoned-cart becomes abandoned_cart. Once saved, that email keeps its property key when the schema is renamed. Use the key displayed in Data, rather than reconstructing it from the current schema name.
A broadcast supplies the contact for each selected recipient. Any additional customer context needs to be reachable from that contact rather than supplied as a second unrelated input.
To add a lookup or calculated value, expand the contact row and select the Evaluated field the email needs. An evaluated relationship is how a broadcast reaches another record: give Learner an evaluated cohort, tick it, and write {{ learner.cohort.name }}. An on-demand relationship resolves for each recipient during expansion. See computed values above and the evaluated attributes reference.
If you need a genuinely free data model, with records that have nothing to do with the recipient, that is what a template is for: your own code passes the data in on each send.
If either the list or the recipient drifts from what the broadcast wants, a repair appears above the list, which stays visible while you read it:
- Data out of sync, reading "The data provided to this template has changed since it was set up. Sync the template to match it.", with a Sync data properties button.
- "The recipient no longer matches the one enforced by the sending context.", with a Sync recipient button.
Once a broadcast is scheduled or sending, the whole panel goes read-only: no ticks, no record pickers, no editing the sample.
A template sets its own
A standalone template owns both. Whatever you put on the list becomes what a send has to carry, so adding or removing a row here changes what your own code, or an integration, has to send. Every key on the list is required in the call, though each record only needs enough to identify it.
A new template does not start empty: it seeds one property for your space's default contact schema and points the recipient at it.
A workflow step offers, it does not impose
A send-email step in a workflow shows you what the step actually receives, and leaves the choice to you. Each thing the step carries is a row you can tick to take. Rows you have taken that no longer match what arrives are marked, which is where the drift shows up.
Add property cannot create data for an earlier workflow step. Anything you add that the step does not carry turns red with "This property is expected but not provided.", and if you leave it there the step fails when the workflow runs. Only take rows the step gives you, and if you need something else, add a step before this one that fetches it.
The step also has its own recipient control, Sends to, in the sidebar outside the editor. It sets the same thing as To in the panel, but only offers what the step carries, and only one level deep.
Changing the workflow upstream changes what this step carries, quietly. Rows can go red on their own. Where two branches meet, only what both branches carry survives, so a property that exists on one path and not the other disappears from the step entirely.
Preview it with sample data
The Sample section below the data model holds sample data: a stand-in value for each property so the editor can render a preview. Edit as JSON opens the raw sample and generation controls; Hide JSON returns to the record pickers. The data model remains above it.
Pick a real record with the picker on its row. The editor copies stored fields and requests the selected Evaluated expansions. The preview uses those sampled values; a real send resolves its execution data separately. Selecting another field requests a sample refresh, but it does not force a scheduled evaluation. Inspect the sample itself and the field’s publication status when a selected value cannot be loaded.
A test send does not check any of this. It mails whatever the preview rendered, so it tells you nothing about whether the recipient is set correctly.
Read the panel when something is wrong
The Checks tab covers three separate data concerns: the model, the recipient and the sample. A correct-looking list does not establish that the recipient or sample is valid.
| What you see | What it means | What to do |
|---|---|---|
| "Recipient path is not provided." | Nothing is in To | Pick a contact row or an email-address row |
| "Unknown key." on a To step | That step points at something no longer there | Repick from the dropdown |
| "Undefined path item." on a To step | The path carries on past a plain value | Shorten it back |
| "Unknown schema" as a row's type | The schema behind that row was deleted | Remove the row and add a replacement |
| "This property is expected but not provided." | The email wants something the sender does not carry | Untick it, or add it upstream |
| "The expectation of this property is not compatible to its provided form. Update it accordingly." | Same key, different shape | Tick the second row for that key, the one the sender actually carries |
| "The expectation of this property is compatible to its provided form, but not exactly the same. You may update it accordingly." | Close enough to work, worth aligning | Same, when convenient |
| Data out of sync | A broadcast's list drifted | Sync data properties |
| "Sample data does not satisfy the expected data representation with the specified attribute expansions:" | The sample no longer fits the list | Fix or regenerate the sample |
When a shape mismatch appears, the same key shows up twice in a row, once ticked and once not. The lower one is what the sender actually carries. Tick it to take it.
The Checks tab groups these under Recipient, Data and Sample & preview. Their actions open Data. For a sample problem, choose Edit as JSON in its Sample section.
On narrow windows the side tabs collapse to icons. Choose Data to open the panel over the email, then close it to return to the full canvas.
Why a later refresh may not change an active send
A standalone sample resolves selected scheduled Evaluated fields against its current read context. A broadcast revision or root workflow run captures the calculation generation, freshness policy and observation time on its first read; child runs inherit that context. Publishing a newer calculation does not replace that captured selection. This fixes the scheduled calculation context, not every live customer field or on-demand lookup.
An enabled calculation with no complete publication or an expired publication fails the expansion for that decision. Refreshing the calculation later does not repair an already captured unavailable selection. A paused definition can use its captured last-published policy; a valid publication with no subject result can return null. An erased pinned generation fails rather than switching to a newer one. Check the record’s Published value, Data through and status, then compare the sample with the execution context. See attribute expansion.
Related
- Sample data: the stand-in values the preview renders against.
- Attribute expansion: selected fields, dependencies and execution freshness.
- Evaluated attributes: on-demand relationships and scheduled event-history measures.
- Liquid and Adaptyle: using what you declared here in the content.
- Schemas: the records behind every record row.