The theMarketer MCP Server lets an AI assistant (Claude, ChatGPT, OpenClaw or any MCP-compatible client) work with your theMarketer account through natural language: look up and manage subscribers, review campaign performance, pull e-commerce and audience reports, send transactional messages and more.
Every action runs under your own theMarketer identity via OAuth 2.1, scoped to the domains you have access to. Read tools never change data. Write tools create or update records. Destructive tools delete or irreversibly alter data and always require confirmation in the assistant.
Audience24
List contacts
list_contactsReadList or count the contacts in the audience that match a set of filters.
Use when the user asks who is in the audience, how many contacts match some criteria, or when another tool needs a contact id. Filters combine with AND; run separate calls for alternatives. For a "how many" question set count_only=true and read total. For the headcount per channel and the last 7 days' joins and losses use get_audience_evolution instead, and get_contact_details for everything about one contact.
Results come 15 per page with total, pages and per_page; narrow the filters rather than paging through a large result. Bounds are inclusive: *_after includes the named day and *_before stops at the start of it, so a calendar month is created_after="2026-05-01", created_before="2026-06-01". Emails and phones come back masked when the account anonymises contacts. list_segments gives the segment_id values.
For geographic audiences, select an existing segment with list_segments and pass its segment_id; do not supply raw personal locations.
Parameters
| Parameter | Type | Description |
|---|
search | string | Text to look for in the first name, last name, email or
phone; a contact matches when any of them contains it. |
email_status | enum | Email consent: subscribed, unsubscribed, or
not_subscribed (never opted in). One of: subscribed, unsubscribed, not_subscribed. |
sms_status | enum | SMS consent, same values as email_status. One of: subscribed, unsubscribed, not_subscribed. |
loyalty_status | enum | Loyalty programme consent, same values as
email_status. On an account with no loyalty programme set up
it matches the consent setting alone, and note says so. One of: subscribed, unsubscribed, not_subscribed. |
has_phone | boolean | True for contacts that have a phone number, False for
contacts without one. |
engagement | enum | Engagement status: active, inactive or cleaned. One of: active, inactive, cleaned. |
gender | enum | male, female or unknown. One of: male, female, unknown. |
acquisition | enum | Where the contact came from, e.g. website (on-site
tracking), import, popup, order or api. One of: website, import, popup, order, embedded_form, landing_page, api, launcher. |
tag | string | Only contacts carrying this tag, matched as spelled in the
account's tag list; case is corrected when only one tag
matches, and note says so. A tag the account's list does
not have is matched exactly as typed, and the note says so. |
first_name | string | First name, substring match; % is a wildcard and
---empty--- selects contacts with no first name. |
last_name | string | Last name, substring match like first_name. |
rfm_group | enum | The RFM group the contact is in, e.g. champions, loyal,
at_risk or lost. One of: champions, loyal, at_risk, cant_lose, potential_loyalist, promising, hibernating, new_customer, needs_attention, lost, many_time_buyer_high_aov, many_time_buyer_low_aov, one_time_buyer_high_aov, one_time_buyer_low_aov. |
funnel_stage | enum | Last funnel stage the contact reached, from awareness
to purchase. One of: awareness, interest, consideration, intent, evaluation, purchase. |
min_rating | integer | Lowest contact rating to include, 1-5 (inclusive). |
max_rating | integer | Highest contact rating to include, 1-5 (inclusive). |
min_loyalty_points | integer | Lowest loyalty points balance to include
(inclusive). |
max_loyalty_points | integer | Highest loyalty points balance to include
(inclusive). |
created_after | string | Contacts added on or after this day (YYYY-MM-DD). |
created_before | string | Contacts added before this day (YYYY-MM-DD); the
day itself is excluded. |
subscribed_after | string | Email subscription date on or after this day
(YYYY-MM-DD); only contacts currently subscribed to email. |
subscribed_before | string | Email subscription date before this day
(YYYY-MM-DD, excluded); only contacts currently subscribed to
email. |
unsubscribed_after | string | Email unsubscription date on or after this day
(YYYY-MM-DD); only contacts currently unsubscribed from email. |
unsubscribed_before | string | Email unsubscription date before this day
(YYYY-MM-DD, excluded); only contacts currently unsubscribed
from email. |
custom_field | string | Label of a custom column defined for this account
(e.g. "Marime"); give it together with custom_field_value. |
custom_field_value | string | Exact value the custom column must hold; give it
together with custom_field. |
segment_id | string | Restrict the list to one custom segment of this
domain: its id as list_segments returns it, 24 hex characters.
An id that names no custom segment here is an error, not an
empty list. System segments (ids starting with system-) are
not accepted here; use the matching filter instead, e.g.
rfm_group for the RFM ones. |
sort_by | enum | Field to order by; created_at by default, which with
sort_desc puts the newest contacts first. One of: created_at, email, firstname, lastname, phone, country, city, acquisition, loyalty_points, rfm_group, funnel. Default: 'created_at'. |
sort_desc | boolean | True for descending order (default), False for
ascending. Default: True. |
count_only | boolean | Return only the counters and no contact rows: the
cheap answer to "how many contacts ..." questions. Default: False. |
page | integer | Page number, starting at 1. Default: 1. |
fields | enum | summary returns eleven fields per contact; full adds
every column (gender, acquisition, RFM group, loyalty tier and
points, rating, per-channel flags and the account's custom
columns). One of: summary, full. Default: 'summary'. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
total | integer | Contacts matching the filters, across all pages. |
page | integer | Page returned, starting at 1. |
pages | integer | Total pages at 15 contacts each. |
per_page | integer | Contacts per page, always 15; narrow the filters rather than paging through a large result. |
contacts | object[] | Contacts on this page: eleven summary fields each, or every column when fields is full. Empty when count_only is set. |
id | object | theMarketer contact id. |
email | object | Email address; masked when the domain anonymizes. |
firstname | object | First name. |
lastname | object | Last name. |
phone | object | Phone number; masked when the domain anonymizes. |
city | object | City. |
country | object | Country. |
tags | string[] | Tags on the contact. |
created_at | object | Acquisition date, DD.MM.YYYY. |
status | object | Engagement status: active, inactive or cleaned. |
unsubscribed | string[] | Channels the contact has opted out of: any of email, sms, push, mobile_push, loyalty. Only channels the contact can use are listed (sms needs a phone, push a push token), matching what get_contact_details and update_contact show. |
has_more | boolean | True when a later page exists; the note says which to ask for. |
note | object | How to get the next page when there is one, why rows are missing when they were omitted on request, which tag a differently cased tag was matched to or that tag is not in the account's tag list, and what loyalty_status matched on an account without a loyalty programme; null when none of these applies. |
Get contact details
get_contact_detailsReadEverything about one contact, by section: profile, purchases, loyalty, activity and deliverability.
Use when the user asks about a specific person: who they are, what they buy, their loyalty standing, what they did recently, or why an email did not reach them. Find people with list_contacts first; change what this tool shows with update_contact or unsubscribe_contact. By default it returns profile, rfm, ecommerce and loyalty; ask for other sections only when the question needs them, because each one is a separate lookup and "all" fetches every section.
A section that could not be loaded reads {"unavailable": <reason>} while the rest still answer; loyalty and loyalty_history read so on accounts without a loyalty programme. Long lists come one page at a time, newest first: orders (25 per page), the onsite and offsite activity timelines, the profile's consent_history and the delivery_log (30 each). One page walks them all together, so ask for page 2 only with the section you need. onsite holds the newest 100 events. Emails and phone numbers come back masked when the account anonymises contacts.
Parameters
| Parameter | Type | Description |
|---|
email | string | Email address of the contact. Use contact_id instead when
the account masks addresses or several contacts match. |
contact_id | string | theMarketer contact id (24 hex characters, as
list_contacts returns it). Pass this or email, not both. |
sections | enum[] | Which sections to fetch; omit for profile, rfm, ecommerce
and loyalty. Any of: profile (identity, consent and its history,
tags, custom columns, device and session facts), rfm (RFM group
and the moves between groups), ecommerce (order totals, rates
and averages), orders (the order list, 25 per page), favorites
(favourite brand, category and products), engagement (when the
contact opens email and SMS), loyalty (points, tier, status),
loyalty_history (points, tier and rewards history), feedback
(NPS group and review ratings), activity (onsite and offsite
event timelines, 30 per page each), referrals (referred contacts
and the refer-a-friend link), deliverability (automatic-cleanup
status plus the email delivery log, 30 per page). "all" fetches
every section. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
contact_id | string | theMarketer id of the contact described. |
sections_returned | string[] | The sections fetched on this call, in the order the keys below are listed. |
profile | object | Identity (name, email, phone, gender code M/F/U, birthday Y-m-d, country/county/city), consent (unsubscribed, applicable_channels and marketing_preferences), is_owner, anonymized, notes, custom_columns (only the columns this contact has a value in), tags, acquisition source, preferred email format, device/session facts (browser, device, subscribe and last-seen datetimes) and consent_history: the subscribe/unsubscribe log, newest first, each entry with date d.m.Y, time and message, 30 per page (items for the requested page, total, pages, has_more and a note saying which page to ask for next). Reads {"unavailable": <reason>} when it could not be loaded. |
rfm | object | The RFM group the contact is in (Champions, Loyal customer, At risk, ...), time_in_group, last_purchase and the history of moves between groups. Reads {"unavailable": <reason>} when it could not be loaded. |
ecommerce | object | Lifetime e-commerce figures: open, click and conversion rates in percent, transactions (orders placed), average_order_value, total_revenue and last_order. Reads {"unavailable": <reason>} when it could not be loaded. |
orders | object | The contact's orders, newest first, each with its product list, 25 per page (items for the requested page, total, pages, has_more and a note saying which page to ask for next). The list is complete: total is every order. Reads {"unavailable": <reason>} when it could not be loaded. |
favorites | object | The favourite brand and category (name, purchases, views, share of purchases in percent) and the favourite products (name, image, category, orders, views), from the contact's purchases and browsing. Reads {"unavailable": <reason>} when it could not be loaded. |
engagement | object | When the contact opens messages, for email and sms: the preferred_hour and the opens per half hour of the day (opens_by_half_hour, 48 counts from 00:00). Reads {"unavailable": <reason>} when it could not be loaded. |
loyalty | object | The loyalty card: points, tier with its range and next_tier (null on a points programme), redeemed_points, about_to_expire, joined_on, last_update and member. Unavailable on accounts without a loyalty programme. Reads {"unavailable": <reason>} when it could not be loaded. |
loyalty_history | object | Four sub-keys - points_history and rewards_history (the last 10 rows each, newest first), tier_evolution and points_evolution (charts over days) - each reading {"unavailable": <reason>} on its own when it could not be loaded. Unavailable on accounts without a loyalty programme. Reads {"unavailable": <reason>} when it could not be loaded. |
feedback | object | What the contact told the account: nps_group (promoter, passive, detractor or null), the number of reviews, last_rating and average_rating. Reads {"unavailable": <reason>} when it could not be loaded. |
activity | object | Two timelines, onsite (website events: views, carts, orders, forms) and offsite (campaign and automation events: delivered, opened, clicked, bounced), each as items newest first with date (d M Y), time (H:i), message (what happened), message_continuation (the product, category, search term, campaign subject or automation it happened to) and action (the path of that campaign or product in the theMarketer app, or null), 30 per page (items for the requested page, total, pages, has_more and a note saying which page to ask for next). offsite is complete; onsite holds the newest 100 events, so its total tops out at 100. Either sub-key reads {"unavailable": <reason>} on its own when it could not be loaded. Reads {"unavailable": <reason>} when it could not be loaded. |
referrals | object | referred: the contacts this one referred; referral_link: this contact's refer-a-friend URL, or null when there is none for the address (a masked address has none). Either sub-key reads {"unavailable": <reason>} on its own when it could not be loaded. Reads {"unavailable": <reason>} when it could not be loaded. |
deliverability | object | cleanup: whether automatic cleanup is on and how close the address is to being cleaned. delivery_log: every send, open and click on the contact's emails, newest first, each with date d.m.Y, time and message, 30 per page (items for the requested page, total, pages, has_more and a note saying which page to ask for next). Either sub-key reads {"unavailable": <reason>} on its own when it could not be loaded. Reads {"unavailable": <reason>} when it could not be loaded. |
Create contact
create_contactWriteAdd one new contact to the audience by email address.
Use when the user wants a single person added, after a call, an event or a manual sign-up. Creates only: an address that already exists fails and points at update_contact, and the existing contact is left untouched. For more than a handful of contacts use import_contacts. Only name, phone and the three consents can be set here; birthday, tags and custom fields go through update_contact afterwards. Manage residence/location in the authenticated theMarketer web app.
The phone is saved in international form: +40722123456, 0040 722 123 456 and, on a domain whose store profile country is Romania, 0722 123 456 all become +40722123456. Letters, or fewer than 7 or more than 15 digits with the country code, stop the call with the fix to make.
The contact is saved quietly: no automations fire and no double opt-in email is sent, so the consent given here is final. Loyalty consent applies on plans that include the loyalty program. Only email consent is on by default; turn SMS or loyalty on only when the user asked for them, because a subscription implied from a conversation is not a ticked box.
Parameters
| Parameter | Type | Description |
|---|
emailrequired | string | Email address that identifies the contact (case-insensitive; matched as stored, lowercase). |
first_name | string | First name of the contact, at most 120 characters. |
last_name | string | Last name of the contact, at most 120 characters. |
phone | string | Phone number, such as +40722123456; spaces, dashes, dots
and brackets are dropped. A number without + or 00 gets the
country code of the domain's store profile country. SMS consent
needs one. |
subscribed_to_email | boolean | Email marketing consent. On by default. Default: True. |
subscribed_to_sms | boolean | SMS marketing consent. Off unless the user
explicitly asked for SMS; needs phone, and the call stops
without one. Default: False. |
subscribed_to_loyalty | boolean | Loyalty programme consent. Off unless the
user explicitly asked; applies on plans with the loyalty program. Default: False. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
created | boolean | True when the contact now exists in this audience. |
contact_id | string | theMarketer id of the new contact (24 hex characters). |
contact | object | The new contact as list_contacts shows it: identity, opted-out channels and acquisition date. |
id | object | theMarketer contact id. |
email | object | Email address; masked when the domain anonymizes. |
firstname | object | First name. |
lastname | object | Last name. |
phone | object | Phone number; masked when the domain anonymizes. |
city | object | City. |
country | object | Country. |
tags | string[] | Tags on the contact. |
created_at | object | Acquisition date, DD.MM.YYYY. |
status | object | Engagement status: active, inactive or cleaned. |
unsubscribed | string[] | Channels the contact has opted out of: any of email, sms, push, mobile_push, loyalty. Only channels the contact can use are listed (sms needs a phone, push a push token), matching what get_contact_details and update_contact show. |
Update contact
update_contactDestructiveChange an existing contact's details, tags or channel consent.
Use when the user wants to correct or complete a contact's record: name, email, phone, gender, birthday, a custom field, the set of tags, or a subscription change including re-subscribing. Pass only what should change; every field you omit keeps its value. For an opt-out alone prefer unsubscribe_contact; for a contact that does not exist yet use create_contact. Manage residence/location in the authenticated theMarketer web app; this tool preserves existing location fields.
tags replaces the whole set: to add one, pass the current tags plus the new one (get_contact_details shows them). Tag changes fire the account's tag automations. Consent changes are logged as manual changes and can re-subscribe someone, so confirm intent first. The result carries the contact as it is after the change, updated the groups written (details the contact already has are not written again, and note says when nothing changed), and warnings names anything that could not be applied, such as an email or phone edit on an account that anonymises contacts.
Parameters
| Parameter | Type | Description |
|---|
contact_id | string | theMarketer contact id (24 hex characters, as
list_contacts returns it). Pass this or email, not both. |
email | string | Email address that identifies the contact to change. Use
contact_id instead when the account masks addresses or several
contacts match. To change the address itself, pass new_email. |
new_email | string | New email address for the contact. An address already
used by another contact is not accepted and nothing is changed.
Cannot be changed on accounts that anonymise contacts;
warnings says so. |
first_name | string | New first name for the contact, at most 120
characters. |
last_name | string | New last name for the contact, at most 120 characters. |
phone | string | New phone number, such as +40722123456 or 0040 722 123
456; spaces, dashes, dots and brackets are dropped. A number
without + or 00 gets the country code of the domain's store
profile country. It must have 7 to 15 digits with its country
code; letters are not accepted. A phone can be replaced but not
removed, and needs the domain's store-profile country to be
set. Cannot be changed on accounts that anonymise contacts;
warnings says so. |
gender | enum | New gender: male, female or unknown. One of: male, female, unknown. |
birthday | string | New date of birth as an ISO date, YYYY-MM-DD. |
tags | string[] | The complete set of tags the contact should have; replaces
the current tags. Pass an empty list to remove them all. A tag
that differs only in case from one in the account's tag list
is saved under the listed spelling and warnings says so; new
tags are added to the list. |
subscribed_to_email | boolean | True to subscribe the contact to email
marketing, False to opt it out. |
subscribed_to_sms | boolean | True to subscribe the contact to SMS marketing,
False to opt it out. Needs a phone on the contact. |
subscribed_to_push | boolean | True to subscribe the contact to web push,
False to opt it out. Needs a push token on the contact. |
subscribed_to_mobile_push | boolean | True to subscribe the contact to mobile
push, False to opt it out. Needs a mobile push token on the
contact. |
subscribed_to_loyalty | boolean | True to enrol the contact in the loyalty
program, False to opt it out. |
custom_fields | object | Ordinary marketing custom field values, as
{label: value}. Never include health, biometric, government ID,
payment-card or authentication data. Each label must be one of
the domain's custom fields (get_audience_options
kind=custom_fields lists them); a label that differs only in
case is saved under the exact name and warnings says so.
Fields you do not name keep their values. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
contact_id | string | theMarketer id of the contact changed. |
updated | string[] | Groups of fields a write was issued for, in write order: profile (names, email, phone, gender, birthday, custom fields), tags, subscriptions; profile is left out when the contact already had every detail given. |
contact | object | The contact re-read after the change: identity, location, tags and the channels it is opted out of. created_at and status are not part of this read and stay null. |
id | object | theMarketer contact id. |
email | object | Email address; masked when the domain anonymizes. |
firstname | object | First name. |
lastname | object | Last name. |
phone | object | Phone number; masked when the domain anonymizes. |
city | object | City. |
country | object | Country. |
tags | string[] | Tags on the contact. |
created_at | object | Acquisition date, DD.MM.YYYY. |
status | object | Engagement status: active, inactive or cleaned. |
unsubscribed | string[] | Channels the contact has opted out of: any of email, sms, push, mobile_push, loyalty. Only channels the contact can use are listed (sms needs a phone, push a push token), matching what get_contact_details and update_contact show. |
note | object | Set when the contact already had every value given, so nothing was written and updated is empty. |
warnings | string[] | Requested changes that could not be applied, and why: a consent change for a channel the contact cannot use, or an email or phone edit on an account that anonymises contacts. Also names a custom field saved under its exact name when the case given differed. |
Unsubscribe contact
unsubscribe_contactDestructiveOpt one contact or many out of marketing channels, keeping the records.
First know which channels the user means. If they did not say, ask them before calling: every channel, or only some of email, SMS, push, loyalty? Use when the user explicitly wants contacts to stop receiving email, SMS, push or loyalty communication; confirm intent first, because this changes consent. Use delete_contact to remove the records themselves, and update_contact to re-subscribe.
One contact, chosen channels: pass email or contact_id, and channels. Only the requested channels change; existing opt-outs stay as they are. Channels the contact cannot use, such as SMS without a phone, come back in skipped. A channel in already_unsubscribed was already off before this call, opted out earlier or never opted in, not this call's doing: re-subscribing it is a separate, deliberate action through update_contact, never a repair of this result. To take many contacts off one channel only (for example SMS but not email), call this once per contact.
Many contacts at once, always every channel: pass contact_ids, a tag or a segment_id (several combine with AND). The first call answers needs_user_input with the one question to ask the user, even when they already named every channel: how many contacts match, what they lose and the first of them to check. Call again with the same selection, channels=["email", "sms", "push", "loyalty"] (as resume_arguments says), decision_token and decision_answers once they agreed. Nothing changes before that, and if the selection has changed meanwhile the question is asked again with the new count. A bulk unsubscribe replaces each contact's earlier choices with these four opt-outs, so an earlier opt-out from mobile push is cleared.
Parameters
| Parameter | Type | Description |
|---|
email | string | One contact: email address of the contact. Use contact_id
instead when the account masks addresses or several contacts
match. |
contact_id | string | One contact: theMarketer contact id (24 hex characters,
as list_contacts returns it). Pass this or email, not both. |
channels | enum[] | One contact: channels to opt out of, any of email, sms,
push, mobile_push, loyalty; omit to opt out of every channel
the contact can use. Bulk: optional on the first call,
required with decision_token, and then exactly email, sms,
push and loyalty. |
contact_ids | string[] | Bulk: theMarketer contact ids (24 hex characters each, as list_contacts returns them), up to 1000. |
tag | string | Bulk: every contact carrying this tag, matched as spelled in
the account's tag list; case is corrected when only one tag
matches; a tag the account's list does not have is matched
exactly as typed. The question says so either way. |
segment_id | string | Bulk: every contact in this custom segment, its id as
list_segments returns it (24 hex characters). |
decision_token | string | From a needs_user_input result of this tool,
together with decision_answers, the same selection and the
four channels; leave it out otherwise. |
decision_answers | object | The user's answer by decision key, e.g.
{"confirm": "proceed"}; only with decision_token. |
domain_id | string | Target domain. |
Returns
The operation's result, pending user questions, or cancellation.
Delete contact
delete_contactDestructiveDelete one contact, or many at once: records are hidden and suppressed, not erased.
Use when the user wants contacts gone and never contacted again; confirm intent first, because the records cannot be restored from here. To keep a record but stop marketing to it use unsubscribe_contact; to see what it holds first use get_contact_details.
One contact: pass email or contact_id; it is deleted at once.
Many contacts: pass contact_ids, a tag or a segment_id (several combine with AND). The first call answers needs_user_input with the one question to ask the user: how many contacts match, what the delete does to them and the first of them to check; call again with the same selection, decision_token and decision_answers once they agreed. Nothing is deleted before that, and if the selection has changed meanwhile the question is asked again with the new count. theMarketer then deletes the contacts in the background; the tool checks a few of them after a short wait, and deleted is false with a note when they were still listed or could not be read back, so check again with list_contacts a few minutes later.
The contacts are opted out of every channel, their names are reduced to initials, their other personal fields are cleared and the records are hidden from the audience. Email addresses and phone numbers stay on file so the addresses remain suppressed, so this is not erasure: when the user asks for personal data to be erased, say plainly that this tool suppresses the records and keeps the email and phone. The account owner's own contact cannot be deleted.
Parameters
| Parameter | Type | Description |
|---|
email | string | Single delete: email address of the contact. Use
contact_id instead when the account masks addresses or
several contacts match. |
contact_id | string | Single delete: theMarketer contact id (24 hex
characters, as list_contacts returns it). Pass this or email,
not both. |
contact_ids | string[] | Bulk: theMarketer contact ids (24 hex characters each, as list_contacts returns them), up to 1000. |
tag | string | Bulk delete: every contact carrying this tag, matched as
spelled in the account's tag list; case is corrected when only
one tag matches; a tag the account's list does not have is
matched exactly as typed. The question says so either way. |
segment_id | string | Bulk delete: every contact in this custom segment, its
id as list_segments returns it (24 hex characters). |
decision_token | string | From a needs_user_input result of this tool,
together with decision_answers and the same selection;
leave it out otherwise. |
decision_answers | object | The user's answer by decision key, e.g.
{"confirm": "proceed"}; only with decision_token. |
domain_id | string | Target domain. |
Returns
The operation's result, pending user questions, or cancellation.
Import contacts
import_contactsDestructiveAdd or refresh many contacts at once, as the import wizard does.
Use when the user has a list of contacts to add, from a spreadsheet, another tool or the conversation, and there are more than a handful; for a single contact use create_contact, which never overwrites. Every row needs an email or a phone, and every email must be a valid address. Send at most 1000 rows per call, and keep rows with an email and phone-only rows in separate calls; a phone-only batch creates SMS-only contacts.
Location fields are not accepted here; manage them in the authenticated theMarketer web app.
New contacts are imported without double opt-in, so a subscribed batch is live at once: confirm the user has permission. With update_existing=true, a row matching an existing contact overwrites the standard fields that row fills and keeps the ones it leaves out, replaces the contact's custom columns with the ones the row names (a row without custom clears them), resets its consent to the batch's and restores a contact removed with delete_contact. To do that, rows that fill different fields are sent as separate imports, at most 10 per call, each listed in imports. Tags apply to the whole call; without tags, updated contacts keep the tags they have. Sign-up automations fire; tag automations do not. Custom column labels must already exist in the account: unknown ones come back in columns_ignored. Addresses on placeholder domains such as example.com count as blacklisted, so test with real-looking domains.
The imports run in the background. status completed means the counts are in report; processing means contacts were still being written when this tool stopped waiting, and list_contacts will show them; awaiting_approval means a file was parked for manual approval and its rows were not imported yet; incomplete means the call stopped after some imports had started: never send the whole batch again, only the rows in rows_not_sent.
Parameters
| Parameter | Type | Description |
|---|
contactsrequired | object[] | The rows to import, 1 to 1000. Each needs email or
phone; the other fields are optional. A row with an email
that is not a valid address stops the call before anything is
sent, and the error names its index. On updated contacts only
the standard fields a row fills change. |
subscribe | boolean | True imports the batch as subscribed to every channel
the plan allows; False imports it as unsubscribed from all
channels, which is how a suppression list is loaded. Default: True. |
update_existing | boolean | True overwrites contacts already in the audience
with the batch's data (see above for how much that changes);
False leaves them untouched and counts them as duplicated. Default: True. |
tags | string[] | Tags for the whole call, applied to every new contact and
replacing the tags of every updated one. A tag that differs
only in case from one the account has takes the account's
spelling; tags the account does not have yet are added to its
tag list. Omit, or pass an empty
list, to import without tags: updated contacts then keep their
tags. An import cannot remove tags; update_contact with tags=[]
does that per contact. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
status | string | completed: every import finished and the counts are in report. processing: some contacts were still being written when this tool stopped waiting; they keep landing and list_contacts shows them. awaiting_approval: an import was parked for manual approval and its rows were not imported yet. incomplete: the call stopped after some imports had started; those keep running, and the rows in rows_not_sent were not imported. |
imports | object[] | The imports this call prepared, one per set of fields the rows fill when existing contacts are updated, otherwise one. |
import_id | string | theMarketer id of this import; its report page in the theMarketer app is /audience/contacts/import/report/<import_id>. |
status | string | This import's own status: completed, processing and awaiting_approval mean what they mean for the overall status; not_started means the call stopped before this import ran, so none of its rows were imported. |
rows_sent | integer | Rows in this import. |
columns_sent | string[] | The fields every row of this import fills, as the column labels sent. |
report | object | When completed: this import's counts per outcome. |
rows_sent | integer | Rows in the imports that started, across every import. |
rows_not_sent | integer[] | Indexes in contacts of the rows that were not imported because the call stopped part way; send only these rows again, never the ones already sent. Empty when every import started. |
recognized_contacts | integer | Rows theMarketer counted before importing, across the imports that started, invalid and blacklisted ones included; normally equals rows_sent. What became of each row is in report. |
columns_matched | string[] | Columns that will be imported, under the labels the account uses for them. |
columns_ignored | string[] | Columns sent that will not be imported: custom labels that do not exist as columns in this account, or that would have been read as a standard field. |
report | object | When every import that started has completed: the counts summed over them; each import's own counts and CSV links are under imports. |
note | string | What the status means for this call, how the rows were split into imports, and anything that was imported differently from what was sent. |
Get automation entries
get_entered_automationReadList the contacts who entered an automation on a given day.
Use to audit automation triggers: who entered which automation on a day. Use get_contact_details to look at one of the contacts, and get_automation_report for how many contacts an automation counted as entered: its entered is the settled count, while this list may also include contacts queued to enter.
Each entry is one contact entering one automation, ordered by entry time, with the contact's email, campaign_segment (the automation's name), barcode, mobile_install and subscribed_push; repeats of the same contact and automation name within a page are left out (rows of a deleted automation, which have no name, are all kept). Some days have no entry list, and note then says to use get_automation_report. No total is reported for this listing: has_more is true when the page came back full, so request the next page while it is true; the last page may turn out empty.
Parameters
| Parameter | Type | Description |
|---|
dayrequired | string | The day to inspect, YYYY-MM-DD. |
page | integer | Page number, starting at 1. Default: 1. |
per_page | integer | Items per page, between 1 and 100. Default: 50. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
entries | object[] | Entries on this page, ordered by entry time, one per contact and automation name: the contact's email, campaign_segment (the automation's name), barcode, mobile_install and subscribed_push. May include contacts queued to enter. |
count | integer | Entries returned on this page, after repeats of the same contact and automation name were left out. Not a total for the day: get_automation_report's entered is the settled count. |
page | integer | Page returned, starting at 1. |
has_more | boolean | True when this page came back full, so a further page may exist. No total is reported for this listing, so the next page can turn out empty. |
note | string | What this page can and cannot tell: whether the day has an entry list at all, that the list may include contacts queued to enter, and how many repeated rows were left out. |
Get audience options
get_audience_optionsReadLook up the values this domain uses (tags, countries, counties, cities, custom fields) and the conditions and values create_segment accepts here.
Use before list_contacts (its tag and custom_field filters), update_contact (its tags) or create_segment (its tag, country, county, city and custom:<label> conditions) whenever the exact spelling of a tag, country, county, city or custom field matters: filters and rules match values as stored, so a filter on "vip" finds nothing when the tag is "VIP Clienti". Countries are the codes stored on the contacts (usually ISO codes such as RO), not the ISO reference list. Before create_segment on an unfamiliar domain, call kind="segment_conditions", then kind="segment_values" with condition. Not for a parameter's fixed choices (channels, genders, statuses): those are in each tool's schema.
Without kind everything comes at once: tags, countries and custom fields in full, cities and counties 50 per page (one page walks both; see cities_total and counties_total), and the RFM groups with the name the tools accept, the label and the code. With kind only that list comes back, narrowed by search, 200 values per page with total, pages and has_more. kind="segment_conditions" reads the domain's live catalogue, 50 per page: only the conditions its plan allows plus its custom attributes (custom:<label>), each with its operators, what the value must be and a preview of the domain's values; unavailable names the conditions this domain cannot use and why. kind="segment_values" returns the domain's list for a condition, the fixed words of a choice condition, or, for products, categories and custom attributes (searched, not listed), the hits for search, required there; a condition that takes free text, a number or a window returns no values and a note saying what to pass.
Parameters
| Parameter | Type | Description |
|---|
kind | enum | Which list to return: tags, countries, counties, cities or
custom_fields for the domain's stored values;
segment_conditions for the create_segment conditions this
domain can use; segment_values for the values one condition
accepts (needs condition). Omit for the overview of every
stored-value list plus the RFM groups. One of: tags, countries, counties, cities, custom_fields, segment_conditions, segment_values. |
search | string | Text to look for, in the kind list or in every list
when kind is omitted. Case-insensitive: exact spellings and
substrings match, and when nothing does the closest spellings
come back instead, so kind="cities", search="cra" finds
Craiova and search="Bucharest" still finds Bucuresti. With
kind="segment_conditions" it matches the condition key, label
or tab; with kind="segment_values" it narrows the values and
is required for product, category and custom-attribute
conditions, which are searched by name (or SKU / id for
products), up to 20 hits. |
condition | string | Only with kind="segment_values": the create_segment
condition whose values you want, as its key from
segment_conditions (e.g. tag, segment, favorite_brand,
purchased_product, custom:Loyalty card). |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
kind | object | The one list requested, or null when every list was returned. |
search | object | The text the lists were narrowed by, or null. |
tags | string[] | Tags defined in this domain, spelled exactly as stored: the values list_contacts.tag, update_contact.tags and create_segment's tag condition take. theMarketer matches tags ignoring case but nothing else. |
countries | string[] | Country values actually stored on this domain's contacts (usually ISO codes such as RO), not the ISO reference list: the values create_segment's country condition takes, case-sensitive. |
counties | string[] | County or region values stored on this domain's contacts, spelled as create_segment's county condition compares them. One page: 50 in the overview, 200 with kind="counties"; see counties_total. |
counties_total | integer | Distinct counties in the domain (after search, when given), across all pages of counties. |
cities | string[] | City values stored on this domain's contacts, as spelled there: what create_segment's city condition must equal exactly. One page: 50 in the overview, 200 with kind="cities"; see cities_total. |
cities_total | integer | Distinct cities in the domain (after search, when given), across all pages of cities. |
custom_fields | string[] | Labels of the domain's custom contact columns: the values list_contacts.custom_field takes, and the <label> in create_segment's custom:<label> conditions. |
conditions | object[] | With kind="segment_conditions": the create_segment conditions this domain can use, 50 per page - only what its plan allows, with its custom attributes (custom:<label>) and, for conditions that take a value from a domain list, how many values exist and the first few. Empty otherwise. |
condition | string | The key to pass as create_segment's condition, e.g. tag, purchased_product or custom:Loyalty card for a custom attribute. |
tab | string | The web app's segment-builder tab the condition sits in, e.g. Subscriber data, E-commerce, Campaign activity. |
label | string | The condition's name in the web app. |
operators | string[] | The operators create_segment accepts for this condition; a single-operator condition may leave operator out. |
value | string | What create_segment's value must be for this condition, in words: a fixed set of choices, a value from a domain list, a number, a window, text, or nothing. |
options_total | object | For a condition that takes a value from one of the domain's lists (tags, brands, segments, cities, stores...): how many values exist; kind="segment_values" with this condition lists them. Null for other conditions, including products, categories and custom attributes, whose values are searched rather than listed. |
options_preview | string[] | The first 10 of those values, by label. Empty when options_total is null. |
note | object | How the condition is evaluated (window, case, what 'favorite' means), or null. |
unavailable | string[] | With kind="segment_conditions": the conditions of the static catalogue this domain cannot use, as condition: reason (e.g. 'nps: needs Ecommerce Pro'); create_segment answers those with the same reason. Not narrowed by search. |
condition | object | With kind="segment_values": the condition the values belong to, as its catalogue key (an alias or raw rule id is resolved to it). |
values | string[] | With kind="segment_values": what create_segment accepts as value for condition - the domain's values, as label (id) when the id differs from the label (create_segment takes either), the search hits for a product, category or custom-attribute condition, or the fixed words of a choice condition. Empty when the condition takes free text, a number or a window: the note then says what to pass. |
total | object | With kind: how many values (or conditions) matched, across all pages. Null in the overview, where cities_total and counties_total carry the counts. |
page | integer | Page returned, starting at 1. |
pages | integer | Total pages: of the kind list at 200 per page (50 for kind="segment_conditions"), or in the overview of whichever of cities (50 per page) and counties (50 per page) has more. |
has_more | boolean | True when a later page of a paged list exists; the note says which to ask for. |
note | object | Which page to ask for next when a list has more, and with kind="segment_values" what to pass as the value when the condition has no list to choose from; null when there is nothing to add. |
rfm_groups | object[] | Overview only: the RFM groups, each with the name the tools accept, the label shown in theMarketer and its code. The same for every domain. |
name | string | The value list_contacts.rfm_group and create_segment's rfm_group rule accept, e.g. champions, at_risk. |
label | string | How theMarketer labels the group in the web app and in list_contacts rows with fields='full', e.g. 'Can't lose them'. |
code | string | theMarketer's two-letter code for the group, as stored on the contact and inside segment rules, e.g. CH. |
List segments
list_segmentsReadList segments by name, inspect custom rules or get a recipient estimate.
Use when the user asks which segments exist, how large one is, or what rules define a custom segment, and before create_segment, to reuse a segment that already exists. To see who is in a custom segment, use list_contacts with its segment_id.
The listing comes 50 segments per page, newest first (built-in segments last), with total, pages and has_more; the note names the next page, and search narrows the list by name before paging. Names longer than 200 characters are shortened in the listing and end in …; segment_id returns the full name. Set include_rules=true to inspect custom criteria. Review all rules and how they combine before suggesting a segment; names alone do not establish a match.
Passing segment_id returns one custom or system segment and includes stored custom rules. It ignores page. Set include_count=true to get its email recipients_estimate before campaign exclusions and smart sending. Count lookup requires segment_id; it never counts an entire listing. The separate count values come from the last background evaluation, not from now: -1 means the count was not computed in this listing, which is not zero. System segments have ids starting with system-; their rules are not exposed by this tool. A rule_count of 0 for a system segment does not mean an unrestricted audience. System ids cannot be used as list_contacts.segment_id; custom segments (24-hex ids) can.
Parameters
| Parameter | Type | Description |
|---|
search | string | Text the segment name must contain, case-insensitive;
applies to system and custom segments alike. Omit to list
every segment. |
segment_id | string | Id from this listing: 24 hex characters for a custom
segment, or system-... for a built-in segment. Returns one
segment with its stored custom rules; ignores page and search. |
include_rules | boolean | Also return each custom segment's rules in
readable form when listing. Off by default to keep the list
short. Default: False. |
include_count | boolean | Load the email recipients_estimate for segment_id.
Requires a single segment id. Does not overwrite stored count. Default: False. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
segments | object[] | The segments on this page, newest first; built-in segments come after the custom ones. |
id | object | Segment id. Custom segments have a 24-hex id usable as list_contacts.segment_id; system segments have a 'system-...' id that list_contacts cannot filter by. |
name | object | Segment name as shown in theMarketer. |
type | string | 'Custom' for segments built from rules, 'System' for theMarketer's built-in ones (activity, gender, RFM, frequency, ...). |
is_system | boolean | True for built-in segments. Their rules are not exposed by this tool; their ids cannot be used with list_contacts. |
recipients_estimate | object | Email recipient estimate loaded on request for one segment with include_count=true. Before campaign exclusions and smart sending; null when not requested or unavailable. Separate from stored count values. |
locked | boolean | True when membership is frozen: theMarketer refreshes the count but no longer adds or removes contacts. |
health | object | Average engagement health of the members, 0-10. |
last_processed | object | When theMarketer last evaluated the segment; null for a custom segment whose first background run has not happened yet. |
count | map<integer> | Members per channel (email, sms, push, mobile_push) from the last evaluation. -1 means the count was not computed in this listing, not zero; system segments can report -1 here. |
rule_count | integer | Number of stored custom rules; 0 for system segments, whose rules are not exposed by this tool. |
rules | object | The rules in readable form, one per line, only when include_rules or segment_id was passed; null otherwise. |
rule_operator | object | How the rules combine: 'all' (every rule must match) or 'any' (one is enough); null for system segments. |
total | integer | Segments matching the supplied filters, across all pages. |
page | integer | Page returned, starting at 1. |
pages | integer | Total pages at 50 segments each. |
per_page | integer | Segments per page, fixed at 50. |
has_more | boolean | True when a later page exists; the note says which to ask for. |
note | object | Pagination instructions, and whether long names were shortened; null when no further guidance is needed. |
Create segment
create_segmentWriteCreate a custom segment from rules; theMarketer evaluates membership in the background.
Use when the user requests an independent segment. For a campaign needing a new segment, pass new_segment to campaign_wizard instead. Never create one for a one-off count or list; use list_contacts with filters. Check list_segments for an existing match. The first call writes nothing and asks for confirmation; return segment_operation, decision_token and decision_answers.create_segment='create' after the user confirms. Name and rules may be omitted on resume.
Rules take a condition, an operator (omit when only one exists) and a value; some also take unit, campaign_id or max_value. Discover conditions and operators with get_audience_options(kind="segment_conditions"), and values with get_audience_options(kind="segment_values", condition=..., search=...). Names resolve to ids; ambiguous or unknown values return suggestions. Examples: {"condition":"tag","operator":"is","value":"VIP"}; {"condition":"shopper_status","operator":"did_not_buy_in_last","value":6,"unit":"months"}; {"condition":"purchased_category","value":["Shoes > Men"]}.
An equivalent segment is reused unless allow_duplicate=true. The result lists the resolved rules. identity_pending means the id or creation result could not be verified: do not repeat creation. Evaluation is asynchronous; list_segments shows its last_processed and counts. Membership updates can trigger existing automations. lock freezes membership after evaluation. With match="all" every rule must hold; with match="any" one is enough.
Parameters
| Parameter | Type | Description |
|---|
name | string | Segment name, at most 120 characters. Required on the first
call; omit on resume to keep the prepared name. |
rules | object[] | Conditions for membership. Required on the first call;
omit on resume to keep the prepared rules. |
match | enum | 'all' requires every rule; 'any' requires one. Defaults to
'all' for a new operation; omitted on resume keeps its choice. One of: all, any. |
lock | boolean | Freeze membership after its first evaluation. Defaults to
false; omitted on resume keeps its choice. |
allow_duplicate | boolean | Create even when equivalent rules and lock already
exist. Defaults to false; omitted on resume keeps its choice. |
skip_value_check | boolean | Skip domain value lookups only for known stored
values, such as a tag an unfinished import is creating. Defaults
to false; omitted on resume keeps its choice. |
segment_operation | string | Short handle returned in resume_arguments; pass
it unchanged on every continuation, even after an error. |
decision_token | string | Token returned with the pending confirmation. |
decision_answers | object | User answers by question key; create_segment=create
only after the user confirms the displayed rules and effects. |
domain_id | string | Target domain. |
Returns
The operation's result, pending user questions, or cancellation.
Get audience evolution
get_audience_evolutionReadGet the audience headcount per channel and the last 7 days' joins and losses.
Use when the user asks how many contacts they have on email, SMS, push or loyalty, or how many joined or left recently. Use get_audience_breakdown for list health (active, inactive, bounced, cleaned) rather than headcount, and get_audience_history for a day-by-day history over a custom date range.
For each channel, contacts is the current headcount (contacts with that channel's identifier who are not opted out of it), and joined_last_7_days and lost_last_7_days count subscriptions and unsubscriptions in a rolling 7-day window ending now. The loyalty headcount is 0 on plans without the loyalty program. A metric that could not be computed reads {"unavailable": <reason>} while the others still answer, and note names it.
Parameters
| Parameter | Type | Description |
|---|
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
email | object | Email channel: contacts with an address who are not opted out of email. |
contacts | object | Contacts currently subscribed on this channel: they have the channel's identifier (email address, phone, push token) and are not opted out of it. An integer, or {"unavailable": <reason>} when this one metric could not be computed (the others are unaffected). |
joined_last_7_days | object | Contacts who subscribed to this channel in the last 7 days (rolling window ending now). An integer, or {"unavailable": <reason>} when this one metric could not be computed (the others are unaffected). |
lost_last_7_days | object | Contacts who unsubscribed from this channel in the last 7 days (rolling window ending now). An integer, or {"unavailable": <reason>} when this one metric could not be computed (the others are unaffected). |
sms | object | SMS channel: contacts with a phone number who are not opted out of SMS. |
contacts | object | Contacts currently subscribed on this channel: they have the channel's identifier (email address, phone, push token) and are not opted out of it. An integer, or {"unavailable": <reason>} when this one metric could not be computed (the others are unaffected). |
joined_last_7_days | object | Contacts who subscribed to this channel in the last 7 days (rolling window ending now). An integer, or {"unavailable": <reason>} when this one metric could not be computed (the others are unaffected). |
lost_last_7_days | object | Contacts who unsubscribed from this channel in the last 7 days (rolling window ending now). An integer, or {"unavailable": <reason>} when this one metric could not be computed (the others are unaffected). |
loyalty | object | Loyalty channel: contacts with an address who are not opted out of loyalty; 0 on plans without the loyalty program. |
contacts | object | Contacts currently subscribed on this channel: they have the channel's identifier (email address, phone, push token) and are not opted out of it. An integer, or {"unavailable": <reason>} when this one metric could not be computed (the others are unaffected). |
joined_last_7_days | object | Contacts who subscribed to this channel in the last 7 days (rolling window ending now). An integer, or {"unavailable": <reason>} when this one metric could not be computed (the others are unaffected). |
lost_last_7_days | object | Contacts who unsubscribed from this channel in the last 7 days (rolling window ending now). An integer, or {"unavailable": <reason>} when this one metric could not be computed (the others are unaffected). |
push | object | Web push channel: contacts with a push token who are not opted out of push. |
contacts | object | Contacts currently subscribed on this channel: they have the channel's identifier (email address, phone, push token) and are not opted out of it. An integer, or {"unavailable": <reason>} when this one metric could not be computed (the others are unaffected). |
joined_last_7_days | object | Contacts who subscribed to this channel in the last 7 days (rolling window ending now). An integer, or {"unavailable": <reason>} when this one metric could not be computed (the others are unaffected). |
lost_last_7_days | object | Contacts who unsubscribed from this channel in the last 7 days (rolling window ending now). An integer, or {"unavailable": <reason>} when this one metric could not be computed (the others are unaffected). |
note | object | Set when at least one metric is unavailable, naming which. Null when all twelve numbers are present. |
Get audience breakdown
get_audience_breakdownReadGet the health of the email list: engaged, dormant, bounced, blacklisted and cleaned contacts.
Use when the user asks how healthy or clean their list is, how many contacts are active versus inactive, or how many bounced, were blacklisted, were cleaned or unsubscribed from everything. These are deliverability counts, not headcounts: use get_audience_evolution for how many contacts each channel has, and list_contacts with engagement="active", "inactive" or "cleaned" to see who is in a bucket.
active_email and inactive_email split the reachable email contacts (address present, not opted out, not blacklisted, not cleaned) by whether they ever opened, clicked or were tracked on site. bounced are hard-bounced addresses opted out of email, manually_unsubscribed are contacts opted out of every channel, and blacklisted and cleaned are the addresses flagged by the blacklist and by the automatic list cleanup. A bucket that could not be computed reads {"unavailable": <reason>} while the others still answer.
Parameters
| Parameter | Type | Description |
|---|
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
active_email | object | Reachable email contacts (address present, not opted out of email, not blacklisted, not cleaned) that have engaged at least once: more than zero opens, clicks or tracked site views. An integer, or {"unavailable": <reason>} when this one bucket could not be computed (the others are unaffected). |
inactive_email | object | The same reachable email contacts with no engagement at all: zero opens, clicks and site views. active_email + inactive_email is the reachable email list. An integer, or {"unavailable": <reason>} when this one bucket could not be computed (the others are unaffected). |
bounced | object | Contacts whose address hard-bounced: they are flagged bounced and opted out of email. An integer, or {"unavailable": <reason>} when this one bucket could not be computed (the others are unaffected). |
manually_unsubscribed | object | Contacts opted out of every channel at once (email, SMS, push and loyalty) after having been subscribed; contacts that never subscribed are not counted. An integer, or {"unavailable": <reason>} when this one bucket could not be computed (the others are unaffected). |
blacklisted | object | Contacts flagged blacklisted; they are excluded from active_email and inactive_email. An integer, or {"unavailable": <reason>} when this one bucket could not be computed (the others are unaffected). |
cleaned | object | Contacts removed by the automatic list cleanup: they ignored the configured number of recent campaigns and the plain-text re-engagement emails that follow, so they were flagged cleaned and opted out of email. An integer, or {"unavailable": <reason>} when this one bucket could not be computed (the others are unaffected). |
note | object | Set when at least one bucket is unavailable, naming which. Null when all six counts are present. |
Analyze audience
analyze_audienceReadAnalyze the customer base: RFM groups, purchase frequency and the on-site funnel.
Use for "how do my customers look" questions: how customers spread across RFM groups (champions, loyal, at risk, lost...), how many buy once versus repeatedly, and where visitors drop out between the homepage and an order. To see the contacts behind a number use list_contacts with rfm_group or funnel_stage; for headcounts use get_audience_evolution and for list health get_audience_breakdown.
These are the three analyses of the Audience pages RFM analysis, Frequency analysis and Funnels, read as the account computes them: RFM and frequency are refreshed at most every two hours over the analysis period configured in the account, and the funnel covers the last three months. This tool only reads them and never changes that period. An analysis that could not be loaded reads {"unavailable": <reason>} while the other two still answer.
Parameters
| Parameter | Type | Description |
|---|
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
rfm | object | RFM analysis (Audience > RFM analysis): aov is the average order value over the analysis period; chart is the distribution of customers across the RFM groups (champions, loyal, at risk, hibernating, lost... - the same groups list_contacts filters by with rfm_group), with each group's count and average order value; flow is how customers moved between groups; timespan is the number of years of orders considered. Refreshed at most every two hours. As the Audience page shows it, or {"unavailable": <reason>} when this one analysis could not be loaded (the others are unaffected). |
frequency | object | Purchase-frequency analysis (Audience > Frequency analysis): chart has one entry per band F1 to F6 - customers with exactly 1, 2, 3, 4, 5 and more than 5 orders - each with its count; timespan is the number of years of orders considered. As the Audience page shows it, or {"unavailable": <reason>} when this one analysis could not be loaded (the others are unaffected). |
funnels | object | On-site funnel over the last three months (Audience > Funnels): one entry per stage - view_homepage, view_category, search, view_product, add_to_cart, initiate_checkout, order - with visitors (contacts who reached the stage), dropOffs (contacts whose last event was this stage), percentage and dropOffsPercentage. As the Audience page shows it, or {"unavailable": <reason>} when this one analysis could not be loaded (the others are unaffected). |
note | object | Set when at least one analysis is unavailable, naming which. Null when all three are present. |
Automations14
List automations
list_automationsReadList the account's automated journeys (automations) with their status, trigger, objective and headline results, newest first.
Use when the user asks which automations exist, which are running or paused, how a journey is doing, or whenever you need an automation id for the other automation tools. For one journey's steps and content use get_automation_details; for its per-step and per-contact figures use get_automation_report.
Each row carries the id, name, status (draft, running, paused) with status_label, the objective, the trigger key and its editor label, created and updated times, currency and stats for the chosen period: contacts entered, waiting in the journey (in_progress), completed, messages sent with unique opens and clicks (summed over the channels), transactions, revenue and its growth against the previous period, and under channels each channel's own sent, unique opens and clicks, their rates in percent, transactions, conversion rate and revenue; only channels with activity are listed, so a channel absent from channels sent nothing in the period. Rows come 20 per page; theMarketer reports no total, so has_more is true when the page came back full and the note names the next page. The period changes the figures only, never which journeys are listed; start_date and end_date give the calendar days it covered.
Parameters
| Parameter | Type | Description |
|---|
status | enum | Which journeys to list: all, running, paused or draft.
Omit for all. One of: all, running, paused, draft. Default: 'all'. |
search | string | Case-insensitive text the journey name must contain. Omit
to list every journey. |
objective | string | Only journeys with this objective, spelled as
get_automation_options kind=objectives lists them (e.g.
"Recover abandoned carts"). Omit for every objective. |
period | enum | The window the stats cover: today, yesterday,
this_week, last_week, this_month, last_month, last_30_days
(default), last_60_days or last_90_days. One of: today, yesterday, this_week, last_week, this_month, last_month, last_30_days, last_60_days, last_90_days. Default: 'last_30_days'. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
automations | object[] | The journeys on this page, newest created first. |
id | string | theMarketer id of the automation. |
name | object | Journey name. |
status | object | draft, running or paused. |
status_label | object | The status as the theMarketer app words it. |
objective | object | The objective chosen for the journey, if any. |
trigger | object | Trigger key as get_automation_options kind=triggers lists it (e.g. cart_abandonment); null until the journey is saved. |
trigger_label | object | The trigger's name in the editor. |
created_at | object | When the journey was created (UTC). |
updated_at | object | When it was last saved (UTC). |
stats | object | Figures for the requested period: the journey as a whole, and each channel under channels. |
entered | integer | Contacts that entered the journey in the period. |
in_progress | integer | Contacts waiting inside the journey right now (in a delay or before a webhook), whatever the period; meaningful for running journeys. |
completed | integer | Contacts that reached the end in the period. |
sent | integer | Messages sent, every channel together. |
unique_opens | integer | Contacts who opened at least one message, summed over the channels. |
unique_clicks | integer | Contacts who clicked at least one message, summed over the channels. |
transactions | integer | Orders attributed to the journey. |
revenue | number | Attributed revenue in currency. |
growth | object | Revenue change against the previous period of the same length, in percent. |
channels | map<object> | The figures per channel (email, sms, push, mobile_push), with the open, click and conversion rates. Only channels with activity are listed: a channel absent from here sent nothing in the period. |
currency | object | Currency of stats.revenue. |
period | string | The period the stats cover. |
start_date | string | First day period covers (YYYY-MM-DD, inclusive). |
end_date | string | Last day period covers (inclusive). |
page | integer | Page returned, starting at 1. |
per_page | integer | Journeys per page, fixed at 20. |
has_more | boolean | True when this page came back full, the only signal theMarketer gives: it reports no total, so the next page may still be empty. |
note | object | Which page to ask for next when there may be more; null when this page is the last. |
Get automation details
get_automation_detailsReadEverything configured on one automated journey: its trigger with settings, the steps in flow order with their ids, which email steps have a saved body, and on request the HTML of one email step.
Use when the user asks what an automation does or how it is set up, before update_automation to see the current trigger and steps (the flow is in the exact shape those tools take, ids included), or to read an email's copy. Whether a journey is ready to start is not decided here: start_automation with dry_run=true runs every start check and never starts it, and its real call asks the user before anything starts. Find the id with list_automations. Performance figures are in get_automation_report.
The result carries name, status with status_label, objective, created and updated times, links.app_url to open the editor, and flow: the trigger (type, run mode, entry window in the shop's timezone, trigger-specific fields) and nested steps - email, sms, push, mobile_push, delay, filter (with yes / no branches), split (a / b), add_tags, remove_tags, unsubscribe, start_automation, webhook - plus orphans not connected to the trigger and notes (what could not be read back exactly, a filter condition that checks a message step which is not in this journey, and a start_automation step whose journey was deleted). A step the tools do not edit reads as type 'kept' with a summary. Email steps in flow carry has_content, not their body; the body is read with email_step_id. email_steps lists each email step with its subject, branch, has_content and the blocks its body holds. With email_step_id the saved HTML of that step comes as email_content, 80 lines per page (a line longer than 200 characters is cut only where a line break changes nothing) with pages and a note naming the next page; each block in it shows as its placeholder and its options come in email_content.blocks, so the lines joined with newlines and the blocks can be passed back to update_automation as they are, unless notes name a block the tools cannot write back in that email. Without it the body is not fetched.
Parameters
| Parameter | Type | Description |
|---|
automation_idrequired | string | The automation's id from list_automations (24 hex
characters). |
email_step_id | string | Id of one email step of this journey (from
email_steps) whose saved HTML you want; omit to skip the
body. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
automation_id | string | theMarketer id of the automation. |
name | object | Journey name. |
status | object | draft, running or paused. |
status_label | object | The status as the theMarketer app words it. |
objective | object | The objective chosen for the journey, if any. |
created_at | object | When the journey was created (UTC). |
updated_at | object | When it was last saved (UTC). |
links | object | Where to open this journey in the theMarketer web app: app_url opens its editor, and switch_domain_url comes first for accounts with several domains. |
flow | object | The journey as create_automation / update_automation take it: trigger with its settings and trigger_label, steps nested in flow order (a filter carries yes / no, a split a / b), each step with its id; a step of a kind these tools do not edit reads as type 'kept' with a summary. An email step carries has_content instead of its body. orphans are steps not connected to the trigger; notes say what could not be read back exactly. The whole flow can be passed back to update_automation as it is: an email step passed back without html keeps its saved body (read it with get_automation_details email_step_id). |
steps_count | integer | Steps reachable from the trigger, orphans excluded. |
email_steps | object[] | Every email step with its subject and whether a body is saved; a journey cannot start while an email step has no body. |
email_content | object | The saved HTML of the step named by email_step_id, 80 lines per page; null when no step was asked for. |
Preview automation email
preview_automation_emailReadShow one email step of an automation as a contact would receive it: placeholders filled in, products taken from the shop's catalogue, links resolved.
Use after create_automation or update_automation saved an email body, and before start_automation, to see the real result and whether anything is still wrong; get_automation_details shows the saved source instead. The email is rendered for a sample contact (the signed-in user's address) with real products from the catalogue, and nothing is sent. rendered carries the HTML 80 lines per page (a line longer than 200 characters cut only where a line break changes nothing) with pages and a note naming the next page. check says whether the email is fit to send: placeholders left unfilled, product slots that stayed empty, a missing unsubscribe link, and a note on what to fix; it covers the whole email whatever page is shown. Its warnings name each filtered product block that too few products in stock meet, with at most how many do (the remaining places are filled with the newest products in stock), each one with a price no product of the catalogue reaches, and each one whose filters the rendering cannot confirm otherwise, such as a price some products may meet; a block that enough products meet needs no warning. A products-from-the-trigger block is warned only for a price no product of the catalogue reaches, since its filters apply only when the event that started the journey carries no products.
The step must be an email step of this journey with a saved body; without one the call says so and names update_automation. Products come from the shop's catalogue rather than from one contact's cart or orders, so a block fed by the trigger shows catalogue products here and the contact's own once the journey runs. When the email has a countdown block, previewing also prepares its countdown images.
Parameters
| Parameter | Type | Description |
|---|
automation_idrequired | string | The automation's id from list_automations (24 hex
characters). |
step_idrequired | string | Id of the email step to render, as get_automation_details
lists it under email_steps. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
automation_id | string | The automation the step belongs to. |
step_id | string | The email step that was rendered. |
subject | object | Subject line saved on the step; null when none is saved yet. |
rendered | object | The rendered HTML, 80 lines per page, with the page counters and a note naming the next page. |
lines | string[] | Lines of the rendered email for this page; join them with newlines to get the HTML back; a line longer than 200 characters is cut only where a line break changes nothing (between table tags or at a space), so a line with no such place stays longer. |
total_lines | integer | Lines in the whole rendered email. |
content_total_chars | integer | Characters in the whole rendered email. |
page | integer | Page returned, starting at 1. |
pages | integer | Total pages of lines. |
per_page | integer | Lines per page, fixed at 80 (about 16000 characters at most, more when a line cannot be cut). |
has_more | boolean | True when a later page exists. |
note | object | Which page to ask for next when there is one; null otherwise. |
check | object | Whether the email is fit to send, and what to fix when not; it covers the whole email whatever page was asked for. |
ok | boolean | True when nothing needs fixing: every placeholder was filled, every product slot shows a product and the unsubscribe link works. |
unresolved_tokens | string[] | Placeholders left as written in the rendered email, such as {{first_name}} inside an attribute or a block where it is not filled, each once in order of appearance; a contact would see them as text. A misspelt placeholder is not listed here: it renders as nothing, and the email step's warnings name it when the body is written. |
empty_product_slots | string[] | Product slots that rendered without a product image or name, named by block and position: the catalogue had nothing to put there, or the slot asks for more products than the block provides. |
missing_unsubscribe | boolean | True when the rendered email has no working unsubscribe link; every marketing email needs one. |
note | object | One sentence on what to fix and how; null when the email is fit to send. |
warnings | string[] | What is worth checking by eye: a filtered product block that too few products meet, so the newest products in stock fill the remaining places, one with a price no product reaches, or one whose filters the rendering cannot confirm; empty when there is nothing to check. |
note | string | What the preview shows (a sample contact, catalogue products, nothing sent), the verdict of check, and what the email's discount codes read as here. |
Get automation report
get_automation_reportReadHow one automated journey performed over a period: contacts entered and completed, sends, opens, clicks, orders and revenue per channel and per step, and on request who a message step reached.
Use when the user asks how an automation is doing, which step loses contacts, how a specific email or SMS in the journey performs, or who received it. Find the id with list_automations, whose rows already carry headline figures; come here for the breakdown. For the journey's setup use get_automation_details.
The result carries totals (entered, completed, waiting inside the journey right now, about_to_enter), channels (email, sms, push, mobile_push with counters and rates in percent) and steps: one entry per step in flow order with its id, kind, a readable label, the branch it sits in and its counters (entered, exited, yes/no for filters, sends, opens, clicks, orders, revenue and rates for message steps; 0 where no contact reached the step in the period, which the note then says). With step_id the recipients of that message step come 25 per page with email or phone, opened, clicked, orders and revenue; theMarketer reports no total, so has_more means the page came back full. Dates are whole days in Romanian time (Europe/Bucharest).
Parameters
| Parameter | Type | Description |
|---|
automation_idrequired | string | The automation's id from list_automations (24 hex
characters). |
start_date | string | First day of the period (YYYY-MM-DD). Give it with
end_date, or omit both for the last 30 days. |
end_date | string | Last day of the period (YYYY-MM-DD), inclusive; not
before start_date. |
step_id | string | Id of an email, sms, push or mobile_push step of this
journey (from steps or get_automation_details) whose
recipients you want; omit to skip the per-contact rows. The
recipient list is kept for about 180 days, so a period older
than that lists no one while the step's figures still count
its sends. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
automation_id | string | theMarketer id of the automation. |
name | object | Journey name. |
status | object | draft, running or paused. |
status_label | object | The status as the theMarketer app words it. |
trigger_label | object | The trigger's name in the editor. |
start_date | string | First day of the period (inclusive). |
end_date | string | Last day of the period (inclusive). |
totals | object | Contacts entered, completed, waiting. |
entered | integer | Contacts that entered the journey. |
completed | integer | Contacts that reached the end. |
waiting | object | Contacts inside the journey right now (in a delay or before a webhook), whatever the period; null when it could not be read this time. |
about_to_enter | integer | Contacts whose trigger event is scheduled and will enter once its wait window passes (cart and checkout abandonment, form abandonment, inactivity). |
note | object | Set when waiting is null: the number of contacts waiting could not be read this time; the other figures are complete. |
channels | object | Sends, opens, clicks, orders, revenue and rates per channel. |
email | object | Email. |
sent | integer | Messages sent. |
opens | integer | Total opens, repeats included. |
unique_opens | integer | Contacts who opened at least once. |
clicks | integer | Total clicks, repeats included. |
unique_clicks | integer | Contacts who clicked at least once. |
orders | integer | Orders attributed to the channel. |
revenue | number | Attributed revenue. |
undelivered | integer | Bounces. |
complaints | integer | Spam complaints. |
unsubscribes | integer | Unsubscribes. |
aov | object | Average value of the attributed orders. |
delivery_rate | object | Delivered / sent, in percent. |
open_rate | object | Opens / delivered, in percent. |
unique_open_rate | object | Unique opens / delivered, in percent. |
click_rate | object | Clicks / opens for email and mobile push, clicks / sent for SMS and web push, in percent. |
unique_click_rate | object | Unique clicks on the same basis, in percent. |
bounce_rate | object | Undelivered / sent, in percent. |
conversion_rate | object | Orders / clicks, in percent. |
unsubscribe_rate | object | Unsubscribes / sent, in percent. |
sms | object | SMS. |
sent | integer | Messages sent. |
opens | integer | Total opens, repeats included. |
unique_opens | integer | Contacts who opened at least once. |
clicks | integer | Total clicks, repeats included. |
unique_clicks | integer | Contacts who clicked at least once. |
orders | integer | Orders attributed to the channel. |
revenue | number | Attributed revenue. |
undelivered | integer | Bounces. |
complaints | integer | Spam complaints. |
unsubscribes | integer | Unsubscribes. |
aov | object | Average value of the attributed orders. |
delivery_rate | object | Delivered / sent, in percent. |
open_rate | object | Opens / delivered, in percent. |
unique_open_rate | object | Unique opens / delivered, in percent. |
click_rate | object | Clicks / opens for email and mobile push, clicks / sent for SMS and web push, in percent. |
unique_click_rate | object | Unique clicks on the same basis, in percent. |
bounce_rate | object | Undelivered / sent, in percent. |
conversion_rate | object | Orders / clicks, in percent. |
unsubscribe_rate | object | Unsubscribes / sent, in percent. |
push | object | Web push notifications. |
sent | integer | Messages sent. |
opens | integer | Total opens, repeats included. |
unique_opens | integer | Contacts who opened at least once. |
clicks | integer | Total clicks, repeats included. |
unique_clicks | integer | Contacts who clicked at least once. |
orders | integer | Orders attributed to the channel. |
revenue | number | Attributed revenue. |
undelivered | integer | Bounces. |
complaints | integer | Spam complaints. |
unsubscribes | integer | Unsubscribes. |
aov | object | Average value of the attributed orders. |
delivery_rate | object | Delivered / sent, in percent. |
open_rate | object | Opens / delivered, in percent. |
unique_open_rate | object | Unique opens / delivered, in percent. |
click_rate | object | Clicks / opens for email and mobile push, clicks / sent for SMS and web push, in percent. |
unique_click_rate | object | Unique clicks on the same basis, in percent. |
bounce_rate | object | Undelivered / sent, in percent. |
conversion_rate | object | Orders / clicks, in percent. |
unsubscribe_rate | object | Unsubscribes / sent, in percent. |
mobile_push | object | Mobile push notifications. |
sent | integer | Messages sent. |
opens | integer | Total opens, repeats included. |
unique_opens | integer | Contacts who opened at least once. |
clicks | integer | Total clicks, repeats included. |
unique_clicks | integer | Contacts who clicked at least once. |
orders | integer | Orders attributed to the channel. |
revenue | number | Attributed revenue. |
undelivered | integer | Bounces. |
complaints | integer | Spam complaints. |
unsubscribes | integer | Unsubscribes. |
aov | object | Average value of the attributed orders. |
delivery_rate | object | Delivered / sent, in percent. |
open_rate | object | Opens / delivered, in percent. |
unique_open_rate | object | Unique opens / delivered, in percent. |
click_rate | object | Clicks / opens for email and mobile push, clicks / sent for SMS and web push, in percent. |
unique_click_rate | object | Unique clicks on the same basis, in percent. |
bounce_rate | object | Undelivered / sent, in percent. |
conversion_rate | object | Orders / clicks, in percent. |
unsubscribe_rate | object | Unsubscribes / sent, in percent. |
steps | object[] | One entry per step in flow order (a branch right after its step, yes before no), each labelled; a step no contact reached in the period shows 0 in the counters its kind has, and null marks a counter the kind does not have. |
step_id | string | The step's id, as get_automation_details shows it; for a message step pass it as step_id to list its recipients. |
type | string | Step kind: email, sms, push, mobile_push, delay, filter, split, add_tags, remove_tags, unsubscribe, start_automation, webhook or kept. |
label | string | The step in words (subject, wait, conditions). |
branch | string | '' on the main path, else the branch path such as 'no' or 'yes.a' ('branch_1' / 'branch_2' under a kept filter or split); 'orphan' when the step is not connected to the trigger. |
entered | object | Contacts that reached the step. |
exited | object | Contacts that moved on from the step. |
yes | object | Filter steps: contacts that matched. |
no | object | Filter steps: contacts that did not match. |
sent | object | Message steps: sent. |
opens | object | Message steps: opens. |
unique_opens | object | Message steps: contacts who opened. |
clicks | object | Message steps: clicks. |
unique_clicks | object | Message steps: contacts who clicked. |
orders | object | Message steps: attributed orders. |
revenue | object | Message steps: attributed revenue. |
undelivered | object | Message steps: bounces. |
unsubscribes | object | Message steps: unsubscribes. |
open_rate | object | In percent. |
unique_open_rate | object | In percent. |
click_rate | object | In percent. |
unique_click_rate | object | In percent. |
conversion_rate | object | In percent. |
unsubscribe_rate | object | In percent. |
survey | object | Email steps that carry a poll: one entry per question with type, options, interactions, responses and stat (count and percent per option); null otherwise. |
recipients | object | With step_id: the contacts that message step reached in the period, 25 per page; null otherwise. |
note | object | Set when some steps have no figures for the period: no contact reached them, and their counters read 0. Null otherwise. |
Get automation options
get_automation_optionsReadLook up what this domain can build automated journeys from: the triggers, filter conditions and step kinds its plan allows (with the fields each takes), the objectives, the email senders, and the domain's own value lists (tags, segments, products, categories, brands, campaigns, order statuses, forms, surveys, custom events, attributes, loyalty tiers, email providers, locations, journeys that can be started by another journey).
Use before create_automation or update_automation to pick a valid trigger key, condition key, step type or sender, and whenever a value's exact spelling matters (a tag, a segment, an order status). Not for a journey's own steps: those are in get_automation_details.
kind=triggers lists each trigger with its key, category, when it fires and needs_tracking (it fires on website activity reported by the theMarketer tracking script); with search (e.g. the trigger key) each one found also carries its fields (required first, with the values_field to look values up) and the general settings it offers. kind=conditions lists each filter condition with operators, what value must be, fixed choices, what an operator or choice word stands for when the word alone does not say it (operator_meanings, choice_meanings), the values_field for list values, and applies_to when it only works after certain triggers; the domain's contact attributes (custom:<Label>) and product attributes (product_attribute:<Label>) are included. kind=actions lists the step kinds with their fields and consequences. Triggers, conditions and actions show only what the domain can use; the unavailable lines say which groups need a plan or feature it lacks. kind=objectives and kind=senders are short lists. kind=email_blocks lists the blocks an automation email can hold (products filled in for each contact) with their options, the personalisation placeholders and the rules for placing blocks in the HTML, and the account's brand (logo, social links, contact e-mail, colours, whether it saved a footer, whether Aqurate recommendations are connected, the language its emails are set to) for HTML that matches it; the blocks' default texts follow that language, so write the email's own text in it too. With trigger, it says whether that trigger's event carries products. kind=discount_templates lists the designs a Discount block can show, 20 per page, in the account's language, narrowed by industry, event and tags, with the values those filters take; the filters combine, so a design shows only when it matches all of them. Each design is a picture behind its preview_url link, which you cannot see: give the user the links and wait for their pick before writing the block; choose one yourself only when the user left the choice to you. kind=values needs field and returns id and label pairs, 200 per page, narrowed by search; products are searched (search required), categories and campaigns are searched when search is given and listed otherwise.
Parameters
| Parameter | Type | Description |
|---|
kindrequired | enum | Which list: triggers, conditions, actions, objectives,
senders, values (with field), email_blocks (the blocks
and placeholders an automation email can use), or
discount_templates (the designs of the Discount block). One of: triggers, conditions, actions, objectives, senders, values, email_blocks, discount_templates. |
field | enum | With kind=values, which list: tags, segments, brands,
categories, products, campaigns_email, campaigns_sms,
campaigns_push, order_statuses, forms, surveys,
custom_events, custom_attributes, product_attributes,
loyalty_tiers, email_providers, countries, counties, cities
or automations (journeys another journey can start). One of: tags, segments, brands, categories, products, campaigns_email, campaigns_sms, campaigns_push, order_statuses, forms, surveys, custom_events, custom_attributes, product_attributes, loyalty_tiers, email_providers, countries, counties, cities, automations. |
search | string | Text to narrow the list by, case-insensitive: for
triggers it matches key, label or category, or whole words
of when the trigger fires (e.g. coupon finds
code_expiration); for actions key, label or category; for
conditions also, as whole words, an operator that names a
state (e.g. buyer finds shopper_status) or one of the fixed
choices and its editor label; for values it matches the
label (closest spellings when nothing contains it), and for
products, categories and campaigns it is sent to the search
itself. |
trigger | string | With kind=email_blocks, the trigger key of the journey
the email is for (e.g. cart_abandonment), to learn whether
its event carries products. Omit when that does not matter. |
industry | string | With kind=discount_templates, only the designs made for
this industry, by name or id (the result lists them); with
event or tags too, a design must match every filter. |
event | string | With kind=discount_templates, only the designs made for
this occasion (e.g. Black Friday), by name or id. |
tags | string[] | With kind=discount_templates, only the designs with any of
these tags (e.g. red), as the result lists them, and that
match industry and event when given. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
kind | string | The list requested. |
search | object | The text the list was narrowed by, or null. |
field | object | With kind=values: the list returned. |
triggers | object[] | kind=triggers: the triggers this domain can use; with search, also the fields and settings each one takes. |
key | string | The type to pass in create_automation's trigger. |
label | string | The trigger's name in the editor. |
category | string | Category key, e.g. website_events. |
category_label | string | Category as the editor shows it. |
description | string | When the trigger fires. |
needs_tracking | boolean | True when the trigger fires on what the theMarketer tracking script reports from the website (visits, carts, product views): without the script on the site it never starts. get_integration_health shows whether website events arrive. |
fields | object | Trigger-specific fields it takes, required ones first. Null in the list given without search: search for the trigger key to see them. |
settings | object | General settings this trigger offers (run mode, smart sending, entry window, ...); all optional. Null in the list given without search, like fields. |
conditions | object[] | kind=conditions: the filter conditions this domain can use, its contact and product attributes included. |
condition | string | The condition key for a filter step, e.g. customer_tag, or custom:<Label> / product_attribute:<Label> for an attribute. |
label | string | The condition's name in the editor. |
category | string | Category key, e.g. contact_data. |
category_label | string | Category as the editor shows it. |
operators | string[] | Operators the condition accepts; with a single one, operator may be left out. |
operator_meanings | map<string> | What an operator stands for, for the operators whose word alone does not say it (e.g. buyer_within: placed an order in the last value days); empty when every operator is plain. |
value | string | What value must be, in words. |
choices | string[] | The fixed words value can take, when the condition has a closed list. |
choice_meanings | map<string> | What a choice stands for, for the choices whose word alone does not say it; empty otherwise. |
values_field | object | When value comes from a domain list: the field to pass to kind=values to see it. |
applies_to | object | When the condition only works in journeys started by certain triggers: which ones. Null when it works everywhere. |
note | object | How the condition is evaluated, or null. |
actions | object[] | kind=actions: the step kinds a journey can contain here, with their fields. |
key | string | The step type to pass. |
label | string | The step's name in the editor. |
consequence | object | What to know before using it (cost, irreversibility, data leaving the account); null when there is nothing special. |
fields | object[] | The fields the step takes. |
name | string | The field name to pass. |
required | boolean | True when the field must be given. |
description | string | What the field means and accepts. |
values_field | object | When the field takes a value from a domain list: the field to pass to kind=values to see them (e.g. products, tags). |
objectives | string[] | kind=objectives: the objectives a journey can be given. |
senders | object | kind=senders: verified senders, reply-tos and defaults. |
values | object[] | kind=values: the domain's values for field, as id and label. |
id | string | The value's id; the tools accept it or the label. |
label | string | The value as the editor shows it. |
email_blocks | object | kind=email_blocks: the blocks an automation email can hold, the placeholders its HTML may use and the rules they follow. |
trigger | object | With kind=email_blocks: the trigger key given, or null. |
discount_templates | object | kind=discount_templates: the designs a Discount block can show, with a preview picture each, and the filters that narrow them. |
unavailable | string[] | With kind=triggers, conditions or actions: entries this domain cannot use yet, grouped by what they need (a plan, the loyalty program, SMS credit, push set up). Not narrowed by search. |
total | integer | Entries matched, across all pages. |
page | integer | Page returned, starting at 1. |
pages | integer | Total pages. |
per_page | integer | Entries per page: 200 for values and objectives, 50 for triggers, conditions and actions, 20 for discount templates. |
has_more | boolean | True when a later page exists. |
note | object | Which page to ask for next, what to pass when the list is searched rather than listed, or null. |
List automation templates
list_automation_templatesReadThe journeys an automation can be created from without describing every step: theMarketer's pre-built library by category, the popular picks for this account, and the account's own saved journeys.
Use when the user wants a ready-made automation (welcome series, cart recovery, win-back, birthday...) or asks what templates exist; then pass the chosen template_id or saved_flow_id to create_automation, which sets it up as a draft to review in get_automation_details. For a journey built step by step, use get_automation_options instead.
source=library returns groups by category, each card with its template_id, name, description, objective, impact and the card's copy (what the journey will do, who enters, what you need); only categories and cards this account's plan offers are listed, and a card names its trigger when the same journey is among the popular picks. source=popular returns up to four library journeys whose trigger no running journey of the account uses yet, each with its trigger named. source=saved returns the account's saved journeys with their trigger and step count, 50 per page. search narrows the library and the popular picks by name or description, and the saved journeys by name (they have no description).
Parameters
| Parameter | Type | Description |
|---|
source | enum | library (the pre-built journeys by category), popular
(suggested for this account), or saved (the account's own
saved journeys). Omit for the library. One of: library, popular, saved. Default: 'library'. |
search | string | Case-insensitive text the name must contain, or the
description for library and popular cards. Omit for
everything. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
source | string | The list requested. |
search | object | The text the list was narrowed by, or null. |
groups | object[] | source=library: the cards by category, in the library's order; only what this account's plan offers. |
category | string | Category label as the library shows it. |
templates | object[] | The cards in this category. |
template_id | string | Pass it as create_automation's template_id to set the journey up as a draft. |
name | object | The journey's name. |
category | object | Library category the card sits in. |
description | object | What the journey is for, in the card's words. |
objective | object | The objective the journey is created with. |
impact | object | The card's impact rating, e.g. high. |
trigger | object | Trigger key the journey starts with (see get_automation_options kind=triggers). Always given for the popular picks; for a library card only when the same journey is among the popular picks, null otherwise (the contacts_added lines say who enters). |
trigger_label | object | The trigger's name in the editor; given together with trigger. |
journey_will | string[] | What the journey does, step by step. |
contacts_added | string[] | Who enters the journey. |
you_need | string[] | What the account needs before the journey can run. |
templates | object[] | source=popular: up to four library journeys whose trigger no running journey of the account uses yet. |
template_id | string | Pass it as create_automation's template_id to set the journey up as a draft. |
name | object | The journey's name. |
category | object | Library category the card sits in. |
description | object | What the journey is for, in the card's words. |
objective | object | The objective the journey is created with. |
impact | object | The card's impact rating, e.g. high. |
trigger | object | Trigger key the journey starts with (see get_automation_options kind=triggers). Always given for the popular picks; for a library card only when the same journey is among the popular picks, null otherwise (the contacts_added lines say who enters). |
trigger_label | object | The trigger's name in the editor; given together with trigger. |
journey_will | string[] | What the journey does, step by step. |
contacts_added | string[] | Who enters the journey. |
you_need | string[] | What the account needs before the journey can run. |
saved | object[] | source=saved: the account's saved journeys, 50 per page. |
saved_flow_id | string | Pass it as create_automation's saved_flow_id to set the journey up again as a draft. |
name | object | Name it was saved under. |
trigger | object | Trigger key the saved journey starts with. |
trigger_label | object | The trigger's name in the editor. |
steps_count | integer | Steps connected to the trigger. |
created_at | object | When it was saved (UTC). |
updated_at | object | When it was last updated (UTC). |
total | integer | Entries matched, across all pages. |
page | integer | Page returned, starting at 1. |
pages | integer | Total pages. |
has_more | boolean | True when a later page exists. |
note | object | Which page to ask for next when there is one; null otherwise. |
Create automation
create_automationWriteCreate a marketing automation (a journey) as a draft, from a trigger and steps, from a pre-built template, or from a saved journey.
Use when the user wants a new automated flow: a welcome series, a cart-recovery sequence, a post-purchase follow-up, a birthday message. Pass exactly one source. (1) trigger plus steps: the trigger says what starts the journey (get_automation_options kind=triggers lists the keys; searched by key it shows the fields one takes) and steps is the ordered list of what happens next; a filter step branches into yes/no, a split into a/b, and on create each branch has its own steps (repeat a step in both branches when both should do it): joining the branches into one shared filter or delay step is done afterwards with update_automation, with a kept step marked shared=true where the other branch reaches it. Names (tags, segments, products, categories, campaigns, forms) are resolved for you and an unknown name is answered with the closest matches. (2) template_id from list_automation_templates: the pre-built journey is copied with its emails. (3) saved_flow_id from list_automation_templates source=saved: one of the account's own saved journeys is copied under new step ids, email bodies included. Not for editing an existing journey (update_automation) or for sending a one-off message (campaign_wizard).
Every email step you write needs html: the full email body with an <a> whose href is exactly {{unsubscribe_link}}. Products that theMarketer fills for each contact go in as blocks: an empty <div data-block="<slot>"></div> in the HTML and an entry in the step's blocks (get_automation_options kind=email_blocks lists them). On save each slot is renamed to the block's id: each email step written comes back in flow.steps with its blocks under their new slots, which later updates use, and a render_check of the email rendered for a sample contact. Some steps have consequences worth telling the user: a webhook step sends contact data to the given URL and stores its credentials with the journey, an unsubscribe step cannot be undone from the journey, SMS steps spend SMS credit, and a start_automation step sends contacts into another journey. SMS and push text is plain text (product blocks go in email steps), a split needs at least one step in one of its branches, a filter condition takes one value unless it is one of the list conditions, and no path from the trigger runs through more than 50 steps. The result is always a draft with the stored flow and the id of every step; start_automation makes it live.
When a draft with exactly this name was created in the last 10 minutes, the call answers needs_user_input first: use that draft or create another. If a call fails without an answer, check list_automations for the draft before creating it again.
Parameters
| Parameter | Type | Description |
|---|
namerequired | string | Name shown in the automations list, at most 120
characters; plain text without <. Links and slashes are
removed. |
trigger | TriggerInput | What starts the journey: type (a trigger key such as
cart_abandonment, order_placed, new_email_subscriber,
tag_added) plus the fields that trigger takes, e.g. wait
for abandonment windows, tag for tag_added, products for
product_ordered, run once or multiple. Required with
steps; omit with template_id or saved_flow_id. |
steps | object[] | The steps after the trigger, in order, each with a type:
email (subject, preview_text, html, optional blocks), sms
(text, optional discount), push / mobile_push (title, text,
url), delay (amount, unit, optional at_time), filter
(conditions with yes and no branches), split (percent_a
with a and b branches), add_tags / remove_tags (tags),
unsubscribe (channels), start_automation (automation),
webhook (url, auth, body). Message steps may carry a ref label that an
automation_activity condition later in the flow refers to as
step_id. The yes/no and a/b branches each hold their
own steps and do not continue into one shared step here
(repeat the step in both, or join them later with
update_automation). May be empty to create the trigger alone
and add steps later. |
template_id | string | Id of a pre-built journey from
list_automation_templates (source=library or popular); the
journey is copied with its steps and email designs and takes
the template's objective. |
saved_flow_id | string | Id or exact name of one of the account's saved
journeys (list_automation_templates source=saved); its steps
and email bodies are copied under fresh step ids. |
objective | string | Optional goal shown in the list, one of: Assist
conversions, Assist recurrence, Assist retention and
recurrence, Convert members to buyers, Convert subscribers to
buyers, Enhance loyalty and engagement, Increase engagement,
Increase loyalty engagement, Increase loyalty purchases,
Nurture relationships, Recover abandoned carts, Recover
inactive users, Request feedback, Use discount codes. Not with
template_id. |
decision_token | string | From a needs_user_input result of this tool,
together with decision_answers; leave it out otherwise. |
decision_answers | object | The user's answer by decision key, e.g.
{"earlier_draft": "use"}; only with decision_token. |
domain_id | string | Target domain. |
Returns
The operation's result, pending user questions, or cancellation.
Update automation
update_automationDestructiveChange an automation's name, trigger or steps; the steps given replace the whole flow.
Use when the user wants to rename a journey, change what starts it, or edit its steps: add a message, change a delay, rewrite an email, adjust a condition. Read the current flow with get_automation_details first: every step there carries an id, and a step passed back with its id is kept, with its statistics and its saved email body; passed back exactly as it reads, it is stored as it is, names and all. A step without an id is new; a step left out of steps is removed. An email step with an id and no html keeps the body it has; html given replaces it; a new email step needs html with an <a> whose href is exactly {{unsubscribe_link}}. Products theMarketer fills for each contact go in as blocks: an empty <div data-block="<slot>"></div> in the HTML and an entry in the step's blocks (get_automation_options kind=email_blocks lists them). On save each new slot is renamed to the block's id, as the result's blocks show; later updates use those slots. On an email step with an id, pass only blocks (with the ids get_automation_details gives as slots) to change blocks' options: list only the blocks to change; the others keep their saved options. Give each block's slot, type and the options to change, and the options left out keep their saved values; the rest of the saved body stays exactly as it is, even when it was made in the web app's email editor. Pass html too to change the email's text or layout, or to swap a block for one of another type: a block listed with its saved slot and type still keeps the options left out; a new slot of the same type as one saved block the HTML no longer holds, with no option set differently, takes over that block and its saved options; any other new slot starts from the defaults. The HTML (its lines joined with newlines) and blocks get_automation_details gives for a step can be passed back as they are, unless its notes name a block the tools cannot write back. Every email step comes back in flow.steps with its blocks and body: written, with a render_check of the email rendered for a sample contact, or kept when its saved body stayed as it was. Steps shown as type kept are passed back as they came; a kept filter or split passed back without branch_1 or branch_2 keeps the saved steps there, and [] removes them. Not for starting, pausing or deleting (use start_automation, pause_automation, delete_automation) and not for creating one (create_automation).
A draft or paused journey takes any change. A running journey takes changes live, and contacts already in it continue on the new flow, except for changes that would leave them stranded: removing or retyping a delay or webhook step they may be waiting at, or changing the trigger type. Those need the journey paused first, which ends the journey for the contacts currently in it. The result lists what changed (empty, with nothing saved, when everything passed matches the journey as stored) and the flow as stored, with the id of every step. No path from the trigger may run through more than 50 steps.
A nested edit works the same way: pass the whole flow back and change only the step in question. To make the delay inside a filter's yes branch 2 days, with the flow read as steps=[email a1b2c3d4e5, filter f6g7h8i9j0 whose yes branch is [delay k1l2m3n4o5 of 1 day, sms p6q7r8s9t0] and whose no branch is empty], send steps=[{"type": "email", "id": "a1b2c3d4e5", "subject": ..., "preview_text": ...}, {"type": "filter", "id": "f6g7h8i9j0", "conditions": [... as read ...], "yes": [{"type": "delay", "id": "k1l2m3n4o5", "amount": 2, "unit": "days"}, {"type": "sms", "id": "p6q7r8s9t0", "text": ...}], "no": []}]: every other step is passed back as read with its id, so it is kept, and only the delay changes.
Parameters
| Parameter | Type | Description |
|---|
automation_idrequired | string | The automation to change, by id (24 hex
characters, from list_automations or create_automation). |
name | string | New name shown in the automations list, at most 120
characters; plain text without <. Links and slashes are
removed. |
trigger | TriggerInput | New trigger (type plus the fields it takes, as in
create_automation). Omit to keep the current trigger; required
when the current one is shown as not editable. |
steps | object[] | The complete new list of steps after the trigger, nested
like in create_automation. Replaces the whole flow: include
every step to keep, each with its id from
get_automation_details; omit the parameter to keep the steps
as they are. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
automation_id | string | Id of the automation that was updated. |
name | string | The name as stored after the update. |
status | string | Status after the update: draft, paused or running (a running journey keeps running on the new flow). |
status_label | object | The status as the theMarketer app words it. |
changed | string[] | What differs from the journey as it was: name, trigger, steps (an email body written counts as a change to the steps). Empty when what was passed matches what is stored; nothing is saved then. |
flow | object | The journey as stored now: trigger and one line per step with its id. |
trigger | string | The trigger as the editor names it, e.g. 'Cart abandonment'; 'not set' when the journey has no start yet. |
trigger_type | object | The trigger key (cart_abandonment, order_placed, ...); null when not set or not editable from here. |
steps | object[] | Every step reachable from the trigger, in flow order, branches nested by path. |
path | string | Where the step sits, in the vocabulary of create_automation and update_automation: steps[0], steps[1].yes[0], steps[2].a[1]. |
id | object | The step's id: pass it back in update_automation to keep the step (and its statistics and email body), or as step_id in an automation_activity condition. |
type | string | email, sms, push, mobile_push, delay, filter, split, add_tags, remove_tags, unsubscribe, start_automation, webhook, or kept for a step this tool cannot edit. |
summary | string | What the step does, in one line. |
body | object | On an email step: 'written' when this call wrote its body, 'kept' when its saved body stayed as it was (passed back without html, or with the same HTML and blocks it has). Null on every other step. |
blocks | object | On an email step: each block in its body, with its options, named by the id the saved body gives it as both slot and id: the slot to pass in later updates to keep or change the block's options (get_automation_details names it the same way). The note says which slot given in this call became which id. Null on every other step, and when the saved body could not be read (the step's warnings say so). |
render_check | object | On an email step whose body this call wrote: the email rendered for a sample contact and what it still lacks, as preview_automation_email reports it. Null on every other step, on a kept body, or when the rendered email was not available yet; preview_automation_email checks it again. |
warnings | object | On an email step: what to check before it sends, such as a {{placeholder}} theMarketer does not fill (usually misspelt), which would show as nothing, or a saved body that could not be read just now. Null on every other step. |
note | object | On an email step this call wrote: a tip for the web app's email editor, such as where to pick another footer design by sight. Null otherwise. |
step_count | integer | How many steps the journey has. |
notes | string[] | What could not be read back exactly, and steps on the canvas that are not connected to the trigger (they never run). |
entry_window | object | When the trigger lets contacts in, in the shop's timezone; null when it has no entry window. |
links | object | Where to open this journey in the theMarketer web app: app_url, and switch_domain_url for accounts with several domains. |
app_url | object | Link to this object in the theMarketer web app, for the user to review or edit it there. Null when the app URL is not configured on this MCP server. |
switch_domain_url | object | Only for accounts with several domains: open this first if the app is currently on another domain, then follow app_url. The app keeps one current domain per user and app_url only works on the domain this object belongs to. |
warnings | string[] | What to know about the saved flow: steps that cannot send yet, conditions on a message not yet received, what a live change means, then every warning of the steps and their render checks, each once and prefixed by the step's path, e.g. 'steps[1].yes[0] (Email: ...): ...'. |
note | string | What happens next and how to follow it. |
Start automation
start_automationDestructiveStart a draft or paused automation after the user confirms what will happen, or check whether it could start.
A call without dry_run never starts anything by itself: it returns the user's question first, and the journey starts only once they answer Start, so call it when the user wants the journey live. dry_run=true only checks and says what a start would do.
Use when the user wants a journey live: from then on every contact the trigger matches enters it and gets real emails, SMS or push messages. Call with dry_run=true first to see what would stop the start, and what a start would do, without starting it. Only a draft or a paused journey can be started; a running one is left as it is, and pause_automation stops it. Before starting, the journey is checked: it needs a trigger with at least one step connected to it, every email step needs a saved body that renders fit to send (as preview_automation_email shows it; a rendering that cannot be read just then does not stop the start, the note says so) and a sender address the domain has verified (a step without one of its own sends from the domain's default sender, so the domain needs one), push steps need web push (mobile push steps the mobile app push) set up on the domain, SMS steps need SMS credit or an SMS provider, the trigger and every filter condition must be ones the domain's plan includes (a loyalty trigger also needs the loyalty program), a filter condition on a message step must check a step of this journey, and a start_automation step must point at a journey of this domain that starts with automation_triggered and does not start this one back (directly or a few journeys on); anything missing is reported and nothing starts. Starting a paused journey does not bring back the contacts who were in it when it was paused.
A journey that passes the checks is not started on the first call: it answers needs_user_input with one question for the user that says what will happen: the journey and domain, who enters, how many emails, SMS and push notifications a contact receives and over how long, that SMS uses credit (with the credit left), every email that creates a unique discount code as it sends (its value and how long it is valid), the journeys it sends contacts on into, the contact details each webhook step sends and to which URL, the channels each unsubscribe step unsubscribes contacts from (which the journey cannot undo), and for a paused journey that the contacts it had do not come back. Call again with decision_token and decision_answers once they agreed; nothing starts before that. A journey edited since the question (its steps or an email body) is not started, and the question is asked again.
The result gives the status before and after, and the note says when a journey this one starts is not running yet, or when the trigger fires on website activity (needs_tracking) and no website events have arrived lately, so no contact would enter yet. With dry_run the same checks run, nothing is asked and nothing changes: ready says whether the journey could start now, problems what stops it (each with its fix; a journey that is already running, or a domain whose plan does not include automations, is reported there too), not_checked what could not be checked this time and consequences what a start would do, in the words of the question a start asks.
Parameters
| Parameter | Type | Description |
|---|
automation_idrequired | string | The automation to start, by id (24 hex characters,
from list_automations or create_automation). |
dry_run | boolean | True runs every check and returns what would stop the
start and what a start would do; nothing is asked or started.
Omit or false to ask the user and start it once they confirm. Default: False. |
decision_token | string | From a needs_user_input result of this tool,
together with decision_answers; leave it out otherwise. |
decision_answers | object | The user's answer by decision key, e.g.
{"confirm": "proceed"}; only with decision_token. |
domain_id | string | Target domain. |
Returns
The operation's result, pending user questions, or cancellation.
Pause automation
pause_automationDestructivePause a running automation after the user confirms, ending the journey for the contacts in it.
Use when the user wants a journey to stop sending: before editing a delay or the trigger, before deleting it, or to switch it off for a while. Only a running journey can be paused; a draft or a paused one is reported as such. Pausing is not a gentle stop: contacts currently in the journey (waiting for a delay or a next step) leave it for good, and starting it again later does not bring them back; new contacts stop entering until start_automation runs it again.
The first call answers needs_user_input with the one question to ask the user, which says how many contacts are in the journey now; call again with decision_token and decision_answers once they agreed. Nothing is paused before that. The count may have moved on by then and the pause still applies; a journey that was edited, stopped or started again since the question is not paused, and the question is asked again.
The result gives the status before and after.
Parameters
| Parameter | Type | Description |
|---|
automation_idrequired | string | The automation to pause, by id (24 hex characters,
from list_automations). |
decision_token | string | From a needs_user_input result of this tool,
together with decision_answers; leave it out otherwise. |
decision_answers | object | The user's answer by decision key, e.g.
{"confirm": "proceed"}; only with decision_token. |
domain_id | string | Target domain. |
Returns
The operation's result, pending user questions, or cancellation.
Delete automation
delete_automationDestructiveDelete a draft or paused automation for good, with its reports, after the user confirms.
Use when the user wants a journey gone: an abandoned draft, a test, a flow that was replaced. Only a draft or a paused journey can be deleted; a running one needs pause_automation first, which ends the journey for the contacts in it. Deleting removes the journey from the automations list for good, with its reports; it cannot be restored from here (duplicate_automation beforehand keeps a copy). To stop a journey without losing it, pause_automation is enough.
The first call answers needs_user_input with the one question to ask the user, which names the journey, its status, how many contacts ever entered it and the journeys whose start_automation step sends contacts into it; call again with decision_token and decision_answers once they agreed. Nothing is deleted before that. A journey that was edited, started or stopped since the question is not deleted, and the question is asked again.
Parameters
| Parameter | Type | Description |
|---|
automation_idrequired | string | The automation to delete, by id (24 hex
characters, from list_automations). |
decision_token | string | From a needs_user_input result of this tool,
together with decision_answers; leave it out otherwise. |
decision_answers | object | The user's answer by decision key, e.g.
{"confirm": "proceed"}; only with decision_token. |
domain_id | string | Target domain. |
Returns
The operation's result, pending user questions, or cancellation.
Duplicate automation
duplicate_automationWriteCopy an automation as a new draft, in the same domain or into another domain of the account.
Use when the user wants a variant of a journey without touching the original, a backup before a big edit, or the same journey on another of their shops. The copy is a draft with the same trigger, steps and email bodies, under new step ids, and keeps the original's name unless name is given; statistics are not copied. The original needs at least one saved step; a brand-new empty draft has nothing to copy. Same-domain copies are immediate and the result carries the new id. A copy into another domain (target_domain, one where the user is admin or owner) is queued by theMarketer: the tool waits a few seconds for it and reports created with its id, or queued when it has not appeared yet, in which case list_automations on that domain shows it shortly. A copy on another domain keeps the email senders and the start_automation targets of the original, which belong to this domain: review them there before starting it. Not for moving contacts between journeys or for starting the copy (start_automation does that).
Parameters
| Parameter | Type | Description |
|---|
automation_idrequired | string | The automation to copy, by id (24 hex characters,
from list_automations). |
name | string | Name for the copy, at most 120 characters; omit to keep the
original's name. Plain text without <; links and slashes are
removed. |
target_domain | string | Another domain of the account to copy into, by
name (hostname) or id as list_domains shows them; omit to copy
within the same domain. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
source_id | string | The automation that was copied. |
automation_id | object | Id of the copy, a draft; null while a copy into another domain is still queued. |
name | string | Name of the copy as stored (or as requested). |
status | string | Always 'draft': a copy never runs by itself. |
outcome | string | created when the copy exists and its id is known; queued when theMarketer is still copying it into the other domain. |
target_domain_id | string | The domain the copy lives in. |
target_domain | object | That domain's name, when copying across domains. |
links | object | Where to open the copy in the theMarketer web app once it exists: app_url, and switch_domain_url for accounts with several domains. |
app_url | object | Link to this object in the theMarketer web app, for the user to review or edit it there. Null when the app URL is not configured on this MCP server. |
switch_domain_url | object | Only for accounts with several domains: open this first if the app is currently on another domain, then follow app_url. The app keeps one current domain per user and app_url only works on the domain this object belongs to. |
note | string | What happened and what to do next. |
Send test automation email
send_test_automation_emailDestructiveSend a test copy of one email step of an automation to up to five addresses.
Use when the user wants to see an automation email in an inbox before starting the journey or after changing the step. It sends one real email per address from the step as currently saved: its subject, preview text and body. When an address belongs to a contact of the domain, the email is personalised with that contact's own data (name, cart, orders); any other address gets sample data. Find the automation with list_automations and the step id with get_automation_details; the step must be an email step whose subject and body are already saved (update_automation saves both). Not for real recipients: the journey itself reaches them once start_automation runs it.
Each domain may send 30 test emails per hour across its automations; once the allowance is used up the remaining addresses come back as 'throttled' and nothing is sent to them. 'sent' means the message was accepted for delivery; delivery problems are not reported back, so ask the recipient to check the inbox and spam folder.
Parameters
| Parameter | Type | Description |
|---|
automation_idrequired | string | The automation's id from list_automations (24 hex
characters). |
step_idrequired | string | Id of the email step to test, as get_automation_details
lists it. |
recipients | string[] | One to five email addresses to send the test to;
duplicates are sent once. Omit to send it to the signed-in
user's own address. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
automation_id | string | The automation the step belongs to. |
step_id | string | The email step the test was sent from. |
subject | string | The subject line of the step as saved; the test carries it. |
results | object[] | One entry per address, in the order given. |
recipient | string | The address the test was sent to. |
outcome | string | 'sent' when theMarketer accepted the test; 'throttled' when the domain's allowance of 30 test emails per hour was used up, in which case nothing was sent to this address. |
note | string | What 'sent' means (accepted, not delivered), how the test is personalised, what the email's discount codes read as in a test, and the hourly allowance. |
Send test automation SMS
send_test_automation_smsDestructiveSend the saved text of an automation's SMS step to the signed-in user's own phone, as a test, after the user confirms.
Use when the user wants to read an automation SMS on their own phone before starting the journey or after changing the step. The test always goes to the phone number on the signed-in user's theMarketer profile, never to a number given here, and it sends the step's text exactly as saved (update_automation changes it). It is charged like a real SMS: one message of SMS credit at the account's price, unless the domain sends through its own SMS provider. Find the automation with list_automations and the step id with get_automation_details.
The first call answers needs_user_input with the one question to ask the user: it carries the text, the masked number and what the test costs, so ask it in full. Call again with the same automation_id and step_id plus decision_token and decision_answers once they agreed; nothing is sent before that. If the text or the phone number changed since the question was asked, nothing is sent and the question comes back for the new text. Once handed to the SMS provider (delivery itself is not confirmed), the result reports the text, the masked phone, cost_per_sms_eur and the remaining_credit_eur left after the test.
theMarketer sends one test SMS per domain every 10 seconds; a test that comes too soon after the previous one is not sent and the result says to try again in a few seconds. A test needs the price of one SMS in whole euros of credit; when the credit is below that the tool says so before asking anything, and get_transactional_credits shows the balance. When only this domain's own credit can be read, the question shows it even when low, since a credit the account shares across its domains may cover the test; if it does not, the test is not sent and the result says so.
Parameters
| Parameter | Type | Description |
|---|
automation_idrequired | string | The automation's id from list_automations (24 hex
characters). |
step_idrequired | string | Id of the SMS step to test, as get_automation_details
lists it. |
decision_token | string | From a needs_user_input result of this tool,
together with decision_answers; leave it out otherwise. |
decision_answers | object | The user's answer by decision key, e.g.
{"confirm": "proceed"}; only with decision_token. |
domain_id | string | Target domain. |
Returns
The operation's result, pending user questions, or cancellation.
Campaigns12
List campaigns
list_campaignsReadList the account's campaigns on every channel, with status, audience, schedule and headline results, most recently scheduled first.
Use when the user asks which campaigns exist, what was sent or is scheduled, or how recent campaigns did, and whenever you need a campaign id for the other campaign tools. For the latest sent campaign call with status="sent" and read the first row. It lists SMS and push campaigns too; the other campaign tools cover email only.
Names are not unique. If several campaigns match the user's request, show their ids, subjects, statuses and dates and ask which one they mean before changing anything. Never select one by guesswork. A draft's send_at is only the time saved on it, even in the past, and schedules nothing; it is null while no send time is set yet: that is chosen when the campaign is scheduled with schedule_campaign.
Each row carries the id, name, status with status_label as the app shows it, type, mode, subject, sender, audience (segment names, exclusions, extra recipients, smart sending), send_at, sent_at, recipients and stats: lifetime sent, delivered, unique opens and clicks, transactions, revenue, unsubscribes, the unique open rate (contacts who opened / delivered) and the click, unique click and conversion rates in percent, resend and A/B parts included. A campaign with an automatic resend also carries resend_after, resend_status and resend_send_at (an estimate until the campaign has finished sending); a manual resend made with create_campaign_resend gives the id of the campaign it follows up in source_campaign_id and its name in source_name. Rows come 20 per page by send date descending; a draft with no send time set sorts by when it was created. A draft that never reached the wizard's schedule step, such as a new manual resend, is listed after every other draft, often many pages in: look it up with search by its name instead of paging. The listing reports no total: has_more is true when the page came back full and the note names the next page. Archived campaigns appear only with status="archived". For the breakdown per part, links, timeline and contacts use get_campaign_report.
Parameters
| Parameter | Type | Description |
|---|
status | enum | Which campaigns to list: all (everything except archived),
draft, scheduled (waiting for their send time, including A/B
parents), sending (going out right now), paused, sent,
archived, or payment_error (scheduled but not sent because the
account was suspended). Omit for all. One of: all, draft, scheduled, sending, paused, sent, archived, payment_error. Default: 'all'. |
type | enum | Channel filter: email, sms, push or mobile_push. Omit for
every channel. One of: email, sms, push, mobile_push. |
search | string | Case-insensitive substring the campaign name or email
subject must contain. Omit to list everything. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
campaigns | object[] | The campaigns on this page, ordered by send date descending; drafts without a send date come last. |
id | object | Campaign id (24 hex characters) for the other campaign tools. |
name | object | Campaign name as shown in theMarketer; recipients never see it. |
status | object | The campaign's status: draft, scheduled (waiting for its send time, A/B parents included), queued, sending, paused, ab_testing, sent, archived or payment_error, in the words list_campaigns' status filter takes. |
status_label | object | The status as the theMarketer app words it: scheduled is 'Scheduled', queued and sending are 'Sending now', payment_error is 'Not sent - Payment error'. |
type | object | Channel: email, sms, push or mobile_push. |
mode | object | Email content mode: regular (HTML editor), ecommerce (HTML with product blocks) or plaintext; null for other channels. |
subject | object | Email subject line. |
preview | object | Preheader text shown next to the subject. |
sender | object | Sender name, address and reply-to. |
name | object | From (sender) display name. |
email | object | From (sender) address. |
reply_to | object | Reply-to address; null when not set. |
audience | object | Audience type, segment names, exclusions, extra recipients and smart sending. |
type | object | 'all' for the whole email audience, 'segment' for the segments listed in segments. |
segments | string[] | Names of the segments the campaign targets; empty when type is 'all'. |
exclude_segments | string[] | Names of the segments whose members are left out. |
extra_recipients | string[] | Addresses that receive a copy regardless of the audience. |
smart_sending | boolean | True when contacts who received a campaign recently (the domain's smart-sending window) are skipped. |
send_at | object | Send time in UTC; only a scheduled status means delivery is planned. A draft's send_at is only the time saved on it, even in the past, and sends nothing; null while no send time is set yet: it is chosen when the campaign is scheduled with schedule_campaign. |
sent_at | object | When sending finished (UTC); null until the campaign is sent. |
recipients | object | Audience size recorded at scheduling (stats.sent also counts the resend and A/B parts) and recounted at send time; null when theMarketer stored no estimate (several segments), and for a manual resend that has not gone out: its recipients are calculated when it is sent. |
stats | object | Headline results from stats.all; all zeros for a campaign that has not been sent, null when the listing carried none. |
ab_test | boolean | True when the campaign has an A/B test. |
resend_after | object | Hours after the main email finishes sending at which its automatic resend goes out; null without an automatic resend. |
resend_status | object | Status of the automatic resend: draft, scheduled, queued, sending, paused, sent or payment_error; null without one. |
resend_status_label | object | The automatic resend's status as the theMarketer app words it; null without one. |
resend_send_at | object | When the automatic resend goes out (UTC). Until the main email has finished sending this is an estimate from its send_at, and the real time is later for batched, optimal-time or A/B sends. Null without a resend, or when a sent campaign's resend was never scheduled and will not go out. |
source_campaign_id | object | For a manual resend (made with create_campaign_resend): the id of the sent campaign it follows up, which tells apart campaigns with the same name; null for every other campaign. |
source_name | object | For a manual resend: the name of the sent campaign it follows up; null when that campaign can no longer be found, and for every other campaign. |
edit_step | object | Last wizard step saved (sender, audience, subject, content, schedule, abtesting, resend, tracking, done); tells how far a draft got. |
created_at | object | When the campaign was created (UTC). |
page | integer | Page returned, starting at 1. |
per_page | integer | Campaigns per page, fixed at 20. |
has_more | boolean | True when this page came back full, which is the only signal theMarketer gives: it reports no total, so the next page may still be empty. |
note | object | Which page to ask for next when there may be more; null when this page is the last. |
Get campaign details
get_campaign_detailsReadEverything configured on one email campaign, by section: what it says, who gets it, when, how links are tagged, and the rendered email.
Use when the user asks what a campaign contains or how it is set up, before campaign_wizard with campaign_id to see the current values, or before create_campaign to learn the domain's verified senders and defaults (summary.domain_defaults). Find the id with list_campaigns. Email campaigns only; performance numbers are in get_campaign_report.
By default it returns summary, audience, schedule and tracking; content renders the email and is heavier, so ask for it only when the user wants to see the copy or check the HTML. The rendered content comes 80 lines per page (a line longer than 200 characters is cut only where a line break changes nothing) with content_total_chars, pages and a note naming the next page; the other sections ignore page.
summary.resend describes the automatic resend (who gets it, after how many hours, its subject, preview and send time) and is null when there is none. Its send time is an estimate until the campaign has finished sending (send_at_is_estimate). A campaign made with create_campaign_resend carries summary.manual_resend instead: the sent campaign it follows up, its rule and who it reaches, counted at send time from that campaign's recipients.
Parameters
| Parameter | Type | Description |
|---|
campaign_idrequired | string | The campaign's id from list_campaigns (24 hex
characters). Use the main campaign's id, not an A/B or resend
child. |
sections | enum[] | Which sections to return; omit for summary, audience,
schedule and tracking. Any of: summary (name, status, mode,
subject, preview, sender, A/B flag, automatic or manual
resend, template id and the domain's wizard defaults),
audience (segments with keys and names, exclusions, extra
recipients, smart sending, recipient count), schedule (send
type, send_at, sent_at, optimal-time and batch settings),
tracking (UTM tags), content (the rendered email, 80 lines
per page; page applies to the content sections only, the
other sections are not paged), content_b (variant B's HTML or
text of an A/B test on the content, paged like content),
content_resend (the automatic resend's rendered email, paged
like content). |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
campaign_id | string | theMarketer id of the campaign. |
sections_returned | string[] | The sections fetched on this call, in the order the keys below are listed. |
summary | object | Identity, status, mode, subject, sender, the A/B flag, the automatic resend or the campaign a manual resend follows up, template id and the domain's wizard defaults (verified senders, default reply-to, optimal hour, smart-sending window). |
audience | object | Audience type, segments (names and keys), exclusions, extra recipients, smart sending and the recorded recipient count. |
schedule | object | Send type, send_at, sent_at, optimal-time settings and batch delivery. |
tracking | object | UTM tagging: enabled flag and the three tags. |
content | object | The rendered email as lines, 80 per page, with content_total_chars, pages, has_more and a note naming the next page. Only fetched when requested. |
content_b | object | Variant B's HTML or text of an A/B test on the content, paged like content (as saved, not rendered); empty with a note for other tests; only when requested. |
content_resend | object | The automatic resend's rendered email (the text of a plaintext campaign), paged like content; only when requested. |
Get campaign report
get_campaign_reportReadHow one email campaign performed: counters and rates, benchmark, clicked links, daily timeline and the contacts behind each metric.
Use when the user asks how a campaign did, what was clicked, who opened or bought, or how it compares with the account's usual results. Find the id with list_campaigns; its rows already carry the headline stats, come here for more. Email campaigns only.
By default it returns overview only; each extra section is a separate read, so ask for what the question needs. overview gives counters and rates for the whole campaign (all), for the campaign without its automatic resend (all_without_resend, the headline the theMarketer app shows) and for each part with data (main, resend, A/B variants, winner), the currency, the last open and click times and survey results. The totals add the parts up without matching people, so a contact who got the main email and the resend counts twice; quote all_without_resend for the campaign itself and resend for the follow-up. For the share of recipients who opened quote unique_open_rate; unique_click_rate is the share of those openers who clicked, not of all recipients. open_rate counts every open, and on all_without_resend it is opens per 100 messages sent, so above 100 means more opens than messages sent. A manual resend made with create_campaign_resend is a campaign of its own: its results are under its own id, not in the resend part of the campaign it follows up. A resend shows 0 sent when no contact matched its rule at send time; get_campaign_details shows whether it went out.
benchmark sets the rates next to the account's and the industry's averages; links lists the top clicked links, the most engaged contacts and the products ordered; timeline gives seven daily rows of opens, clicks, orders and revenue plus clicks by country, in a window anchored on today for campaigns older than six days; contacts lists who did what for one metric, 50 per page, narrowed by search. Contact rows carry the contact id and name, never the email address. Links, timeline and contacts exist only once the campaign has been sent: for a draft or scheduled campaign they are skipped with a note, while overview still answers with zeros. A section that could not be loaded reads {"unavailable": <reason>} while the rest still answer. Rates are percentages.
Parameters
| Parameter | Type | Description |
|---|
campaign_idrequired | string | The campaign's id from list_campaigns (24 hex
characters). Use the main campaign's id; its A/B and
automatic resend parts are reported under it, while a manual
resend reports under its own id. |
sections | enum[] | Which sections to return; omit for overview only. Any
of: overview (counters and rates per part, currency, last
open/click, survey), benchmark (campaign vs account vs
industry), links (top links, top fans, products ordered),
timeline (7 daily rows and countries), contacts (who did
what for metric, paged). |
metric | enum | Required with the contacts section: which contacts to
list - sent (everyone it went to), opens, clicks,
transactions (buyers) or unsubscribed (unsubscribes, bounces
and complaints, with a status per row). One of: sent, opens, clicks, transactions, unsubscribed. |
search | string | With contacts: substring the contact's email must
contain. Omit for everyone. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
campaign_id | string | theMarketer id of the campaign. |
name | object | Campaign name. |
status | object | The campaign's status, in the words list_campaigns' status filter takes. |
status_label | object | The status as the theMarketer app words it. |
sections_returned | string[] | The sections fetched on this call, in the order the keys below are listed. |
overview | object | Counters and rates for the whole campaign (stats.all), for the campaign without its automatic resend (the app's headline) and for each part that has data (main, resend, A/B variants, winner), the currency, last open and click times and survey results. Reads {"unavailable": <reason>} when that part could not be loaded. |
benchmark | object | Open, click, unsubscribe and conversion rates, AOV and revenue for this campaign next to the account's and the industry's averages. Reads {"unavailable": <reason>} when that part could not be loaded. |
links | object | Top clicked links, most engaged contacts and products ordered. Reads {"unavailable": <reason>} when that part could not be loaded. |
timeline | object | Daily opens, clicks, orders and revenue over a 7-day window anchored on today for campaigns older than six days, plus clicks by country. Reads {"unavailable": <reason>} when that part could not be loaded. |
contacts | object | The contacts behind metric, 50 per page, optionally narrowed by search. Reads {"unavailable": <reason>} when that part could not be loaded. |
note | object | Caveats about this answer, e.g. sections skipped because the campaign has not been sent. |
Create email campaign
create_campaignDestructiveCreate an email campaign through theMarketer's wizard - sender, audience, subject, content, schedule, tracking - and schedule it or leave it as a draft.
Use only outside a conversation, when a program already holds every decision (audience, send time, A/B test, resend) as data. When a user is talking, even if they said everything in one message, use campaign_wizard and give what they said as the answers to its first round; their words are answers, not arguments. With draft=true (default) the campaign is fully configured and left as a draft: nothing is sent until it is scheduled with schedule_campaign. Pass draft=false only when the user explicitly asked to send or schedule and has confirmed content, sender, audience and time: that is a real send; once scheduled, update_campaign can move it or change its content, and delete_campaign cancels it. When in doubt keep the draft and call send_test_campaign first. Email campaigns only.
Content is either html or plain_text, never both, and must carry the unsubscribe link: an <a> whose href is exactly {{unsubscribe_link}} in HTML, the placeholder anywhere in plain text. Do not put HTML comments (<!-- ... -->) in the html. For product blocks use table-based layout and inline CSS, absolute URLs and plain product links: click tracking and the campaign's UTM tags are added at send time; take names, prices (price_display) and images from list_products.
The audience is the user's decision. Pass segments only with segments the user named (names or keys as list_segments shows them); an empty list sends to the whole email audience, only when the user asked for everyone. When they did not say who should receive it, omit segments; when they only described it ('loyal customers', 'inactive for 6 months'), pass that description as audience_description and no segments: the result offers exact name matches or a choice between existing and new segments. Ask only for missing criteria: pass the specific question in audience_clarification to return audience_criteria. Omit it when the user already gave the period, such as 'last 30 days'. Use list_segments to find suitable segments, then let the user choose. Names do not establish matching rules. Without a description, the result asks whether to use all subscribers, an existing or a new segment. Either way the first call creates nothing until the user confirms the audience and its recipient count. Never pick a segment or call create_segment on your own. Pass a typed answer as the user wrote it: a segment name selects that segment, any other text comes back as their audience criteria. Choosing another audience opens a follow-up question; ask what they want, then retry with the new audience and the other original arguments, without the previous decision_token or decision_answers.
A/B testing is the user's decision too: unless ab_test is given, the confirmation asks whether to run one (not with use_optimal_time), so pass ab_test only for a test the user described ({'type': 'none'} when they already said no A/B test): type subject (subject_b, preview_b), content (html_b, or plain_text_b for a plaintext campaign) or time (send_at_b); split halves the audience, otherwise A and B go to size% each and the winner by winner_by to the rest after decide_after hours; leave those four out unless the user stated them: the confirmation asks them. Write variant B as you write variant A. It also asks whether to add an automatic resend (the campaign sent again after_hours after it goes out, to contacts who did not engage): pass resend only for one the user described. To follow up on a campaign that has already gone out, use create_campaign_resend instead. When status is 'needs_user_input', nothing was written. Show all pending_changes; nothing is saved yet. Reuse explicit user choices for configuration in decisions_pending. Ask missing choices with every option and its details; use clickable choices when available, otherwise plain text. Never invent answers. For every confirmation, show the changes or final summary and ask explicitly; the original request is not confirmation. Re-ask expired or changed questions; never reuse their old answers. Call the same tool with the original arguments plus resume_arguments, decision_token and decision_answers. Use question keys and option values, free text only when allowed, and lists for multiple choices.
send_at is ISO 8601 at least 15 minutes ahead: with a UTC offset it is used as given, without one it is read in the shop's timezone. Omit it to send as soon as possible; on a draft the time stored then is only a placeholder and nothing is scheduled. The result shows the campaign as stored, with its effective UTC send time, its A/B test and resend and a recipient estimate per segment. When the account is blocked from sending, the campaign stays a draft and sending_block says why. Follow it with list_campaigns or get_campaign_details, and use get_campaign_report once it was sent.
Parameters
| Parameter | Type | Description |
|---|
namerequired | string | Campaign name as shown in theMarketer's lists and reports,
at most 100 characters; recipients never see it. |
subject_linerequired | string | Email subject, at most 100 characters; variables
such as {{client_firstname}} are allowed. |
sender_name | string | From (sender) display name. Omit for the domain's
default sender name. |
sender_email | string | From (sender) address. Omit for the domain's default
sender (the one the app preselects, even when several are
verified; the result's sender shows which was used); when
given it must be one of the verified senders (the error lists
them). |
html | string | Full raw email HTML containing an unsubscribe anchor whose
href is exactly {{unsubscribe_link}}, e.g. in the footer. Pass
either html or plain_text, not both. |
plain_text | string | Text-only email body containing {{unsubscribe_link}}
somewhere; the campaign is stored in plaintext mode. Pass either
plain_text or html, not both. |
preview_text | string | Preheader text shown next to the subject in inboxes,
at most 200 characters. Default: ''. |
reply_to | string | Reply-to address; defaults to the domain's default
reply-to. |
segments | string[] | Segments the user chose, by exact name or custom segment
id from list_segments, or by campaign key from decisions_pending
or resume_arguments (e.g. 'VIP customers',
activity::active_30_days, custom::<segment id>). Contacts in
any of them receive the campaign. An empty list selects the
whole email audience. Omit when the user has not chosen yet:
the result then asks them. |
audience_description | string | The audience in the user's own words when
they described it without naming segments (e.g. 'customers who
did not buy for 6 months'). Offers exact name matches or a choice
between existing and new segments. This is not a semantic search. |
audience_clarification | string | A question about genuinely missing audience
criteria, such as the period meant by 'recent'. Omit when the
user already supplied the criteria, including any time period.
Used only while segments is omitted. After the answer, omit
this question when retrying with the chosen audience. |
exclude_segments | string[] | Segments whose contacts are removed from the
audience at send time, by name or key. |
extra_recipients | string[] | Addresses that get a copy when the first batch
goes out, outside the audience (e.g. the marketing manager). |
smart_sending | boolean | Skip contacts who received a campaign recently
(window configured in the domain's email settings). Default: False. |
send_at | string | When to send, as ISO 8601 at least 15 minutes from now.
With a UTC offset (e.g. 2026-10-01T10:00:00+03:00) it is used
as given; without one (2026-10-01T10:00:00) it is read in the
shop's timezone, as the theMarketer app does. The result
reports the effective UTC time. Omit to send as soon as
possible; a draft then keeps a placeholder time and is not
scheduled. |
use_optimal_time | boolean | Deliver to each contact at their own predicted
best hour instead of all at send_at; theMarketer then spreads
the send over up to 24 hours. Default: False. |
optimize_for | enum | Goal of the optimal-time model when use_optimal_time
is set: opening (opens) or buying (purchases). One of: opening, buying. Default: 'opening'. |
utm_source | string | UTM source appended to every link; defaults to the
domain's setting. |
utm_medium | string | UTM medium appended to every link; defaults to the
domain's setting. |
utm_campaign | string | UTM campaign appended to every link; defaults to the
domain's setting. |
draft | boolean | True (default) leaves the campaign in draft status: every
step is saved and the app opens it on the last wizard step, so
it can be reviewed, tested with send_test_campaign and scheduled
by hand. False schedules the real send at send_at (or as soon
as possible); once scheduled, update_campaign can move send_at
or change the content, and delete_campaign cancels it. Default: True. |
ab_test | object | The A/B test the user described, or {'type': 'none'}
when they already said no A/B test; omit it otherwise: the
confirmation asks whether to run one. |
resend | object | Never together with an A/B test on the send time. The
automatic resend the user described: who gets the campaign
again (to, required), after how many hours, with which
subject, preview text or own content (html, or plain_text on
a plaintext campaign); it goes to the campaign's audience as it
is when the resend goes out; {'to': 'none'} when the user
already said no resend. Omit it otherwise: the confirmation
asks whether to add one. The automatic resend
follows this campaign after_hours after it goes out; to
follow up on a campaign that has already gone out, use
create_campaign_resend instead. |
decision_token | string | From a 'needs_user_input' result, once the user
answered its questions; omit on the first call. |
decision_answers | object | The user's answers by decision key; each value
is an option value or allowed free text. Omit on the first call. |
domain_id | string | Target domain. |
Returns
The operation's result, pending user questions, or cancellation.
Create or change an email campaign with the user
campaign_wizardDestructiveCreate an email campaign with the user, or with campaign_id change an existing draft or scheduled one: theMarketer asks the user every decision (format, audience, exclusions, send time, A/B test, resend, sender) in one round, plus one more for the A/B details, the optimal time's day, a typed resend or an unclear audience, then shows the whole plan for one confirmation, and only then creates the campaign as a draft or schedules it.
Use when the user wants a new email campaign, or to change one, in a conversation, even if they said everything in one message; Use create_campaign or update_campaign for choices already specified as structured fields; their required user confirmations still apply. Email campaigns only.
To change a campaign, pass campaign_id with domain_id: the first round shows what is set now and lets the user keep or change each setting and the content, the format stays as it is, and the confirmation shows each change as it is now and as it will be; nothing is written before the user confirms. Pass only the texts the result asks for: the others stay as stored. A campaign that is sending or has gone out cannot change.
Start with domain_id only: the result asks the first round. When the user already said what they want (audience, time, A/B test, resend, sender), answer the first round from their words and ask only what they did not say. Show every question of a round with clickable choices; if the client shows at most four questions at a time, show them in batches and collect all answers before calling again. The decisions are never parameters: they come only from the user's answers. There is no audience or segment parameter: the segment, everyone or a new segment is the answer to the audience question. Pass wizard_operation back unchanged on every call, as resume_arguments gives it. Write the content only when the result says write_content; if the conversation does not say what the email is about, ask the user together with the first round. Then call again with wizard_operation and the content: subject_line, preview_text, html or plain_text as the user chose, and only the variant B fields the result lists. The content is checked as the campaign editor checks it; an error names what to fix in the content, never a decision. html must carry an <a> whose href is exactly {{unsubscribe_link}}, plain_text the placeholder; for product blocks use table-based layout and inline CSS, absolute URLs and plain product links, with names, prices (price_display) and images from list_products. Take the logo, colours, social links and contact e-mail from the result's brand (the logo as {{logo_url}}), never invent them. When the result says provide_segment, pass the agreed new_segment with wizard_operation. The final summary confirms both creations; do not call create_segment separately. Campaign creation and scheduling continue while segment membership is being calculated.
send_at and send_at_b are ISO 8601, written from the user's words for the send time and for variant B; pass them only when the result asks for them, and on a change only when the user picks a new time. With a UTC offset they are used as given, without one they are read in the shop's timezone. They must be at least 15 minutes and at most 30 days ahead, send_at_b after send_at; the confirmation shows each one next to the user's words. On the confirming call pass only the answer; the content shown is kept. Passing different content asks the confirmation again. When status is 'needs_user_input', no campaign change was written; a segment from a prior confirmed attempt can remain saved. Show all pending_changes; nothing is saved yet. Reuse explicit user choices for configuration in decisions_pending. Ask missing choices with every option and its details; use clickable choices when available, otherwise plain text. Never invent answers. For every confirmation, show the changes or final summary and ask explicitly; the original request is not confirmation. Re-ask expired or changed questions; never reuse their old answers. Call the same tool with the original arguments plus resume_arguments, decision_token and decision_answers. Use question keys and option values, free text only when allowed, and lists for multiple choices.
The result carries the campaign id, its status, the effective UTC send time, the sender, audience and A/B test as stored and a recipient estimate per segment. Follow it with list_campaigns or get_campaign_details, test a draft with send_test_campaign, and use get_campaign_report once it was sent.
Parameters
| Parameter | Type | Description |
|---|
wizard_operation | string | The handle of this wizard's progress, kept by
theMarketer, from the last result's resume_arguments; pass it
back unchanged. Omit on the first call; a changed or expired
one is answered with status 'unavailable': check the
campaigns and segments, then start again without it. |
decision_token | string | From a 'needs_user_input' result, once the user
answered its questions; omit on the first call. |
decision_answers | object | The user's answers by decision key; each value
is an option value or allowed free text, a list for multiple
choices. Omit on the first call. |
subject_line | string | The email's subject line, at most 100 characters,
without < or >; variables such as {{client_firstname}} are
allowed. Pass it with the content, once the result says
write_content. |
preview_text | string | Preheader text shown next to the subject in inboxes,
at most 200 characters, without < or >. |
name | string | Campaign name as shown in theMarketer's lists and reports, at
most 100 characters; recipients never see it. Omit to use the
subject line. |
html | string | Full raw email HTML with an unsubscribe anchor whose href is
exactly {{unsubscribe_link}}, when the user chose an HTML email.
HTML comments are removed before saving. |
plain_text | string | Text-only email body containing {{unsubscribe_link}},
when the user chose plain text. |
send_at | string | The send time the user gave, as ISO 8601: with a UTC offset
it is used as given, without one it is read in the shop's
timezone. Only when the result asks for it: a set time, or the
day for the best-time send on another day. |
send_at_b | string | Variant B's send time for a send-time A/B test, as ISO
8601 like send_at, after variant A's. |
subject_b | string | Variant B's subject line for a subject A/B test, at most
100 characters, different from subject_line. |
preview_b | string | Variant B's preview text for a subject A/B test, at most
200 characters. |
html_b | string | Variant B's full HTML for a content A/B test on an HTML
email, with the same unsubscribe link. |
plain_text_b | string | Variant B's text for a content A/B test on a plain
text email, containing {{unsubscribe_link}}. |
campaign_id | string | The id of an existing draft or scheduled email
campaign to change with the user, from list_campaigns or an
earlier result; omit to create a new campaign. Pass it on every
call of that change, with wizard_operation. |
new_segment | object | The name, rules, match and lock of the new segment the user
selected as this campaign's audience. Pass when provide_segment is
requested; omit afterwards to keep it. Nothing is created until
the final confirmation covers the segment and campaign together. |
domain_id | string | Target domain. |
Returns
The operation's result, pending user questions, or cancellation.
Update email campaign
update_campaignDestructiveChange an existing email campaign that is still a draft or scheduled, for explicit changes provided as structured fields: subject, sender, content, audience, send time or UTM tags, one or several at once.
When a user is talking about changing a campaign, use campaign_wizard with campaign_id: it shows what is set now, lets the user keep or change each setting, and confirms every change before writing. Use this tool when the requested changes are already specified, to edit a campaign before it goes out or to move a scheduled send. Pass campaign_id (from create_campaign, campaign_wizard or list_campaigns) and only the fields to change; everything else is kept. If several campaigns match the name, ask the user to choose using their ids, subjects and dates before calling this tool. It works on draft and scheduled campaigns: a campaign that is sending or paused is controlled with pause_campaign and resume_campaign, and a sent one cannot change apart from its waiting resend. A scheduled campaign is scheduled again with the new values, which is also how a scheduled send is moved; send_now=true moves delivery to as soon as possible after explicit confirmation. Every change to a scheduled campaign is confirmed by the user first, since saving schedules it again. A scheduled campaign is postponed by moving its send_at here, or cancelled with delete_campaign. On a draft, send_now only saves that setting and keeps the campaign as a draft; schedule_campaign schedules a draft. 'Send it to segment X' selects an audience; pass send_now only when the user explicitly requests sending now.
Content follows the campaign's mode: html for an HTML campaign, plain_text for a plaintext one, and it must still carry the unsubscribe link ({{unsubscribe_link}} as an <a> href in HTML, anywhere in plain text). Do not put HTML comments (<!-- ... -->) in the html. sender_email must be one of the domain's verified senders. segments, exclude_segments and extra_recipients replace the stored lists; an empty segments list selects the whole email audience and requires confirmation. Omitted audience fields keep their stored values.
Pass segments only with segments the user named or chose. If they describe a new audience without naming segments, pass audience_description and omit segments: the result offers exact name matches or a choice between existing and new segments. Ask only for missing criteria: pass the specific question in audience_clarification to return audience_criteria. Omit it when the user already gave the period, such as 'last 30 days'. Use list_segments to find and inspect suitable segments, then let the user choose before passing segments. Segment names do not establish matching rules. Changes to segments, exclusions, extra recipients or smart sending require the user's confirmation of the current and proposed audience and recipient estimates. Counts are before exclusions and smart sending; the final filtered count is unavailable. pending_changes lists all requested changes waiting for the decisions, including subject or content edits; show this list before asking the questions. No fields are saved while a decision is pending. Edits only to other fields do not ask an audience question. Pass a typed answer as the user wrote it: a segment name selects that segment, any other text comes back as their audience criteria. Choosing another audience opens a follow-up question; ask what they want, then retry with the new audience, keeping campaign_id and the other requested changes, without the previous decision_token or decision_answers.
ab_test sets the A/B test as create_campaign does (subject on HTML campaigns only, content or send time, split or a winner) and replaces the stored one; {'type': 'none'} turns it off and deletes its variants. Omit it to keep the stored A/B test. Both need the user's confirmation. An A/B test cannot run with the optimal send time: when both would apply, the confirmation asks which one to keep.
resend sets the automatic resend: the campaign sent again to the contacts who did not engage, after_hours after it goes out. It is set before the campaign goes out; to follow up on a campaign that has already gone out, use create_campaign_resend instead. As in create_campaign, resend gives who gets it (to, needed only when adding one), after_hours 1-72, subject_line, preview_text or own content (html, or plain_text on a plaintext campaign), and changes only what it gives: the resend keeps its other saved values and its content unless html or plain_text is given. {'to': 'none'} turns it off and deletes it. Omit it to leave the resend alone. A resend can be added while the campaign is a draft, or scheduled without an A/B test, and needs a send time; it is not available with an A/B test on the send time. Once the campaign has been sent, pass resend alone to change or turn off a resend still waiting to go out: after_hours then counts from when the campaign went out, and the confirmation shows the new send time. While the campaign is sending, its resend cannot change. A resend cannot change within 15 minutes of the campaign's send; once the campaign has been sent, it can be edited until an hour before its own send and turned off until 15 minutes before. Every resend change needs the user's confirmation. When status is 'needs_user_input', nothing was written. Show all pending_changes; nothing is saved yet. Reuse explicit user choices for configuration in decisions_pending. Ask missing choices with every option and its details; use clickable choices when available, otherwise plain text. Never invent answers. For every confirmation, show the changes or final summary and ask explicitly; the original request is not confirmation. Re-ask expired or changed questions; never reuse their old answers. Call the same tool with the original arguments plus resume_arguments, decision_token and decision_answers. Use question keys and option values, free text only when allowed, and lists for multiple choices.
On a resend of another campaign, only the name, subject, preview text, content, send time and UTM tags can change.
send_at is ISO 8601 at least 15 minutes ahead, read in the shop's timezone when it has no offset. The result lists the fields that were applied, the status, the effective UTC send time, the audience and the resend as stored, the resend also in words in the note. Test the result with send_test_campaign and follow it with get_campaign_details.
Parameters
| Parameter | Type | Description |
|---|
campaign_idrequired | string | The campaign to change, by id (24 hex characters, from
create_campaign, campaign_wizard or list_campaigns). If names
are duplicated, ask the user which campaign they mean; never
guess the id. |
name | string | New campaign name as shown in theMarketer, at most 100
characters. |
subject_line | string | New email subject, at most 100 characters. |
preview_text | string | New preheader text shown next to the subject, at
most 200 characters. |
sender_name | string | New From (sender) display name. Cannot change on a
resend of another campaign (made with create_campaign_resend). |
sender_email | string | New From (sender) address; must be one of the domain's
verified senders. Cannot change on a resend of another
campaign (made with create_campaign_resend). |
reply_to | string | New reply-to address. Cannot change on a resend of
another campaign (made with create_campaign_resend). |
html | string | New full email HTML for an HTML campaign, with an unsubscribe
anchor whose href is exactly {{unsubscribe_link}}. |
plain_text | string | New body for a plaintext campaign, containing
{{unsubscribe_link}} somewhere. |
segments | string[] | Segments the user chose, by exact name or custom segment
id from list_segments. Campaign keys from decisions_pending or
resume_arguments are also accepted, e.g. custom::<segment id>
or activity::active_30_days. Replaces the whole stored list after confirmation:
to add one, pass every current segment plus the new one
(get_campaign_details shows them). An empty list selects the
whole email audience, also requiring confirmation. Omit to keep
the stored list unless audience_description asks for a new one.
Cannot change on a resend of another campaign (made with
create_campaign_resend). |
audience_description | string | The new audience in the user's own words
when they described it without naming segments. Omit segments
to offer exact name matches or a choice between existing and
new segments. This is not a semantic search of segment rules.
Omit both fields to keep the stored audience. Cannot change on
a resend of another campaign (made with create_campaign_resend). |
audience_clarification | string | A question about genuinely missing audience
criteria, such as the period meant by 'recent'. Use alongside
audience_description and omit segments. Omit when the user
already supplied the criteria and period, and when retrying
with the chosen audience after their answer. |
exclude_segments | string[] | Segments to exclude at send time, by name or key;
replaces the stored list (empty list clears it). Cannot change
on a resend of another campaign (made with
create_campaign_resend). |
extra_recipients | string[] | Addresses that get a copy outside the audience;
replaces the stored list (empty list clears it). Cannot change
on a resend of another campaign (made with
create_campaign_resend). |
smart_sending | boolean | Whether to skip contacts who received a campaign
recently. Cannot change on a resend of another campaign (made
with create_campaign_resend). |
send_at | string | New send time, as ISO 8601 at least 15 minutes from now.
With a UTC offset (e.g. 2026-10-01T10:00:00+03:00) it is used
as given; without one (2026-10-01T10:00:00) it is read in the
shop's timezone, as the theMarketer app does. The result
reports the effective UTC time. |
send_now | boolean | Move a scheduled campaign to as soon as possible
(minimum 15 minutes after saving), after explicit confirmation.
On a draft, only saves the setting and does not schedule delivery.
Use only for an explicit request to send now; a request to send
to a segment changes the audience. Cannot be combined with send_at. Default: False. |
use_optimal_time | boolean | Deliver at each contact's predicted best hour
(true) or to everyone at send_at (false). |
optimize_for | enum | Goal of the optimal-time model: opening (opens) or
buying (purchases). One of: opening, buying. |
utm_source | string | New UTM source appended to every link. |
utm_medium | string | New UTM medium appended to every link. |
utm_campaign | string | New UTM campaign appended to every link. |
ab_test | object | The A/B test to set, {'type': 'none'} to turn it off, or
omit to keep the stored one. Cannot be set on a resend of
another campaign (made with create_campaign_resend). |
resend | object | Never together with an A/B test on the send time. The
automatic resend to add or change, {'to': 'none'} to turn it
off, or omit to leave it alone. to is required when adding a
resend; on a campaign that already has one, every field left
out, to included, keeps the resend's saved value, so a delay
or subject change can pass that field alone. Its own content
is html on an HTML campaign, plain_text on a plaintext
campaign. On a campaign that has been sent, pass it
alone to change a resend still waiting to go out. The
automatic resend is set before the campaign goes out and
follows it after_hours after it goes out; to follow up on a
campaign that has already gone out, use create_campaign_resend
instead. |
decision_token | string | From a needs_user_input result for this campaign,
once the user answered all its pending questions; omit on the
first call. |
decision_answers | object | The user's answers by decision key; each value
is an option value or allowed free text. Omit on the first call. |
domain_id | string | Target domain. |
Returns
The operation's result, pending user questions, or cancellation.
Resend a sent email campaign
create_campaign_resendWriteCreate a resend of a sent email campaign: a new draft that goes only to the original's recipients who did not open it, who opened but did not click, or who clicked but did not buy.
Use when the user wants to follow up on a campaign that has already gone out, as the Resend action in the theMarketer campaign list does. It never sends: the draft copies the original's sender, audience, content, subject and preview, and is scheduled afterwards with schedule_campaign, after review (get_campaign_details) and a test (send_test_campaign). For a campaign that has not gone out yet, set an automatic resend instead with the resend parameter of update_campaign, or of create_campaign for a new campaign: it goes out by itself after_hours after the campaign. Only a sent email campaign without an automatic resend can be resent this way; clicked_not_purchased needs an e-commerce plan.
The draft keeps the original's extra recipients and smart sending; they are shown in the confirmation and cannot be changed here. Extra recipients each get a copy whatever the rule, and smart sending can skip contacts who got another campaign recently, possibly everyone. Who exactly receives it is calculated at send time. Only the name, subject, preview text, content, send time and UTM tags of the draft can change later (update_campaign). Each confirmed call creates a new draft, even when the campaign already has a resend draft; a draft sends nothing until it is scheduled. When status is 'needs_user_input', nothing was written. Show all pending_changes; nothing is saved yet. Reuse explicit user choices for configuration in decisions_pending. Ask missing choices with every option and its details; use clickable choices when available, otherwise plain text. Never invent answers. For every confirmation, show the changes or final summary and ask explicitly; the original request is not confirmation. Re-ask expired or changed questions; never reuse their old answers. Call the same tool with the original arguments plus resume_arguments, decision_token and decision_answers. Use question keys and option values, free text only when allowed, and lists for multiple choices.
Parameters
| Parameter | Type | Description |
|---|
source_campaign_idrequired | string | The sent campaign to follow up on, by id (24
hex characters, from list_campaigns); the main campaign, not
an A/B variant. |
resend_torequired | enum | Who of its recipients get the resend: not_opened (did
not open it), opened_not_clicked (opened but did not click) or
clicked_not_purchased (clicked but did not buy; e-commerce
plans only). One of: not_opened, opened_not_clicked, clicked_not_purchased. |
subject_line | string | A new subject for the resend, at most 100
characters; omit to keep the original's. |
preview_text | string | A new preview text for the resend, at most 200
characters; omit to keep the original's, or pass an empty
string to clear it. |
name | string | The draft's name in theMarketer, at most 100 characters;
omit for 'Resend' followed by the original's name. |
decision_token | string | From a 'needs_user_input' result, once the user
answered its questions; omit on the first call. |
decision_answers | object | The user's answers by decision key; each value
is an option value. Omit on the first call. |
domain_id | string | Target domain. |
Returns
The operation's result, pending user questions, or cancellation.
Schedule email campaign
schedule_campaignDestructiveSchedule an email campaign that is still a draft: it goes out at send_at, or as soon as possible with send_now=true.
Use when the user wants a draft sent, including a resend draft from create_campaign_resend and a draft from create_campaign or campaign_wizard. A campaign that is already scheduled is changed with campaign_wizard and campaign_id (or update_campaign from a program); a new campaign is created with campaign_wizard. It is a real send: while it is scheduled, campaign_wizard with campaign_id can change its send time or content, and delete_campaign cancels it. Test it with send_test_campaign first.
Before anything is saved the draft is checked as the theMarketer wizard checks it: a subject, content with the unsubscribe link (<a href="{{unsubscribe_link}}">Unsubscribe</a> in HTML, {{unsubscribe_link}} in plain text) and a sender. An automatic resend needs its subject and the unsubscribe link too, and cannot go with a send-time A/B test. A resend of another campaign must still go only to that campaign's recipients who match its rule, with no A/B test or automatic resend added; the original must be sent. A campaign with an A/B test is rescheduled with its variants; for a send-time test, variant B's time must stay after the new send time. The confirmation shows what goes out, to whom and when; if the campaign changes before the send is confirmed, the user is asked again. When status is 'needs_user_input', nothing was written. Show all pending_changes; nothing is saved yet. Reuse explicit user choices for configuration in decisions_pending. Ask missing choices with every option and its details; use clickable choices when available, otherwise plain text. Never invent answers. For every confirmation, show the changes or final summary and ask explicitly; the original request is not confirmation. Re-ask expired or changed questions; never reuse their old answers. Call the same tool with the original arguments plus resume_arguments, decision_token and decision_answers. Use question keys and option values, free text only when allowed, and lists for multiple choices.
send_at is ISO 8601 at least 15 minutes ahead: with a UTC offset it is used as given, without one it is read in the shop's timezone. The account can require a longer lead time, so the result reports the send time theMarketer stored. When the account is blocked from sending, the campaign stays a draft and sending_block says why. The domain's admins get a 'campaign scheduled' email. Follow it with list_campaigns or get_campaign_details.
Parameters
| Parameter | Type | Description |
|---|
campaign_idrequired | string | The draft to schedule, by id (24 hex characters, from
create_campaign, campaign_wizard, create_campaign_resend or
list_campaigns). |
send_at | string | When to send, as ISO 8601 at least 15 minutes from now.
With a UTC offset (e.g. 2026-10-01T10:00:00+03:00) it is used
as given; without one (2026-10-01T10:00:00) it is read in the
shop's timezone. Pass send_at or send_now, not both. |
send_now | boolean | Send as soon as possible (about 15 minutes after
confirming), only when the user asked to send now. Pass
send_at or send_now, not both. Default: False. |
use_optimal_time | boolean | Deliver to each contact at their own predicted
best hour, spread over up to 24 hours (true), or to everyone at
send_at (false). Omit to keep the draft's setting. |
optimize_for | enum | Goal of the optimal-time model: opening (opens) or
buying (purchases). Omit to keep the draft's setting. One of: opening, buying. |
decision_token | string | From a 'needs_user_input' result, once the user
answered its questions; omit on the first call. |
decision_answers | object | The user's answers by decision key; each value
is an option value. Omit on the first call. |
domain_id | string | Target domain. |
Returns
The operation's result, pending user questions, or cancellation.
Send test campaign email
send_test_campaignDestructiveSend a test copy of an email campaign to up to five addresses.
Use when the user wants to see the email in an inbox before scheduling it or after editing it. It sends one real email per address from the campaign as currently saved, with a '[Test]' subject prefix (except for addresses listed in the campaign's extra recipients) and test versions of the unsubscribe and tracking links; unsubscribed and unknown addresses receive it too. The campaign can be in any status, draft included; find the id with list_campaigns. Not for real recipients: schedule it with schedule_campaign (or change it with update_campaign).
Each domain may send 30 test emails per hour; once the limit is reached the remaining addresses come back as 'throttled' and nothing is sent to them. 'sent' means the message was accepted for delivery; delivery problems are not reported back, so ask the recipient to check the inbox and spam folder.
Parameters
| Parameter | Type | Description |
|---|
campaign_idrequired | string | The campaign's id from list_campaigns (24 hex
characters). For a resend, pass the main campaign's id. |
recipientsrequired | string[] | One to five email addresses to send the test to.
Duplicates are sent once. |
variant | enum | 'a' (default) sends the campaign itself, a manual resend
made with create_campaign_resend included. 'b' sends variant
B's content of an A/B test on the content of an HTML campaign,
under variant A's subject. 'resend' sends the automatic resend
as it will go out, with its own subject, preview and content;
it is not available for plaintext campaigns, whose resend text
get_campaign_details shows (section content_resend), or less
than an hour before the resend goes out. One of: a, b, resend. Default: 'a'. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
campaign_id | string | The campaign the test was sent from. |
results | object[] | One entry per address, in the order given. |
recipient | string | The address the test was sent to. |
outcome | string | 'sent' when theMarketer accepted the test; 'throttled' when the domain's limit of 30 test emails per hour was reached, in which case nothing was sent to this address. |
note | string | What 'sent' means (accepted, not delivered), the hourly throttle and how the test email differs from the real send. |
Pause campaign
pause_campaignWritePause an email campaign that is sending right now.
Use when the user wants to stop a send in progress: status 'sending', shown as 'Sending now' in list_campaigns. Batches already in flight finish, no further batch starts, and pending A/B or resend parts are paused with it; resume_campaign continues the send later. A scheduled campaign is not sending yet, so it cannot be paused: cancel it with delete_campaign, or postpone it: change its send time with campaign_wizard and campaign_id. Drafts and sent campaigns have nothing to pause, and a campaign that is already paused comes back unchanged.
The result gives the status before and after the call and a note on what the pause means for the send.
Parameters
| Parameter | Type | Description |
|---|
campaign_idrequired | string | The campaign's id from list_campaigns (24 hex
characters); the main campaign, not an A/B or resend child. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
campaign_id | string | The campaign acted on. |
status_before | string | The campaign's status when the tool read it (draft, scheduled, sending, paused, sent...), the same word as list_campaigns. |
status_after | string | The campaign's status after the call, the same word as list_campaigns; equal to status_before when nothing had to change. |
status_label | object | status_after as the theMarketer app words it. |
note | string | What happened and what it means for the send. |
Resume campaign
resume_campaignDestructiveResume a paused email campaign so the remaining batches go out.
Use when the user wants to continue a send that pause_campaign or the app's Pause button stopped: status 'paused' in list_campaigns. This is a real send to the rest of the audience, so confirm with the user first. The remaining batches are queued again and paused A/B or resend parts wait to go out again. A scheduled campaign is not paused and goes out at its send_at: cancel it with delete_campaign, or postpone it: change its send time with campaign_wizard and campaign_id. A draft is scheduled with schedule_campaign, and a sent campaign has nothing to resume. A campaign that is already sending comes back unchanged.
The result gives the status before and after the call and a note on how the send continues.
Parameters
| Parameter | Type | Description |
|---|
campaign_idrequired | string | The campaign's id from list_campaigns (24 hex
characters); the main campaign, not an A/B or resend child. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
campaign_id | string | The campaign acted on. |
status_before | string | The campaign's status when the tool read it (draft, scheduled, sending, paused, sent...), the same word as list_campaigns. |
status_after | string | The campaign's status after the call, the same word as list_campaigns; equal to status_before when nothing had to change. |
status_label | object | status_after as the theMarketer app words it. |
note | string | What happened and what it means for the send. |
Delete campaign
delete_campaignDestructiveDelete a draft, scheduled or paused campaign for good, after the user confirms.
Use when the user wants a campaign gone before it goes out: an abandoned draft, a test, or a scheduled send they want cancelled. Deleting a scheduled campaign is how its send is cancelled; to send it later instead, move its send_at with update_campaign. Deleting a paused campaign drops the batches it has not sent; what went out stays in its report. Its A/B test and resend go with it. A campaign that is sending, testing its A/B variants or already sent cannot be deleted: pause_campaign stops a running send first, and sent campaigns stay in the reports. A deleted campaign cannot be restored.
The first call answers needs_user_input with the one question to ask the user, which names the campaign, its status and its send time; call again with decision_token and decision_answers once they agreed. Nothing is deleted before that. A campaign renamed, rescheduled or given an A/B test or resend since the question is not deleted, and the question is asked again; one that has started sending since cannot be deleted.
Parameters
| Parameter | Type | Description |
|---|
campaign_idrequired | string | The campaign to delete, by id (24 hex characters,
from list_campaigns); the main campaign, not an A/B or resend
part. |
decision_token | string | From a needs_user_input result of this tool,
together with decision_answers; leave it out otherwise. |
decision_answers | object | The user's answer by decision key, e.g.
{"confirm": "proceed"}; only with decision_token. |
domain_id | string | Target domain. |
Returns
The operation's result, pending user questions, or cancellation.
Domain6
List domains
list_domainsReadList the theMarketer domains (shops) this connection can work with.
Use first when the account manages several domains and you need to pick one: pass a domain's name or id as domain_id to any other tool. Single-domain accounts never need it.
Returns domains, one entry per domain with its id, hostname, shop URL and the user's role on it, plus count.
Parameters
No parameters.
Returns
| Field | Type | Description |
|---|
domains | object[] | One entry per domain. |
domain_id | string | Domain id; accepted by every domain_id parameter. |
name | object | Hostname, e.g. shop.example; accepted by domain_id too. |
url | object | Full shop URL. |
permission | object | The user's role on the domain, e.g. owner or admin. |
count | integer | Domains returned. |
Get sending domain
get_sending_domainReadShow the sending domain's setup: DNS records, senders and reply-to address.
Use when the user asks how their sending domain is configured, which DNS records theMarketer expects and which are still missing, or which sender addresses campaigns can go out from. It reads the current state and changes nothing; the DNS lookup runs live, so the call takes a few seconds. To re-run the full check and store its outcome use validate_domain; for whether the website tracking works use get_integration_health.
Returns the domain, valid, every expected record in dns_records with found, missing_records, the senders with the default_sender, sender_name, the effective reply_to, the extra and validated sender domains, a link to the settings page and a note naming the records to add when some are missing.
Parameters
| Parameter | Type | Description |
|---|
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
domain | object | The sending domain, e.g. shop.example; null when none is configured yet. |
valid | boolean | True when the email providers have confirmed the domain and every DNS record is in place. |
dns_records | object[] | Every DNS record theMarketer expects on the domain (DKIM, SPF, DMARC and the newsletter subdomain records) with its name, type, value, priority and whether it was found. |
name | object | Host the record is set on, e.g. mkt._domainkey.shop.example. |
type | object | Record type: TXT, CNAME or MX. |
value | object | The value the record must hold, exactly as it has to be entered at the DNS provider. |
priority | object | Priority of an MX record; null for TXT and CNAME records. |
found | boolean | True when the record was found in DNS with the expected value. |
missing_records | integer | How many of dns_records are not visible in DNS yet. |
default_sender | object | The sender address campaigns use unless another one is chosen; null when no sender is configured. |
senders | object[] | Every sender address configured on the domain, with the default one flagged. |
email | object | The sender address. |
default | boolean | True for the address campaigns are sent from unless another sender is chosen. |
sender_name | object | The from-name shown next to the sender address. |
reply_to | object | Where replies go: the custom reply-to address when one is set, otherwise the default sender address. |
extra_sender_domains | string[] | Additional domains senders may use besides the main sending domain. |
validated_domains | string[] | The sending domains the email providers have confirmed. |
links | object | Where to open the email settings in the theMarketer web app. |
app_url | object | Link to this object in the theMarketer web app, for the user to review or edit it there. Null when the app URL is not configured on this MCP server. |
switch_domain_url | object | Only for accounts with several domains: open this first if the app is currently on another domain, then follow app_url. The app keeps one current domain per user and app_url only works on the domain this object belongs to. |
note | object | Set when records are missing: which ones, and what to do next. Null when every record is in place. |
Validate sending domain
validate_domainWriteRun the sending-domain check now: DNS records and email provider setup.
Use when the user asks whether their sending domain is set up correctly (SPF, DKIM, DMARC, sender identities), or has just added DNS records and wants them verified. The check runs now and takes about 10 seconds: it looks up every expected DNS record, asks the email providers to confirm the sender identities again and stores the outcome on the domain. For the full record list and the senders without re-running the check use get_sending_domain.
Returns valid true when everything passes. A failed check lists the records to fix in failed_records (name, type and the value to set) with a note on what to do next; an empty list with valid false means the records are in place and the providers have not confirmed the domain yet.
Parameters
| Parameter | Type | Description |
|---|
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
valid | boolean | True when the email providers confirmed the domain and every DNS record is in place; the outcome is stored on the domain. |
failed_records | object[] | Only the DNS records that were not found, each with the name, type and value to set; empty when valid. |
name | object | Host the record is set on, e.g. mkt._domainkey.shop.example. |
type | object | Record type: TXT, CNAME or MX. |
value | object | The value the record must hold, exactly as it has to be entered at the DNS provider. |
priority | object | Priority of an MX record; null for TXT and CNAME records. |
found | boolean | True when the record was found in DNS with the expected value. |
links | object | Where to open the email settings in the theMarketer web app. |
app_url | object | Link to this object in the theMarketer web app, for the user to review or edit it there. Null when the app URL is not configured on this MCP server. |
switch_domain_url | object | Only for accounts with several domains: open this first if the app is currently on another domain, then follow app_url. The app keeps one current domain per user and app_url only works on the domain this object belongs to. |
note | object | What to do next when the check did not pass; null when valid. |
Get the account's plan prices, billing date and usage totals.
Use for plan tier, pricing and email usage questions. Returns the plan tier (contact bounds, contacts counted, current and next monthly price), discount, sent, billing_date, email_credit and max_pause_months. Billing identity, invoices and payment details are not included; view invoices and payment settings in the authenticated theMarketer web app.
Parameters
| Parameter | Type | Description |
|---|
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
plan | object | The current contact tier with its bounds, the contacts counted and the current and next monthly price. |
tier_start | object | Lower bound of the current contact tier. |
tier_end | object | Upper bound of the current contact tier. |
contacts | object | Contacts counted for billing. |
monthly_price | object | Monthly price of the current tier, EUR. |
next_tier_price | object | Monthly price of the next tier, EUR. |
discount | object | Discount percent applied to the subscription. |
sent | object | Emails sent in the current billing month. |
billing_date | object | Next billing date, e.g. '31 Jul 2026'; null when none is scheduled. |
email_credit | object | Remaining email credit. |
max_pause_months | object | How many months the subscription may be paused. |
Verify connection
verify_connectionReadCheck that this connection can work with the domain.
Use when tools keep failing and you want to tell a connection problem from a data problem, or when the user asks whether the integration is set up. For the list of domains the connection can reach use list_domains; for whether the website tracking works use get_integration_health.
Returns valid true when the domain is reachable on an active paid plan. Free, paused or suspended accounts come back with valid false and a note explaining it, so a false here does not by itself mean the connection is wrong.
Parameters
| Parameter | Type | Description |
|---|
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
valid | boolean | True when the domain is reachable on an active paid plan. |
note | object | Set when the domain is not on an active paid plan: what that means and what to do. Null when valid. |
Get integration health
get_integration_healthReadCheck whether the shop's website tracking reaches theMarketer.
Use when the user asks whether the tracking script is installed and working, before relying on funnel, audience or e-commerce figures, or when automations built on website events do not fire. It reads which standard events (page views, product views, add to cart, checkout, order...) and which custom events reached theMarketer in the last 48 hours; nothing is changed.
Returns tracking_active, the events and custom_events maps of event name to seen, the window_hours and a note on what to check when events are missing, e.g. no order event while products are viewed.
Parameters
| Parameter | Type | Description |
|---|
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
tracking_active | boolean | True when at least one standard website event was received in the last 48 hours. |
window_hours | integer | Length of the observation window, in hours. |
events | map<boolean> | Standard website events (view_homepage, view_category, view_product, add_to_cart, search, add_to_wishlist, remove_from_wishlist, initiate_checkout, remove_from_cart, order, generic_page_view) and whether each was seen in the window. |
custom_events | map<boolean> | Custom events defined on the domain and whether each was seen in the window; empty when none is defined. |
note | object | What to check when tracking is missing or incomplete; null when it looks healthy. |
E-commerce11
List products
list_productsReadBrowse the shop's product catalogue with the filters, sorts and paging of the Products page.
Use when the user asks what the shop sells, which products are on sale, in stock, best selling, most viewed or best rated, or when picking products to feature in a campaign. Results come 15 per page with total, pages and has_more; the note names the next page.
Prices are in the account currency: price is what the shop charges now, full_price the regular price, and price_display / full_price_display render them the way the shop does. For an email block prefer availability="in_stock", skip products with disabled true or any issues, and use image and url as they come: click tracking and the campaign's UTM tags are added at send time. Products the merchant disabled in theMarketer are listed too and come back with disabled true.
category and brand accept a name or an id; get_product_options lists the ones this catalogue has. Use get_product_details for one product's description, reviews, history and orders.
Parameters
| Parameter | Type | Description |
|---|
search | string | Words to look for in the product name, SKU, shop id or
URL, case-insensitive. Every word must appear, in any order
and in any of these: "pantofi piele naturala" finds "Pantofi
maro piele naturala". Accents you type are optional:
"naturală" finds "naturala" and "naturală", while "naturala"
alone may miss a name spelt "naturală". When each word is in
more than 150 products, the words are matched in the order
typed and without accents; when no product has them in that
order, the pages run through the products with the rarest
word and keep those with every word. The note says which.
Omit to list the whole catalogue. |
category | string | One category by full path ("Footwear > Running"), by
leaf name when it is unique, or by id. Matches the product's
main category and its other categories. A name that does not
match is answered with the closest spellings. |
brand | string | One brand by name (case-insensitive) or id. A name that
does not match is answered with the closest spellings. |
availability | enum | "in_stock", "supplier_stock" (orderable from the
supplier), "out_of_stock", or "all" (default). One of: all, in_stock, supplier_stock, out_of_stock. Default: 'all'. |
discounted | boolean | true for products currently discounted, false for
products at full price; omit for both. |
min_price | number | Lowest current price to include, inclusive, in the
account currency. |
max_price | number | Highest current price to include, inclusive. |
min_margin | number | Lowest margin in percent, inclusive. Products without
an acquisition price have no margin and never match a margin
bound. |
max_margin | number | Highest margin in percent, inclusive. |
min_stock | integer | Fewest units in stock to include, inclusive. |
max_stock | integer | Most units in stock to include, inclusive. |
health | enum | "with_issues" for products whose feed entry has a
validation problem (bad URL or image) or whose price is below
the acquisition price; "without_issues" for products whose
feed entry is valid; "any" (default) for both. One of: any, with_issues, without_issues. Default: 'any'. |
sort | enum | "newest" (default) / "oldest" by the date the shop added
the product; "price_asc" / "price_desc" by current price;
"full_price", "discount", "best_selling", "most_viewed",
"highest_rated", "most_reviewed", "stock", "stock_movement",
"added_to_cart", "conversion_rate", "click_rate", "margin",
"acquisition_price", "last_sync", "issues", "recurrence"
highest first; "name", "sku", "shop_id" alphabetical. One of: newest, oldest, price_asc, price_desc, full_price, discount, best_selling, most_viewed, highest_rated, most_reviewed, stock, stock_movement, added_to_cart, conversion_rate, click_rate, margin, acquisition_price, last_sync, issues, recurrence, name, sku, shop_id. Default: 'newest'. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
products | object[] | The products on this page, in sort order. |
id | object | The product's id in theMarketer: pass it to get_product_details or a segment rule. |
shop_id | object | The shop's own product id. |
sku | object | SKU from the feed. |
name | object | Product name. |
url | object | Absolute product URL from the feed; use it as the link target as is. |
image | object | Absolute URL of the main image; null when the product has none. |
gallery | string[] | Further image URLs, at most 5 shown. |
price | object | Current selling price in the account currency; equals full_price when the product is not discounted. |
full_price | object | Regular price; differs from price only while a discount runs. |
discount_percent | object | Discount as a whole percent, 0 to 100; 0 when none; null when the product's prices do not support the discount it carries. |
currency | object | ISO code of the account currency (e.g. RON); null when the shop's currency settings could not be loaded. |
price_display | object | price formatted the way the shop shows it (thousands and decimal separators, currency symbol and position), e.g. '1.299,00 Lei'; null when the shop's currency settings could not be loaded. |
full_price_display | object | full_price formatted like price_display; show it struck through only when discount_percent is above 0. |
availability | object | 'in_stock', 'supplier_stock' (orderable from the supplier) or 'out_of_stock'. |
stock | object | Units in stock. |
brand | object | Brand name, or null. |
category | object | Main category, leaf name; the category filter also accepts the full path. |
rating | object | Average review rating, 0 to 10; null when unrated. |
reviews | object | Number of reviews. |
ordered | object | Units sold through tracked orders. |
views | object | Tracked product views. |
added_to_cart | object | Units added to a cart in tracked sessions. |
click_rate | object | Share of the category's views this product took, in percent - not an email click rate. |
conversion_rate | object | Units ordered per 100 views, in percent. |
margin | object | (price - acquisition price) / price, in percent; null when the feed carries no acquisition price. |
acquisition_price | object | Purchase cost from the feed, in the account currency; 0 when not fed. |
stock_movement | object | Share of the stock sold since it was last replenished, 0-100 percent. |
recurrence | object | Repurchase interval in days as the merchant set it; null when unset. |
added | object | When the shop added the product, e.g. '3 months ago'. |
last_sync | object | When the feed last updated this product, e.g. '2 hours ago', or 'never'. |
disabled | boolean | True when the product is disabled in theMarketer; skip it in campaigns. |
issues | object | Feed problems found on this product ('invalid_url', 'invalid_image'; in a list_products listing with health="with_issues" also 'price_below_acquisition_price' when that is why it is listed); skip products that have any. Null when the product is flagged with issues that are not listed here. |
extra_attributes | object | The feed's extra attributes (colour, size, material, ...), only those with a value. |
page | integer | Page returned, starting at 1. |
per_page | integer | Products per page, always 15. |
total | integer | Products matching the filters, across all pages; when the note says the pages run through the products containing one word, the products containing that word. |
pages | integer | Total pages at 15 products each. |
has_more | boolean | True when a later page exists; the note names it. |
currency | object | ISO code of the account currency every price is in; null when the shop's currency settings could not be loaded. |
price_format_note | string | How price_display renders prices, with an example, or why it is null. |
filters_applied | map<string> | The filters and sort in effect, with brand and category resolved to 'name (id)', so what matched is unambiguous. |
note | object | What to know about the rows on this page, which page to ask for next, or why nothing matched and what to try; null on a last page with nothing to add. |
Get product options
get_product_optionsReadList the categories and brands of this shop's catalogue, with the ids the product filters accept.
Use before list_products when the user names a category or brand and you are not sure of its exact spelling, or when the user asks what categories or brands the shop has.
Without kind both lists come at once, 50 of each per page; with kind only that list, 200 per page. search narrows by name (case-insensitive, anywhere in the name or path) and falls back to the closest spellings when nothing matches literally. Category labels are full paths ("Root > Parent > Leaf"); list_products accepts the path, a unique leaf name or the id.
Parameters
| Parameter | Type | Description |
|---|
kind | enum | "categories" or "brands" for one list; omit for both. One of: categories, brands. |
search | string | Text the name must contain, case-insensitive; omit for
the full list. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
kind | object | The one list requested, or null when both were returned. |
categories | object[] | Categories on this page, as full paths 'Root > Parent > Leaf', each with the id list_products.category accepts. |
id | string | The id the brand / category filters accept. |
label | string | Brand name, or the category's full path 'Root > Parent > Leaf'. |
product_count | object | Products under this brand, when known; null for categories. |
brands | object[] | Brands on this page, each with the id list_products.brand accepts and its product count when known. |
id | string | The id the brand / category filters accept. |
label | string | Brand name, or the category's full path 'Root > Parent > Leaf'. |
product_count | object | Products under this brand, when known; null for categories. |
categories_total | integer | Categories matching, across all pages; 0 when only brands were requested. |
brands_total | integer | Brands matching, across all pages; 0 when only categories were requested. |
page | integer | Page returned, starting at 1. |
pages | integer | Total pages: 200 per page with kind, 50 of each list per page without it. |
has_more | boolean | True when a later page exists; the note says which. |
note | object | Which page to ask for next, or that search matched nothing literally and the closest spellings are shown; null otherwise. |
Get product details
get_product_detailsReadEverything about one catalogue product, by section: summary, reviews, price and stock history, orders.
Use when the user asks about a specific product: its price and availability, what customers say about it, how its price or stock moved, or who bought it. Find the product with list_products first, or pass its shop id or SKU when exactly one product carries it.
By default returns summary (the product as list_products shows it, plus description, revenue and extra attributes) and reviews; ask for history and orders when the question needs them. Review ratings are on a 5-point scale, the summary's rating on 10. Reviews carry no reviewer names. Orders come newest first, 25 per page. Prices are in the account currency with price_display rendered the shop's way.
Parameters
| Parameter | Type | Description |
|---|
productrequired | string | The product's id (24 hex characters, as list_products
returns it), or the shop's product id or SKU when exactly
one product carries it. Variants often share a SKU: then the
call lists them and you pass the id of the one you mean. |
sections | enum[] | Which sections to return; omit for summary and
reviews. Any of: summary, reviews (star distribution and the
latest 15 reviews), history (price and stock changes as
dated rows), orders (orders containing the product, 25 per
page). |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
product_id | string | theMarketer id of the product described. |
sections_returned | string[] | The sections included on this call, in the order the keys below are listed. |
summary | object | Identity, prices, availability, stats, description, revenue and extra attributes. |
reviews | object | Star distribution and the latest reviews (rating on 5, no reviewer names). |
history | object | Price and stock history as dated rows. |
orders | object | Orders containing the product, 25 per page, newest first. |
Update product
update_productDestructiveChange what the product page lets a merchant edit: disable or enable a product, exclude it from recommendations, set its repurchase interval, or fill a custom column.
Use when the user wants a product hidden from campaigns and recommendations (or shown again), kept out of product recommendations only, given a repurchase interval in days for replenishment automations, or tagged in one of the catalogue's custom columns. Prices, stock, names, images and categories come from the product feed and cannot be edited here; the feed sync is where those change.
Pass at least one change. Each field is applied only when it differs from the product's current value, and changed lists what was actually changed. Custom columns are the ones the Products page shows beyond its standard fields (feed attributes such as colour or season, or columns the merchant added); a name that matches none is answered with the available ones. Find the product with list_products, or pass its shop id or SKU when exactly one product carries it.
Parameters
| Parameter | Type | Description |
|---|
productrequired | string | The product's id (24 hex characters, as list_products
returns it), or the shop's product id or SKU when exactly one
product carries it. Variants often share a SKU: then the call
lists them and you pass the id of the one you mean. |
disabled | boolean | true to disable the product in theMarketer (left out of
campaigns and recommendations), false to enable it again. |
exclude_from_recommendations | boolean | true to keep the product out of
product recommendations while it stays in the catalogue,
false to include it again. |
recurrence | integer | Repurchase interval in days, 0 or more; 0 clears it. |
column | string | Name of the custom column to fill, as the Products page
lists it (for example "season" or "Collection"); requires
value. |
value | string | The text to write into column; requires column. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
product_id | string | theMarketer id of the product changed. |
name | object | Product name, from the feed. |
changed | string[] | The fields this call changed: 'disabled', 'exclude_from_recommendations', 'recurrence' or the custom column's name. Empty when the product already had the requested values. |
disabled | boolean | True when the product is now disabled in theMarketer and left out of campaigns and recommendations. |
exclude_from_recommendations | boolean | True when the product is now left out of product recommendations while staying in the catalogue. |
recurrence | object | Repurchase interval in days, as now set; null when unset. |
custom_attributes | map<string> | The product's custom attributes after the change, as text; a list value is joined with ', '. |
links | object | Where to open this product in the theMarketer web app. |
app_url | object | Link to this object in the theMarketer web app, for the user to review or edit it there. Null when the app URL is not configured on this MCP server. |
switch_domain_url | object | Only for accounts with several domains: open this first if the app is currently on another domain, then follow app_url. The app keeps one current domain per user and app_url only works on the domain this object belongs to. |
List orders
list_ordersReadList the shop's orders for a period with their value, status, buyer, source and products, plus the order count, revenue and average order value of the whole selection.
Use when the user asks what was ordered recently, how many orders or how much revenue a period brought, which orders came from a campaign, automation or popup, what a given customer bought, or to look up one order by its number. Orders come 15 per page, newest first by default, with total, pages and has_more; the note names the next page. stats covers every order matching the filters, not just the page; with search, only when the matches fit on one page.
Each order carries the shop's order number, total, discount and shipping in the account currency (currency), the shop's status text, the date, the source that led to it and its product lines. contact_email is masked when the account anonymises contact data; pass contact_id to get_contact_details for the buyer's profile.
For the day-by-day, week-by-week or month-by-month split between orders attributed to theMarketer and the rest use get_order_trend; for the sent, clicks, conversion rate and revenue of each channel use get_ecommerce_stats.
Parameters
| Parameter | Type | Description |
|---|
period | enum | Date window to list: today, yesterday, this_week,
last_week, this_month, last_month, last_30_days (default),
last_60_days or last_90_days. The "_days" windows cover N
whole days including today: last_30_days is today and the 29
days before it. Ignored when start and end are given. One of: today, yesterday, this_week, last_week, this_month, last_month, last_30_days, last_60_days, last_90_days. Default: 'last_30_days'. |
start | string | First day of a custom window, YYYY-MM-DD; requires end. |
end | string | Last day of a custom window, YYYY-MM-DD, inclusive; requires
start. |
status | string | Text the order status must contain, case-insensitive:
"completed" matches "Completed" and "Completed (paid)". It is
matched against the statuses this shop's orders carry, which
get_order_options lists; a text none of them contains gives
an empty result naming them. Omit for every status. |
source | enum | Only orders from one source: newsletter (email campaigns),
email_automation, bulk_sms (SMS campaigns), sms_automation,
bulk_push (push notification campaigns), popup, website
(orders placed on the site without a marketing touch), import,
or retail (orders recorded outside the website). Omit for
every source. The sources do not cover every order: some
orders listed as 'Website' or 'Push notifications automation'
match none of them, and the first page's note counts the
period's orders no source covers. One of: newsletter, email_automation, bulk_sms, sms_automation, bulk_push, popup, website, import, retail. |
search | string | Order number or buyer email to look for. Omit to list
every order. |
sort | enum | Order the rows by date (default) or order number. To see
the orders of one status, filter by status; of one buyer,
pass their email as search; of one source, filter by
source. One of: date, number. Default: 'date'. |
descending | boolean | true (default) for newest or highest number first;
false for the reverse. Default: True. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
orders | object[] | The orders on this page, in sort order. |
number | object | The shop's own order number. |
total | object | Order value in the account currency, as the shop reported it. |
status | object | Order status as the shop reports it (e.g. 'Completed', 'Pending', 'Cancelled'). |
contact_email | object | The buyer's email (or phone when the order carries no email), masked when the account anonymises contact data; null when the order has no contact. |
contact_id | object | The buyer's contact id; pass it to get_contact_details for the full profile. Null when the order has no contact. |
date | object | Order date as YYYY-MM-DD; null when the shop sent none. |
source | object | What led to the order: 'Newsletter', 'Email Automation', 'Bulk SMS', 'SMS Automation', 'Bulk Push notifications', 'Push notifications automation', 'Popups', 'Import', 'Retail', or 'Website' for an order without a marketing touch. Some 'Website' and 'Push notifications automation' orders match no source filter. |
discount | number | Discount applied, in the account currency. |
shipping | number | Shipping charged, in the account currency. |
lines | object[] | The products in the order. |
name | object | Product name at the time of the order; null when the product has since left the catalogue. |
quantity | object | Units ordered. |
unit_price | object | Price paid per unit, in the account currency. |
product_id | object | The product's id in theMarketer; pass it to get_product_details. Null when the product is gone. |
image | object | Absolute URL of the product's main image. |
page | integer | Page returned, starting at 1. |
per_page | integer | Orders per page, always 15. |
total | integer | Orders matching the filters, across all pages. |
pages | integer | Total pages at 15 orders each. |
has_more | boolean | True when a later page exists; the note names it. |
stats | object | Order count, revenue and average order value of every order matching the filters in the period, search included; {"unavailable": reason} when they could not be loaded or the search matches more orders than one page holds (the orders still answer). |
period | object | The date window that was applied. |
preset | string | The named period applied (e.g. 'last_30_days'), or 'custom' when start and end were given. |
start | string | First day the figures cover (YYYY-MM-DD), inclusive: the window actually applied, a named period resolved to its dates. |
end | string | Last day the figures cover (YYYY-MM-DD), inclusive: the window actually applied. |
currency | object | ISO code of the account currency every amount is in; null when the shop's currency settings could not be loaded. |
note | object | Which page to ask for next, why nothing matched and what to try, or, with source on the first page, how many orders of the period match no source filter; null on a last page with nothing to add. |
Get order options
get_order_optionsReadList the values the order filters accept: the statuses this shop's orders carry and the sources orders can come from.
Use before list_orders when the user names an order status and you are not sure how the shop spells it (each shop sends its own status texts, e.g. "Completed", "Finalizată", "processing"), or when the user asks which statuses or sources exist. The statuses come from the shop's own orders; the sources are the fixed set list_orders understands.
Without kind both lists come at once; with kind only that list. search narrows by text (case-insensitive, anywhere in the value) and falls back to the closest spellings when no status matches literally.
Parameters
| Parameter | Type | Description |
|---|
kind | enum | "statuses" or "sources" for one list; omit for both. One of: statuses, sources. |
search | string | Text the status or source must contain, case-insensitive;
omit for the full lists. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
kind | object | The one list requested, or null when both were returned. |
statuses | string[] | Every order status this shop's orders carry, spelled as the shop sends it; list_orders.status matches any part of these, case-insensitive. |
sources | object[] | The values list_orders.source accepts, with what each covers. |
key | string | The value to pass as list_orders.source. |
label | string | How the Orders page names this source. |
description | string | Which orders the source covers. |
note | object | Set when search matched no status literally and the closest spellings are shown, or when the shop has no orders yet; null otherwise. |
Get order trend
get_order_trendReadShow how many orders and how much revenue the shop made per day, week or month, split between orders attributed to theMarketer and the rest.
Use when the user asks how sales are trending, how much of the shop's revenue theMarketer drives, or wants a chart-ready series of orders over the last two weeks, three and a half months or fifteen months. Each bucket has the orders and revenue that followed a theMarketer campaign, automation or popup (attributed_*) and every other order (other_*), in the account currency (currency); totals sums the buckets. Buckets end now and come oldest first: 15 days, 15 weeks or 15 months.
For the orders themselves, with buyer, status and products, use list_orders; for the sent, clicks, conversion rate and revenue of each channel use get_ecommerce_stats.
Parameters
| Parameter | Type | Description |
|---|
granularity | enum | Bucket size: daily (default, the last 15 days),
weekly (the last 15 weeks, Monday to Sunday) or monthly (the
last 15 calendar months). One of: daily, weekly, monthly. Default: 'daily'. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
granularity | string | The bucket size returned: daily, weekly or monthly. |
buckets | object[] | Up to 15 buckets ending now, oldest first. |
label | string | The bucket as the chart labels it: a weekday name ('Mon'), a day span ('01 Sep - 07 Sep') or a month name ('Sep'). |
attributed_orders | integer | Orders that followed a theMarketer campaign, automation or popup. |
other_orders | integer | Every other order the shop recorded. |
attributed_revenue | number | Value of the attributed orders, in the account currency. |
other_revenue | number | Value of the other orders, in the account currency. |
totals | object | The sum over every bucket returned. |
attributed_orders | integer | Attributed orders across all buckets. |
other_orders | integer | Other orders across all buckets. |
attributed_revenue | number | Attributed revenue across all buckets, in the account currency. |
other_revenue | number | Other revenue across all buckets, in the account currency. |
currency | object | ISO code of the account currency the revenue is in; null when the shop's currency settings could not be loaded. |
note | string | What 'attributed' means and which span the buckets cover. |
List coupons
list_couponsReadList the account's discount codes as the Coupons page shows them, newest first.
Use when the user asks which coupons exist, which codes a customer can still use, whether a code was redeemed, or where a code came from. For "which codes can customer X still use" call with search=<their email> and used=false, then check expires_at: expired codes are listed too. To register a new code use save_coupon; for a customer's points and rewards use get_contact_details with the loyalty section.
Each coupon carries its code, value and type ('fixed', 'percentage' or 'shipping'), whether it was used, when it expires, its source ('API', 'popup', 'launcher', 'Campaign: <name>', 'Automation: <name>') and the contact it is assigned to (contact_email, masked when the account anonymises contact data, and contact_id for get_contact_details). Results come 15 per page with total, pages and has_more; the note names the next page.
Parameters
| Parameter | Type | Description |
|---|
search | string | Part of a coupon code, or a contact's email address, to
look for; case-insensitive. Omit to list every coupon. |
used | boolean | true for codes already redeemed, false for codes still
available; omit for both. |
type | enum | Only coupons of this kind: "fixed" (amount off),
"percentage" (percent off) or "shipping" (free shipping). One of: fixed, percentage, shipping. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
coupons | object[] | The coupons on this page, most recently created first. |
code | object | The discount code customers type at checkout. |
value | object | Amount off for a fixed coupon, percent off for a percentage coupon; carries no meaning for a shipping coupon. |
type | object | 'fixed' (amount off), 'percentage' (percent off) or 'shipping' (free shipping). |
used | boolean | True once the code was redeemed in an order. |
expires_at | object | When the code stops being valid, as an ISO timestamp; expired codes are listed too, so compare it with today. |
source | object | Where the code came from: 'API' for codes registered through save_coupon, 'popup' or 'launcher' for codes handed out on the site, 'Campaign: <name>' or 'Automation: <name>' for codes generated by a send. |
campaign_name | object | The campaign or automation the code was generated for, when there is one. |
contact_email | object | Email of the contact the code is assigned to; null for an unassigned code. Masked when the account anonymises contact data. |
contact_id | object | theMarketer id of that contact, for get_contact_details; null for an unassigned code. |
created_at | object | When the code was recorded, as an ISO timestamp. |
page | integer | Page returned, starting at 1. |
per_page | integer | Coupons per page, always 15. |
total | integer | Coupons matching the filters, across all pages. |
pages | integer | Total pages at 15 each. |
has_more | boolean | True when a later page exists; the note names it. |
note | object | Which page to ask for next, or why nothing matched and what to try; null on a last page with results. |
Save coupon
save_couponDestructiveRegister a discount code in theMarketer, optionally assigned to one contact.
Use when the user wants theMarketer to know a discount code, so campaigns can show it or a customer can receive it. The code itself is created in the shop; theMarketer only records it, and the same code can be registered more than once. Use list_coupons to see the codes already recorded.
Assigning the code to a contact records it on that contact and runs the reward-redeemed automation, so the customer may receive an email. An email that matches no contact leaves the coupon unassigned; with points to deduct, an unknown email stops the save. Points to deduct are checked against the contact's loyalty balance first: a deduction larger than the balance stops the save. Returns the confirmation with the code, the assignment as theMarketer recorded it and, after a deduction, the points left.
Parameters
| Parameter | Type | Description |
|---|
coderequired | string | The discount code customers type at checkout. |
typerequired | enum | "fixed" (amount off), "percentage" (percent off) or "shipping"
(free shipping). One of: fixed, percentage, shipping. |
valuerequired | number | Amount or percent, depending on type: greater than 0, and at
most 100 for a percentage; any number, 0 included, for shipping. |
expiration_daterequired | string | Last valid moment, in the future, as "YYYY-MM-DD"
(expires at the start of that day, so give tomorrow's date or
later) or "YYYY-MM-DD HH:MM:SS", on the shop's clock. |
email | string | Contact to assign the coupon to. An email that matches no
contact leaves the coupon unassigned; with points to deduct, an
unknown email stops the save. |
decrease_points | integer | Loyalty points to deduct from the contact given in
email for this coupon, at most their current balance; 0 for
none. Needs email. Default: 0. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
saved | boolean | True: theMarketer confirmed the coupon was recorded. |
code | string | The discount code as recorded. |
assigned_to | object | The contact email the coupon was assigned to, lowercased; null when no email was given or no contact has it (note says which). |
contact_id | object | theMarketer id of the contact the coupon was assigned to, for get_contact_details; null when unassigned. |
points_left | object | The contact's loyalty balance after the deduction; null when no points were deducted or the balance could not be read back. |
note | string | What to keep in mind: the code must exist in the shop, and why the coupon is unassigned or how to check its assignment. |
Get e-commerce stats
get_ecommerce_statsReadReport e-commerce performance per theMarketer channel over a period.
Use when the user asks how the shop performed through theMarketer, which channel brings the orders, or how much revenue campaigns and automations generated in a given month or window. The default is the last 30 days; pick a named period or give start and end for an exact window. It covers only what theMarketer sent and the orders that followed: for the shop's total order count and revenue, or the orders themselves, use list_orders; for the attributed-vs-other trend use get_order_trend; for per-campaign figures use get_campaign_report; for who is on the site right now use get_realtime_visitors.
Returns one block per channel (newsletter, email_automation, sms_automation, push_automation, push, sms) plus total, each with sent, clicks, transactions, conversion_rate (transactions per 100 clicks) and revenue as numbers in currency. Archived campaigns are left out of the campaign channels. The period block gives the first and last day the figures cover, so a follow-up call with those dates as start and end returns the same figures.
Parameters
| Parameter | Type | Description |
|---|
period | enum | Named window: "today", "yesterday", "this_week",
"last_week", "this_month" or "last_month"; "last_30_days"
(default), "last_60_days" or "last_90_days" count whole days
back from today, today included: "last_30_days" is today
and the 29 days before it. Weeks and months are
calendar-aligned. Ignored when start and end are given. One of: today, yesterday, this_week, last_week, this_month, last_month, last_30_days, last_60_days, last_90_days. Default: 'last_30_days'. |
start | string | First day of a custom window (YYYY-MM-DD), inclusive; give
it together with end. |
end | string | Last day of a custom window (YYYY-MM-DD), inclusive; give it
together with start. Must not be before start. A custom
window can be as long as needed. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
period | object | The date window that was applied. |
preset | string | The named period applied (e.g. 'last_30_days'), or 'custom' when start and end were given. |
start | string | First day the figures cover (YYYY-MM-DD), inclusive: the window actually applied, a named period resolved to its dates. |
end | string | Last day the figures cover (YYYY-MM-DD), inclusive: the window actually applied. |
currency | object | ISO code of the account currency every revenue is in; null when the shop's currency settings could not be loaded. |
newsletter | object | Email campaigns (one-off newsletters); archived campaigns are not counted. |
sent | integer | Messages sent through this channel. |
clicks | integer | Clicks on those messages. |
transactions | integer | Orders placed after a click on this channel's messages. |
conversion_rate | number | Transactions per 100 clicks, in percent; 0 when there were no clicks. |
revenue | number | Revenue of the attributed orders, in currency. |
email_automation | object | Emails sent by automations (welcome, abandoned cart, ...). |
sent | integer | Messages sent through this channel. |
clicks | integer | Clicks on those messages. |
transactions | integer | Orders placed after a click on this channel's messages. |
conversion_rate | number | Transactions per 100 clicks, in percent; 0 when there were no clicks. |
revenue | number | Revenue of the attributed orders, in currency. |
sms_automation | object | SMS sent by automations. |
sent | integer | Messages sent through this channel. |
clicks | integer | Clicks on those messages. |
transactions | integer | Orders placed after a click on this channel's messages. |
conversion_rate | number | Transactions per 100 clicks, in percent; 0 when there were no clicks. |
revenue | number | Revenue of the attributed orders, in currency. |
push_automation | object | Push notifications sent by automations. |
sent | integer | Messages sent through this channel. |
clicks | integer | Clicks on those messages. |
transactions | integer | Orders placed after a click on this channel's messages. |
conversion_rate | number | Transactions per 100 clicks, in percent; 0 when there were no clicks. |
revenue | number | Revenue of the attributed orders, in currency. |
push | object | Push-notification campaigns; archived campaigns are not counted. |
sent | integer | Messages sent through this channel. |
clicks | integer | Clicks on those messages. |
transactions | integer | Orders placed after a click on this channel's messages. |
conversion_rate | number | Transactions per 100 clicks, in percent; 0 when there were no clicks. |
revenue | number | Revenue of the attributed orders, in currency. |
sms | object | SMS campaigns; archived campaigns are not counted. |
sent | integer | Messages sent through this channel. |
clicks | integer | Clicks on those messages. |
transactions | integer | Orders placed after a click on this channel's messages. |
conversion_rate | number | Transactions per 100 clicks, in percent; 0 when there were no clicks. |
revenue | number | Revenue of the attributed orders, in currency. |
total | object | All six channels added up; its conversion_rate is computed over the summed clicks and transactions. |
sent | integer | Messages sent through this channel. |
clicks | integer | Clicks on those messages. |
transactions | integer | Orders placed after a click on this channel's messages. |
conversion_rate | number | Transactions per 100 clicks, in percent; 0 when there were no clicks. |
revenue | number | Revenue of the attributed orders, in currency. |
Get real-time visitors
get_realtime_visitorsReadShow who is on the website right now, from the last 5 minutes of tracking.
Use when the user asks how many people are on the site at the moment, where they came from, what they are looking at, or how many of today's visitors are known contacts. For past performance use get_ecommerce_stats, list_orders or get_campaign_report.
Returns visitors (last 5 minutes): total, from_marketer (visitors who arrived from a theMarketer campaign) with its percent, desktop and mobile counts with their percents, and sources with the percent of visitors from email, direct, social, other and search traffic. top_pages lists the 20 most viewed pages of the last 30 minutes with their view counts, and known_vs_anonymous gives the sessions per day over the last 8 days split into identified contacts and anonymous visitors. It does not list individual visitors. A section that could not be loaded reads {"unavailable": <reason>} while the others still answer.
Parameters
| Parameter | Type | Description |
|---|
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
visitors | object | Visitors active in the last 5 minutes with their origin and device split. Or {"unavailable": <reason>} when this one section could not be loaded (the others are unaffected). |
top_pages | object | Up to 20 most viewed pages of the last 30 minutes, most viewed first. Or {"unavailable": <reason>} when this one section could not be loaded (the others are unaffected). |
known_vs_anonymous | object | Sessions per day over the last 8 days, split into identified contacts and anonymous visitors. Or {"unavailable": <reason>} when this one section could not be loaded (the others are unaffected). |
note | object | Set when nobody is on the site right now or when a section is unavailable; null otherwise. |
To help us resolve it quickly, include your theMarketer domain, the assistant you use (Claude, ChatGPT, OpenClaw, ...), the approximate time and the exact error message shown. Please do not include passwords or API keys.