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.
Audience14
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. 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 | Exact tag name; only contacts carrying that tag. |
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: its id as
list_segments returns it, 24 hex characters. 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, and why rows are missing when they were omitted on request; null when this page is the last and complete. |
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 reads so on accounts without a loyalty program. 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). Wins over email when both are given. |
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 program. 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. 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 and tags go through update_contact afterwards. Manage residence/location in the authenticated theMarketer web app.
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. |
last_name | string | Last name of the contact. |
phone | string | Phone number, international format preferred (e.g.
+40700000000). 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 a phone number. 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, 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). Wins over email when both are given. |
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. Cannot be changed on
accounts that anonymise contacts; warnings says so. |
first_name | string | New first name for the contact. |
last_name | string | New last name for the contact. |
phone | string | New phone number, with the country prefix (e.g.
+40700000000). 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. |
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 column values, as {label: value}.
Never include health, biometric, government ID, payment-card
or authentication data.
Merged into the contact's existing columns by label; columns
you do not name are kept. |
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. |
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. |
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. |
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 the contact's own earlier choice, 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, in two steps: 1. Preview: pass contact_ids, a tag or a segment_id (several combine with AND) and no confirm_token. Nothing changes; the result gives matched, a sample, warnings, an ask_user question and a confirm_token. Ask the user the ask_user question in full, even when they already named every channel, and wait for their answer. 2. Confirm: call again with the same selection, channels=["email", "sms", "push", "loyalty"] and the preview's confirm_token. Only a preview gives one, so even when the user says they already saw the numbers, preview first. If the selection has changed since the preview, nothing changes and you are told to preview again.
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). Wins over email when both are
given. |
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 for the preview, required
to confirm, 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: exact tag name; every contact carrying it. |
segment_id | string | Bulk: every contact in this custom segment, its id as
list_segments returns it (24 hex characters). |
confirm_token | string | Bulk, step 2 only: the confirm_token the preview returned for this same selection, after the user has agreed. It only comes from a preview; leave it out to preview. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
contact_id | object | theMarketer id of the contact changed (one contact). |
unsubscribed_now | string[] | Channels THIS CALL turned off: the contact was subscribed to them before the call and is opted out now. Empty when the call changed nothing. |
already_unsubscribed | string[] | Channels the contact had ALREADY opted out of before this call; the call did not touch them. These opt-outs predate the call and are the contact's standing choice - do not 'correct' or re-subscribe them. |
still_subscribed_to | string[] | Channels the contact remains subscribed to after this call (not requested, so left on). |
skipped | string[] | Requested channels the contact has no identifier for (no phone for sms, no push token for push/mobile_push); nothing changed for these, and nothing needed to. |
unsubscribed | object | Bulk: True once the contacts are opted out, False for a preview (nothing changed). |
matched | object | Bulk: contacts the selection matches right now. |
confirm_token | object | Bulk preview: pass it back as confirm_token, with the same selection and all four channels, to unsubscribe these contacts once the user has agreed. |
sample | object | Bulk preview: the first contacts the selection matches, up to 15, for the user to check before confirming. |
ask_user | object | Bulk preview: the question to put to the user before confirming, word for word or translated into their language. It carries the count and every warning; do not shorten it. |
warnings | object | Bulk preview: what the unsubscribe will do. Tell the user every item before asking them to confirm. |
note | object | Bulk: what happened, what to tell the user and what to do next. |
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 in two steps: 1. Preview: pass contact_ids, a tag or a segment_id (several combine with AND) and no confirm_token. Nothing is deleted; the result gives matched, a sample, warnings, an ask_user question and a confirm_token. Ask the user the ask_user question in full and wait for their answer. 2. Confirm: call again with the same selection and the preview's confirm_token. Only a preview gives one, so even when the user says they already saw the numbers, preview first. If the selection has changed since the preview, nothing is deleted and you are told to preview again. theMarketer then deletes the contacts in the background, so the result says the job was accepted, not that every record is already gone.
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). Wins over email
when both are given. |
contact_ids | string[] | Bulk: theMarketer contact ids (24 hex characters each, as list_contacts returns them), up to 1000. |
tag | string | Bulk delete: exact tag name; every contact carrying it. |
segment_id | string | Bulk delete: every contact in this custom segment, its
id as list_segments returns it (24 hex characters). |
confirm_token | string | Bulk, step 2 only: the confirm_token the preview returned for this same selection, after the user has agreed. It only comes from a preview; leave it out to preview. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
deleted | boolean | True when the contact is now hidden and opted out of every channel, or, for a bulk delete, when theMarketer accepted the job. False for a preview: nothing changed. Email and phone stay on file for suppression; this is not erasure. |
contact_id | object | theMarketer id of the suppressed contact (single delete). |
matched | object | Bulk delete: contacts the selection matches right now. |
confirm_token | object | Bulk preview: pass it back as confirm_token, with the same selection, to delete these contacts once the user has agreed. |
sample | object | Bulk preview: the first contacts the selection matches, up to 15, for the user to check before confirming. |
ask_user | object | Bulk preview: the question to put to the user before confirming, word for word or translated into their language. It carries the count and every warning; do not shorten it. |
warnings | object | Bulk preview: what the delete will do. Tell the user every item before asking them to confirm. |
note | object | Bulk delete: what happened and what to do next. |
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. 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 fields present in the batch, replaces the contact's tags and custom columns with the batch's, resets its consent to the batch's and restores a contact removed with delete_contact. Tags apply to the whole import. 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 import runs in the background. status completed means the counts are in report; processing means the contacts were still being written when this tool stopped waiting, and list_contacts will show them; awaiting_approval means the file was parked for manual approval and nothing was imported yet.
Parameters
| Parameter | Type | Description |
|---|
contactsrequired | object[] | The rows to import, 1 to 1000. Each needs email or
phone; the other fields are optional, and only the columns at
least one row fills are sent, so a field left empty on every row
is not touched on updated contacts. |
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 import, applied to every new contact and
replacing the tags of every updated one. Omit to import without
tags, which also clears the tags of updated contacts. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
import_id | string | theMarketer id of the import; its report page in the theMarketer app is /audience/contacts/import/report/<import_id>. |
status | string | completed: the counts are in report. processing: the contacts were still being written when this tool stopped waiting; they keep landing and list_contacts shows them. awaiting_approval: the import was parked for manual approval and nothing was imported yet. |
rows_sent | integer | Rows in the CSV this tool sent. |
recognized_contacts | integer | Rows counted in the file before importing; normally equals rows_sent. |
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 completed: imported, duplicated, invalid and blacklisted row counts, plus links to a CSV of each non-empty outcome (opening them needs a theMarketer session). |
note | string | What the status means for this import, 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, and when. Use get_contact_details to look at one of the contacts, and get_report with scope="automation" for how the automation performed.
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. 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. Each one is a contact entering one automation: the contact's email, campaign_segment (the automation's name), barcode, mobile_install and subscribed_push. |
count | integer | Number of entries on this page. |
page | integer | Page returned, starting at 1. |
has_more | boolean | True when this page came back full (count equals per_page), so a further page may exist. No total is reported for this listing, so the next page can turn out empty. |
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 the audience's segments, or fetch one custom segment with its rules.
Use when the user asks which segments exist, how large one is, or what rules define it, 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 with total, pages and has_more; the note names the next page, and search narrows the list by name before paging. Passing segment_id returns that one custom segment with its rules and ignores page. Counts come from the last background evaluation, not from now: -1 means the count was not computed in this listing (every built-in System segment shows -1), which is not zero. System segments have ids starting with system-, have no rules and 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 of one custom segment (24 hex characters, as this
tool returns it) to fetch in full, rules included. System
ids are not accepted. |
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. |
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, in theMarketer's order. |
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: no rules, no document, and not usable with list_contacts. |
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 - every system segment reports -1 here. |
rule_count | integer | Number of rules the segment is built from; 0 for system. |
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 matched (after search, when given), 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 | How to get the next page when there is one, and that search narrows the listing by name; null when this page is the last. |
Create segment
create_segmentWriteCreate a custom segment from rules; theMarketer evaluates it in the background.
Use when the user wants a reusable, named group of contacts defined by conditions: to target a campaign, to watch a cohort, or to filter list_contacts by segment_id. Not for a one-off count or list: list_contacts with filters answers that without creating anything. Call list_segments first to reuse a segment that already exists.
Each rule names a condition, an operator (omit it where the condition has a single one) and a value; some conditions add unit, campaign_id or max_value. Which conditions this domain can use, their operators and what each value must be come from get_audience_options(kind="segment_conditions"); the values one condition accepts (tags, segments, brands, categories, products, stores, custom-attribute values) from get_audience_options(kind="segment_values", condition=..., search=...). Names are accepted wherever theMarketer shows a picker and are resolved to ids; an unknown or ambiguous name is answered with the closest matches, so a segment never silently matches nobody. 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"]}.
The result says whether a segment was created or an identical one already existed (then nothing is written unless allow_duplicate=true) and lists the rules as stored. Evaluation is asynchronous: the count in list_segments stays 0 until the first run, and membership keeps updating unless lock is set. With match="all" every rule must hold; with match="any" one rule is enough.
Parameters
| Parameter | Type | Description |
|---|
namerequired | string | Name of the new segment, as it will appear in theMarketer. |
rulesrequired | object[] | Between 1 and 20 rules; match says whether a contact must satisfy all of them or any one. |
match | enum | 'all' requires every rule to match (AND); 'any' accepts a
contact matching at least one rule (OR). One of: all, any. Default: 'all'. |
lock | boolean | Freeze membership after the first evaluation: theMarketer
keeps refreshing the count but no longer adds or removes
contacts. Off by default, so the segment stays live. Default: False. |
allow_duplicate | boolean | Create the segment even when one with exactly the
same rules already exists. Off by default; the existing segment
is returned instead. Default: False. |
skip_value_check | boolean | Do not resolve or verify values against the
domain (brand, product, category, segment, campaign, tag, store,
tier and custom-attribute values). Values must then already be
in the stored form (24-hex ids where the description says id).
Only when you know the value exists, e.g. a tag or attribute
value an unfinished import is creating; otherwise an unknown
value is answered with the closest matches. Default: False. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
created | boolean | True when a new segment was stored; false when an identical one already existed and nothing was written. |
segment_id | object | Id of the new segment (usable as list_contacts.segment_id), or of the existing one when created is false. Null when the new segment could not be found by name yet. |
name | string | Name of the segment created or found. |
rules_applied | string[] | The rules as written, one readable line each; names that were resolved to ids show as name (id), and expanded category subtrees list every category included. |
existing_segment | object | The segment with the same rules that already existed, when created is false. |
links | object | Where to open this segment 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. |
note | string | What happens next, or why nothing was created. |
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. |
Campaigns8
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.
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 and the open, click and conversion rates in percent, resend and A/B parts included. Rows come 20 per page by send date descending, drafts without a date last. 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 | theMarketer's status word: draft, pending (scheduled), waiting (scheduled A/B parent), queued, running, paused, ab_testing, sent, archived or payment_error. |
status_label | object | The status as the theMarketer app words it, where it differs from status: pending and waiting are 'Scheduled', queued and running are 'Sending now', payment_error is 'Not sent - Payment error'; draft, paused, sent and archived read the same in both. |
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 | When the campaign is or was scheduled to go out (UTC); null for drafts. |
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). |
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 send at which the resend goes out; null when no resend is configured. |
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 update_campaign 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 (long lines wrapped at 200 characters) with content_total_chars, pages and a note naming the next page; the other sections ignore page.
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 and resend flags, 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 content only, the other sections are not paged). |
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, A/B and resend flags, 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. |
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 and for each part with data (main, resend, A/B variants, winner), the currency, the last open and click times and survey results; 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; A/B and resend parts
are reported under it. |
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 | theMarketer's status word. |
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) 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 when the user wants a new email campaign. With draft=true (default) the campaign is fully configured and left as a draft: nothing is sent until someone schedules it in the theMarketer app. 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 with no cancel once scheduled (update_campaign can still move send_at or change the content while it is scheduled). 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. 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. Omit sender_email and sender_name for the domain's default sender; a given sender_email must be one of the verified senders (get_campaign_details lists them). Omit segments for the whole email audience, or pass names or keys as list_segments shows them.
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. The result carries the campaign id, its status, the effective UTC send time, the sender and audience as stored 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;
recipients never see it. |
subject_linerequired | string | Email subject; 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. Default: ''. |
reply_to | string | Reply-to address; defaults to the domain's default
reply-to. |
segments | string[] | Segments to send to, by name or key as list_segments
shows them (e.g. 'VIP customers', 'Active 30 days',
activity::active_30_days, custom::<segment id>). Contacts in
any of them receive the campaign. Omit to send to the whole
email 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 (now + 15 minutes). |
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 48 hours. Default: False. |
optimize_for | enum | Goal of the optimal-time model when use_optimal_time
is set: opening or clicking. One of: opening, clicking. 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), which cannot be cancelled afterwards. Default: True. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
campaign_id | string | Id of the new campaign (24 hex characters), for update_campaign, send_test_campaign, get_campaign_details and reports. |
status | string | 'scheduled' when theMarketer accepted the send, 'draft' when draft=true or when the account is blocked from sending (see sending_block). |
send_at | object | Effective send time in UTC as theMarketer stored it, after the 15-minute minimum was applied; null when the schedule step was not reached. |
timezone | object | Timezone the send time was interpreted in when send_at had no offset; null when an offset was given or nothing was scheduled. |
sender | object | The From name, address and reply-to actually stored: the domain's defaults when none were given. |
name | object | From (sender) display name. |
email | object | From (sender) address. |
reply_to | object | Reply-to address; null when not set. |
audience | object | The audience as stored: type, segments, exclusions, extra recipients and smart sending. |
type | string | 'all' for the whole email audience, 'segment' when one or more segments were selected. |
segments | string[] | Selected segments as 'name (key)'; contacts in any of them receive the campaign. |
exclude_segments | string[] | Excluded segments as 'name (key)'; their contacts are removed from the audience at send time. |
extra_recipients | string[] | Addresses that get a copy when the first batch goes out, outside the audience and without the [Test] prefix. |
smart_sending | boolean | Whether contacts who received a campaign recently are skipped. |
recipients_estimate | map<integer> | Recipients per selected segment key (or 'all') at creation time, from theMarketer's segment counter; the final audience is recounted when the send starts, after exclusions and smart sending. |
sending_block | object | Why the account cannot send right now (payment, reputation, email_free_limit), in which case the campaign stayed a draft; null when sending is allowed. |
links | object | Where to open this campaign 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. |
note | string | What happens next and how to follow it. |
Update email campaign
update_campaignDestructiveChange an email campaign that is still a draft or scheduled: subject, sender, content, audience, send time or UTM tags, one or several at once.
Use when the user wants to edit a campaign before it goes out, or to move a scheduled send. Pass campaign_id (from create_campaign or list_campaigns) and only the fields to change; everything else is kept. 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. A scheduled campaign is scheduled again with the new values, which is also how a scheduled send is moved; there is no cancel, and send_now=true sends as soon as possible instead.
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). 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 sends to the whole email audience. 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 and the audience as stored. 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 or list_campaigns). |
name | string | New campaign name as shown in theMarketer. |
subject_line | string | New email subject. |
preview_text | string | New preheader text shown next to the subject. |
sender_name | string | New From (sender) display name. |
sender_email | string | New From (sender) address; must be one of the domain's
verified senders. |
reply_to | string | New reply-to address. |
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 to send to, by name or key as list_segments
shows them. Replaces the whole stored list: to add one, pass
every current segment plus the new one (get_campaign_details
shows them). An empty list sends to the whole email audience. |
exclude_segments | string[] | Segments to exclude at send time, by name or key;
replaces the stored list (empty list clears it). |
extra_recipients | string[] | Addresses that get a copy outside the audience;
replaces the stored list (empty list clears it). |
smart_sending | boolean | Whether to skip contacts who received a campaign
recently. |
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 | Send as soon as possible (now + 15 minutes) instead of
at a specific time; 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 or clicking. One of: opening, clicking. |
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. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
campaign_id | string | Id of the campaign that was updated. |
status | string | Status after the update: 'draft' or 'scheduled' (a scheduled campaign is re-scheduled with the new values). |
send_at | object | Effective send time in UTC as theMarketer stores it now; for a scheduled campaign the 15-minute minimum applies again. |
timezone | object | Timezone the send time was interpreted in when send_at had no offset; null when an offset was given or nothing was scheduled. |
changed | string[] | The parameters that were applied, in the order given. |
audience | object | The audience as stored after the update. |
type | string | 'all' for the whole email audience, 'segment' when one or more segments were selected. |
segments | string[] | Selected segments as 'name (key)'; contacts in any of them receive the campaign. |
exclude_segments | string[] | Excluded segments as 'name (key)'; their contacts are removed from the audience at send time. |
extra_recipients | string[] | Addresses that get a copy when the first batch goes out, outside the audience and without the [Test] prefix. |
smart_sending | boolean | Whether contacts who received a campaign recently are skipped. |
links | object | Where to open this campaign 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. |
note | string | What happens next and how to follow it. |
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 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: use create_campaign or update_campaign to schedule the send.
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). |
recipientsrequired | string[] | One to five email addresses to send the test to.
Duplicates are sent once. |
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 'running', 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 and cannot be paused or cancelled: use update_campaign to move its send_at. 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 | theMarketer's status word when the tool read the campaign. |
status_after | string | theMarketer's status word after the call; 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 go back to pending. A scheduled campaign is not paused and goes out at its send_at (update_campaign moves it), a draft is scheduled with update_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 | theMarketer's status word when the tool read the campaign. |
status_after | string | theMarketer's status word after the call; 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. |
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 | Text to look for in the product name, SKU, shop id or
URL, case-insensitive. 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 | integer | Discount as a whole percent; 0 when none. |
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 | string[] | Feed problems found on this product ('invalid_url', 'invalid_image'); skip products that have any. |
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. |
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 | Which page to ask for next, or why nothing matched and what to try; null on a last page with results. |
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.
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. 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 without a marketing touch), import, or retail (orders
recorded outside the website). Omit for every source. 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), value, number, status,
email or source. One of: date, value, number, status, email, source. Default: 'date'. |
descending | boolean | true (default) for newest, highest or Z-A 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. |
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 for every order matching the filters in the period; {"unavailable": reason} when the figures could not be loaded this time (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, or why nothing matched and what to try; null on a last page with results. |
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. Returns the confirmation with the code and the assignment.
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; any
number, 0 included, for shipping. |
expiration_daterequired | string | Last valid moment as "YYYY-MM-DD" (expires at the
start of that day) or "YYYY-MM-DD HH:MM:SS". |
email | string | Contact to assign the coupon to; an unknown email leaves the
coupon unassigned. |
decrease_points | integer | Loyalty points to deduct from that contact for this
coupon; 0 for none. 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. An email that matches no contact leaves the coupon unassigned. |
note | string | What to keep in mind: the code must exist in the shop, and how to check the 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 largest orders, 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 echoes the window that was applied.
Parameters
| Parameter | Type | Description |
|---|
period | enum | Named window: "today", "yesterday", "this_week",
"last_week", "this_month", "last_month", "last_30_days"
(default), "last_60_days" or "last_90_days". Weeks and months
are calendar-aligned; the "_days" windows end now. 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. |
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. |
Reports4
Get one performance metric of a marketing channel, day by day.
Use when the user asks how email, SMS or push campaigns, automations or signup forms performed over a period: sends, opens, clicks, revenue, conversion, unsubscribes, form impressions and signups. The default window is the last 30 days; pick a named period or give start and end, and add compare_to for the change against the previous period or the previous year. Windows cover at most 90 days. For one campaign's full report use get_campaign_report; for orders and revenue per theMarketer channel use get_ecommerce_stats or list_orders; for how many contacts there are use get_audience_evolution (today) or get_audience_history (over time).
Returns series with a value per day, total over the window, by_campaign with the campaigns or automations behind it (largest first, 25 per page; campaigns_total, pages and has_more say how many there are and the note names the next page). With a comparison it adds previous_series, previous_total and change_percent. unit says whether the numbers are counts, percents or amounts in currency.
Parameters
| Parameter | Type | Description |
|---|
channelrequired | enum | "email", "sms", "push" or "forms" (signup forms). One of: email, sms, push, forms. |
metricrequired | enum | What to measure. email accepts sent, opens, unique-opens,
open-rate, unique-open-rate, clicks, unique-clicks, click-rate,
unique-click-rate, transactions, revenue, conversion-rate,
average-order-value, unsubscribed, unsubscribe-rate, bounced,
bounce-rate, complaints and complaint-rate; sms and push accept
sent, clicks, unique-clicks, click-rate, unique-click-rate,
transactions, revenue, conversion-rate, average-order-value,
unsubscribed and unsubscribe-rate; forms accept impressions,
total-impressions, subscribed-users, total-subscribed-users,
subscribe-rate and total-subscribe-rate. One of: sent, open-rate, unique-open-rate, click-rate, unique-click-rate, opens, unique-opens, clicks, unique-clicks, transactions, revenue, conversion-rate, average-order-value, unsubscribed, complaints, bounced, bounce-rate, complaint-rate, unsubscribe-rate, total-impressions, total-subscribed-users, total-subscribe-rate, impressions, subscribed-users, subscribe-rate. |
scope | enum | What to aggregate: "campaigns" (default) or "automation"
for email, sms and push; "popups" (default) or "embedded" for
forms. One of: campaigns, automation, popups, embedded. |
period | enum | Named window: "today", "yesterday", "this_week",
"last_week", "this_month", "last_month", "last_30_days"
(default), "last_60_days" or "last_90_days". Weeks run Monday
to Sunday and months are calendar months; the "_days" windows
end today and include 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), 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; the window
covers at most 90 days. |
compare_to | enum | "previous_period" compares with the same number of
days ending the day before the window, "previous_year" with
the same dates one year earlier; "none" (default) adds no
comparison. One of: previous_period, previous_year, none. Default: 'none'. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
channel | string | The channel measured: email, sms, push or forms. |
scope | string | What was aggregated: campaigns or automation; popups or embedded for forms. |
metric | string | The metric code measured, e.g. 'open-rate'. |
unit | string | What the numbers are: 'count', 'percent' (0-100) or 'currency' (amounts in currency). |
currency | object | ISO code of the account currency for a 'currency' metric; null for counts and percents, or when the shop's currency settings could not be loaded. |
window | object | The dates that were 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. |
compare_to | string | The comparison applied: 'previous_period', 'previous_year' or 'none'. |
previous_start | object | First day of the comparison window; null without a comparison. |
previous_end | object | Last day of the comparison window; null without a comparison. |
series | object[] | The metric's value for each day. |
date | string | The day, YYYY-MM-DD. |
value | number | The metric's value for that day. |
total | object | The metric over the whole window: counts and amounts summed, rates computed over the window's totals. |
previous_series | object[] | The metric's value for each day of the comparison window; empty without a comparison. |
date | string | The day, YYYY-MM-DD. |
value | number | The metric's value for that day. |
previous_total | object | The metric over the comparison window; null without a comparison. |
change_percent | object | Percent change of total against previous_total; null without a comparison. |
by_campaign | object[] | The campaigns or automations behind the total, largest value first, 25 per page. |
ref | string | theMarketer's reference number for the campaign or automation, as the report labels it; find it by name in list_campaigns for its id. |
name | object | Its name, as shown in theMarketer. |
value | number | The metric's value for it over the window. |
campaigns_total | integer | How many campaigns or automations contributed in the window, across every page of by_campaign. |
page | integer | The by_campaign page returned, starting at 1. |
pages | integer | Total by_campaign pages at 25 campaigns each. |
has_more | boolean | True when a later by_campaign page exists; the note names it. The metric totals cover the whole window regardless of page. |
note | object | Which page to ask for the next campaigns, and set when the window is long or when no campaign of this scope was active in it; null otherwise. |
Get audience history
get_audience_historyReadGet the day-by-day history of an audience count: subscribers per channel or email list health.
Use for trends: how the number of email, SMS, push or loyalty subscribers, or the active, inactive, cleaned and bounced email counts, changed over time. The default window is the last 30 days; pick a named period or give start and end, and add compare_to for the change against the previous period or the previous year. Windows cover at most 90 days. For today's numbers and the last 7 days' joins and losses use get_audience_evolution; for list health today use get_audience_breakdown; for campaign performance use get_report.
Returns series with one value per day: the end-of-day snapshot of the count, not that day's signups, and latest, the last recorded day's count in the window. With a comparison it adds previous_series, previous_latest and change_percent. The note explains the values.
Parameters
| Parameter | Type | Description |
|---|
metricrequired | enum | Which count to follow: total-subscribed-emails,
total-subscribed-sms, total-subscribed-push,
total-subscribed-loyalty, total-unsubscribed-emails,
total-unsubscribed-sms, total-unsubscribed-push,
total-unsubscribed-loyalty, total-active-emails,
total-inactive-emails, total-cleaned-emails or
total-bounced-emails. One of: total-subscribed-emails, total-subscribed-sms, total-subscribed-push, total-subscribed-loyalty, total-unsubscribed-emails, total-unsubscribed-sms, total-unsubscribed-push, total-unsubscribed-loyalty, total-active-emails, total-inactive-emails, total-cleaned-emails, total-bounced-emails. |
period | enum | Named window: "today", "yesterday", "this_week",
"last_week", "this_month", "last_month", "last_30_days"
(default), "last_60_days" or "last_90_days". Weeks run Monday
to Sunday and months are calendar months; the "_days" windows
end today and include 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), 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; the window
covers at most 90 days. |
compare_to | enum | "previous_period" compares with the same number of
days ending the day before the window, "previous_year" with
the same dates one year earlier; "none" (default) adds no
comparison. One of: previous_period, previous_year, none. Default: 'none'. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
metric | string | The count followed, e.g. 'total-subscribed-emails'. |
window | object | The dates that were 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. |
compare_to | string | The comparison applied: 'previous_period', 'previous_year' or 'none'. |
previous_start | object | First day of the comparison window; null without a comparison. |
previous_end | object | Last day of the comparison window; null without a comparison. |
series | object[] | The count at the end of each day; a day at 0 has no recorded count. |
date | string | The day, YYYY-MM-DD. |
value | number | The metric's value for that day. |
latest | object | The last recorded day's count in the window; null when no day was recorded. |
previous_series | object[] | The count at the end of each day of the comparison window; empty without a comparison. |
date | string | The day, YYYY-MM-DD. |
value | number | The metric's value for that day. |
previous_latest | object | The last recorded day's count in the comparison window; null without a comparison. |
change_percent | object | Percent change of latest against previous_latest; null without a comparison or when the earlier count is 0. |
note | string | How to read the values. |
List analytics reports
list_analytics_reportsReadList the reports saved in the Analytics section of theMarketer.
Use when the user asks which reports or dashboards they have set up, or before get_analytics_report when the report's name is not known. Both the reports theMarketer provides ('system') and the ones the account built ('custom') are listed. For one metric of one channel without a saved report use get_report.
Returns reports with each report's index, name, type and when it was created and last changed, 50 per page with count, pages and has_more. Several reports often share a name such as "Custom report": tell them apart by index and by when they were created or changed, and pass the index to get_analytics_report for the figures.
Parameters
| Parameter | Type | Description |
|---|
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
reports | object[] | The saved reports on this page, most recently created first. |
index | integer | The report's position in the saved list; pass it or the name to get_analytics_report. |
name | string | The report's name, as shown in theMarketer. |
type | string | 'system' for the reports theMarketer provides, 'custom' for those the account built. |
created_at | object | When the report was created, as theMarketer labels it (e.g. '05 Sep 2026'). |
updated | object | When the report was last changed, as theMarketer labels it (e.g. '2 days ago'). |
count | integer | How many reports are saved, across all pages. |
page | integer | Page returned, starting at 1. |
pages | integer | Total pages at 50 reports each. |
has_more | boolean | True when a later page exists; the note names it. |
note | object | Which page to ask for next, or that the account has no saved reports; null on a last page with results. |
Get analytics report
get_analytics_reportReadGet one report saved in the Analytics section of theMarketer, over a period.
Use when the user asks for one of their saved reports or dashboards by name ("show me my Email overview report"), or for the figures the Analytics page shows for a period. The default window is the last 30 days compared with the previous period; pick a named period or give start and end, and set compare_to to change or drop the comparison. Windows cover at most 90 days. Use list_analytics_reports for the report names; for one metric of one channel without a saved report use get_report; for one campaign use get_campaign_report.
Returns the report's title and type, the window applied and widgets: each with its channel, scope, metrics (day-by-day series, total and change_percent, with a unit of count, percent or currency) and by_campaign with the campaigns behind the figures. links opens the report in theMarketer.
Parameters
| Parameter | Type | Description |
|---|
reportrequired | string | The report's name as list_analytics_reports shows it
(case-insensitive; part of the name works when it matches one
report), or its index as a number. |
period | enum | Named window: "today", "yesterday", "this_week",
"last_week", "this_month", "last_month", "last_30_days"
(default), "last_60_days" or "last_90_days". Weeks run Monday
to Sunday and months are calendar months; the "_days" windows
end today and include 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), 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; the window
covers at most 90 days. |
compare_to | enum | "previous_period" (default) compares with the same
number of days ending the day before the window,
"previous_year" with the same dates one year earlier; "none"
leaves the comparison out. One of: previous_period, previous_year, none. Default: 'previous_period'. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
index | integer | The report's position in the saved list. |
title | string | The report's name. |
type | string | 'system' for a report theMarketer provides, 'custom' for one the account built. |
window | object | The dates that were 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. |
compare_to | string | The comparison applied: 'previous_period', 'previous_year' or 'none'. |
previous_start | object | First day of the comparison window; null without a comparison. |
previous_end | object | Last day of the comparison window; null without a comparison. |
currency | object | ISO code of the account currency every 'currency' metric is in; null when the shop's currency settings could not be loaded. |
widgets | object[] | The report's widgets in the order the page shows them. |
title | string | The widget's title, as shown in the report. |
channel | string | What the widget measures: 'email', 'sms', 'push', 'audience' or 'signup_forms'. |
scope | object | What it aggregates: 'campaigns' or 'automation'; 'popups' or 'embedded' for signup forms; null for audience counts. |
metrics | object[] | The widget's metrics, each day by day with its total. |
metric | string | The metric code, e.g. 'open_rate'. |
unit | string | What the numbers are: 'count', 'percent' (0-100) or 'currency' (amounts in the report's currency). |
series | object[] | The metric's value for each day. |
total | object | The metric over the whole window; null when it has no total. |
change_percent | object | Percent change against the comparison window; null without a comparison. |
by_campaign | object[] | The campaigns or automations behind the widget's figures, with their value per metric; empty for widgets without a campaign split. |
ref | string | theMarketer's reference number for the campaign or automation, as the report labels it; find it by name in list_campaigns for its id. |
name | object | Its name, as shown in theMarketer. |
values | map<number> | Its value for each of the widget's metrics, keyed by metric code. |
links | object | Where to open this report 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 the report has no widgets; null otherwise. |
Reviews3
Get reviews overview
get_reviews_overviewReadShow how customers rate the shop: score, NPS split, rating trend, most reviewed products and most active reviewers.
Use when the user asks how the shop is rated, what its NPS is, whether ratings are improving, which products get the most reviews, who reviews the most, or how many reviews await moderation. For the reviews themselves use list_reviews; for one product's reviews and star distribution use get_product_details; to approve or reject a review use moderate_review.
Returns the score on the account's scale (score_as: '0-10', '0-5' or 'nps'), the nps and the average rating on both 0-10 and 0-5, reviews_total, reviews_last_30_days and pending_reviews, the promoters, passives and detractors with counts and percents, what the account collects ('products' or 'orders'), the rating trend over the last 8 periods, the 10 most_reviewed_products and the 10 top_reviewers (names and contact ids, no email addresses). Every section loads on its own: one that could not be loaded reads {"unavailable": <reason>} while the others still answer, and the note says when no review is approved yet.
Parameters
| Parameter | Type | Description |
|---|
trend | enum | Period size of the rating trend: "daily", "weekly",
"monthly" (default) or "quarterly"; the trend always covers
the last 8 periods. One of: daily, weekly, monthly, quarterly. Default: 'monthly'. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
score | object | The shop's score on the scale the account chose (score_as); null until a review is approved. |
score_as | object | The scale the account scores on: '0-10', '0-5' (stars) or 'nps' (Net Promoter Score, -100 to 100). |
nps | object | Net Promoter Score of the reviewers, -100 to 100: promoters (9-10) minus detractors (0-6) as a percent; null until a review is approved. |
average_rating_10 | object | Average rating of the approved reviews on 0-10; null when none is approved. |
average_rating_5 | object | The same average as stars on 0-5; null when none is approved. |
reviews_total | object | Approved reviews on record; null when the score section could not be loaded. |
reviews_last_30_days | object | Reviews received in the last 30 days; null when the score section could not be loaded. |
pending_reviews | object | Reviews waiting for moderation; list them with list_reviews. Null when the count could not be loaded. |
promoters | object | Reviewers who rated 9 or 10 on 0-10; null when the score section could not be loaded. |
passives | object | Reviewers who rated 7 or 8 on 0-10; null when the score section could not be loaded. |
detractors | object | Reviewers who rated 0 to 6 on 0-10; null when the score section could not be loaded. |
collects | object | What customers are asked to review: 'products' (one review per product bought) or 'orders' (one review per order); null when the settings could not be loaded. |
trend | object | The average rating per period over the last 8 periods, oldest first. Or {"unavailable": <reason>} when this one section could not be loaded (the others are unaffected). |
most_reviewed_products | object | Up to 10 products with the most reviews, most reviewed first. Or {"unavailable": <reason>} when this one section could not be loaded (the others are unaffected). |
top_reviewers | object | Up to 10 contacts who wrote the most reviews, most active first; names and contact ids only. Or {"unavailable": <reason>} when this one section could not be loaded (the others are unaffected). |
note | object | Set when no review is approved yet, when reviews await moderation, or when a section is unavailable; null otherwise. |
List reviews
list_reviewsReadList customer reviews as the Feedback pages show them: newest first with ids and paging, or the 15 highest- or lowest-rated with product and contact.
Use when the user asks what customers wrote, which reviews await moderation, what the best or worst reviews say, or to find a review before approving, rejecting or deleting it with moderate_review. For the shop's score and NPS use get_reviews_overview; for one product's reviews use get_product_details.
The default, sort="newest", pages through the reviews 15 at a time, newest first, filtered by status and optionally by search; each row carries its review_id (for moderate_review), status, stars, text, date and the reviewer's name, without the product. sort="highest_rating" or "lowest_rating" shows the first 15 reviews ranked by rating with their product (shop id, name) and contact (contact id, name) and any photos, but no review ids; it takes no search or page. total, pages, has_more and the note say how to get the next page or the other view. Reviewer email addresses are never included.
Parameters
| Parameter | Type | Description |
|---|
status | enum | Which reviews to list: "pending" (default; awaiting
moderation), "approved", "rejected" or "all". One of: pending, approved, rejected, all. Default: 'pending'. |
sort | enum | "newest" (default; by date, with review ids and paging),
"highest_rating" or "lowest_rating" (the first 15 by rating,
with product and contact, no ids). One of: newest, highest_rating, lowest_rating. Default: 'newest'. |
search | string | Text to look for in what the customer wrote; it does not
match the reviewer's name or the product. Only with
sort="newest". Omit to list every review of the chosen status. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
reviews | object[] | The reviews on this page, in sort order. |
review_id | object | The review's id, to pass to moderate_review; null on the rating-ranked list, which carries no ids. |
status | object | 'pending' (awaiting moderation), 'approved' (counted in the product's rating) or 'rejected' (on record, not counted). |
stars | number | The rating as stars, 0 to 5. |
text | object | What the customer wrote; null for a rating without text. |
date | object | When the review was left, as the page shows it (a date or a relative label such as '2 days ago'). |
product | object | The product reviewed; null on the newest-first list, which carries no product. |
contact | object | Who wrote the review; the newest-first list gives the name only, the rating-ranked list adds the contact id. |
media | string[] | URLs of the photos attached to the review; empty when none. |
status | string | The status filter applied: 'pending', 'approved', 'rejected' or 'all'. |
sort | string | The order applied: 'newest', 'highest_rating' or 'lowest_rating'. |
pending_reviews | object | Reviews waiting for moderation; known when status is 'pending' or when ranking by rating, null otherwise. |
page | integer | Page returned, starting at 1. |
per_page | integer | Reviews per page, always 15. |
total | object | Reviews matching the filter across all pages; null when ranking by rating, which shows the first 15 only. |
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, how to get the other view (ids and paging, or products and contacts), or why nothing matched. |
Moderate review
moderate_reviewDestructiveApprove, reject or delete one customer review, as the Feedback moderation page does.
Use when the user wants a pending review accepted (approve), declined or kept out of the product's rating (reject), or removed altogether (delete). Find the review and its id with list_reviews first; the ranked view carries no ids. Deleting is irreversible: confirm with the user before calling with action="delete".
Approving marks the review approved in the account: its rating counts in the product's rating and review count, the contact's NPS class is set from the rating and the loyalty programme may credit points to the contact's balance. Rejecting keeps the review on record as rejected and out of the product's rating; rejecting an approved review removes its rating from the product. Deleting removes the review from the account for good. Returns the review's status before and after, its stars and text, the product with its star distribution, and whether anything changed: a review that already has the requested status is left as it is.
Parameters
| Parameter | Type | Description |
|---|
review_idrequired | string | The review's id, 24 hexadecimal characters, as
list_reviews returns it with sort="newest". |
actionrequired | enum | "approve" to accept the review, "reject" to keep it on
record without counting it, or "delete" to remove it
permanently. One of: approve, reject, delete. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
review_id | string | The review acted on. |
action | string | 'approve', 'reject' or 'delete'. |
changed | boolean | True when the call changed the review; false when it already had the requested status. |
status_before | object | The review's status before the call. |
status_after | object | The review's status after the call; null once deleted. |
stars | number | The review's rating as stars, 0 to 5. |
text | object | What the customer wrote, up to 200 characters; null for a rating without text. |
product | object | The product reviewed with its current star distribution; null when it could not be loaded. |
note | object | What the action changed beyond the review itself: the product's rating, the contact's NPS class, loyalty points. |
Transactional4
Send transactional email
send_transactional_emailDestructiveSend one transactional email: an order confirmation, a delivery update, a receipt.
Use for a single operational email to one recipient. Never for marketing or newsletters: those are campaigns (create_campaign). This sends a real email and uses one transactional email credit, two with bcc, so confirm the content and the recipient with the user first. Check the balance with get_transactional_credits and follow delivery in list_transactional_messages, which also shows bounces.
Returns result "success" with the message_id of the stored message, the recipient and the credits_used. With queue=true the email is accepted as soon as it is queued (queued true, no message_id yet) and its delivery shows in list_transactional_messages within a few minutes. An email that could not be sent is answered with an error naming the reason: a recipient domain without mail records, a sender that is not verified in the account, no credit left, or an account in sandbox mode, where only the sandbox recipients listed by get_transactional_credits can be reached.
Parameters
| Parameter | Type | Description |
|---|
torequired | string | Recipient email address; its domain needs MX records. |
subjectrequired | string | Email subject. |
bodyrequired | string | Operational email body, HTML or plain text; an open-tracking
pixel is added. Do not include passwords, authentication codes,
payment-card data, government identifiers or health data. |
sender | string | From address as a bare email (shop@example.com), one of
the account's verified senders (get_sending_domain lists
them). Defaults to the account's default sender. |
reply_to | string | Reply-to email address. |
bcc | string | One extra recipient who gets a copy; uses a second credit. |
queue | boolean | Queue the email instead of sending it right away. Default: False. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
result | string | 'success' when theMarketer accepted the email for delivery. |
message_id | object | Id of the stored message; null when the email was queued, whose id appears in list_transactional_messages once it is sent. |
bcc_message_id | object | Id of the copy sent to bcc; null when no copy was asked for. |
queued | boolean | True when the email was queued for sending rather than sent right away. |
recipient | string | The address the email was sent to. |
credits_used | integer | Transactional email credits this call used: 1, or 2 with a bcc copy. |
note | object | When the email was queued or a copy was sent; null otherwise. |
Send transactional SMS
send_transactional_smsDestructiveSend one transactional SMS: an order update or a delivery notice.
Use for a single operational text message to one number. Never for marketing: SMS campaigns are created in theMarketer. This sends a real SMS through the account's provider and uses SMS credit per segment (160 characters in the GSM alphabet, 70 with other characters), so confirm the text and the number with the user first. Check the balance with get_transactional_credits and follow delivery in list_transactional_messages with channel="sms".
Returns result "success" with the message_id, the recipient as sent, the provider's status label when it gave one, and how many segments the text takes. An SMS that could not be sent is answered with an error naming the reason, such as no credit left or an account in sandbox mode, where only the sandbox numbers listed by get_transactional_credits can be reached and the text is limited to 160 characters.
Parameters
| Parameter | Type | Description |
|---|
torequired | string | Recipient in international format: "+", country code and
number, digits only, e.g. +40712345678. Spaces and dashes are
removed. |
contentrequired | string | Operational message text; do not include authentication
codes, passwords, payment-card data or other restricted data.
Characters outside the GSM alphabet (most accented letters,
emoji) shorten each segment to 70 characters. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
result | string | 'success' when theMarketer handed the SMS to the provider. |
message_id | object | Id of the stored SMS; null when none was assigned. |
recipient | string | The number the SMS was sent to, in international format. |
provider_status | object | The provider's status label at hand-over, such as 'Sent' or 'Queued at network'; null when the provider gave none. Rely on result for the outcome. |
segments | integer | How many SMS segments the text takes: 160 characters per segment (153 each when split) for texts in the GSM alphabet, 70 (67 each when split) when the text has other characters. Each segment uses credit. |
note | object | When the text spans several segments or uses characters that shorten them, and where to follow delivery. |
Get transactional credits
get_transactional_creditsReadShow the SMS and transactional email credit: balance in EUR, how many messages it pays for, and whether each channel is in sandbox mode.
Use before a send, when a send says there is no credit left, or when the user asks "how many SMS can I still send" or "how much transactional credit is left". Marketing email credit (campaigns) is a different balance: use get_costs for it.
Returns sms with the credit in EUR, the messages it pays for at the account's price per SMS, that price, and the channel's sandbox state; and email with the balance in EUR, the plan it is priced on with its cost and volume, the emails the balance still pays for (derived from the balance and the plan price, so remaining_is_estimate is true), the automatic top-up settings and the sandbox state. A channel in sandbox mode reaches only its sandbox_recipients, the account's own test addresses or numbers. Each channel loads on its own: one that could not be loaded reads {"unavailable": <reason>} while the other still answers.
Parameters
| Parameter | Type | Description |
|---|
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
sms | object | The SMS credit and sandbox state. Or {"unavailable": <reason>} when this channel could not be loaded (the other is unaffected). |
email | object | The transactional email credit, its plan and sandbox state. Or {"unavailable": <reason>} when this channel could not be loaded (the other is unaffected). |
note | object | When SMS is not set up, when a channel is in sandbox mode, when a section could not be loaded, and where marketing email credit is. |
List transactional messages
list_transactional_messagesReadList the transactional emails or SMS sent in a period, newest first, with their delivery status and the window's summary numbers, as the Transactional > Emails / SMS pages show them.
Use after send_transactional_email or send_transactional_sms to confirm delivery, to see what bounced or failed, or to answer "did the order confirmation reach this customer" (search by the address or number). Recipients are masked as on the page; for one contact's whole message history across campaigns and automations use get_contact_details(sections=["deliverability"]).
Returns one page of 15 messages with id, time, status, masked recipient and, for emails, sender, subject, opens and a view link, or, for SMS, the text and its cost; the summary (sent, delivered, bounced or failed, with percents) for every message in the window; and total, pages, has_more and the note saying how to get the next page or widen the window. The summary covers the whole window even when search narrows the messages.
Parameters
| Parameter | Type | Description |
|---|
channel | enum | "email" (default) for transactional emails or "sms" for
transactional SMS. One of: email, sms. Default: 'email'. |
period | enum | The window: "this_month" (default), "today", "yesterday",
"this_week", "last_week", "last_month" or "last_30_days".
Ignored when start and end are given. One of: this_month, today, yesterday, this_week, last_week, last_month, last_30_days. Default: 'this_month'. |
start | string | First day of a custom window, YYYY-MM-DD; give end too. |
end | string | Last day of a custom window, YYYY-MM-DD, inclusive; give
start too. |
search | string | Text to look for: for emails in the recipient, sender and
subject; for SMS in the recipient number. Omit to list every
message in the window. |
page | integer | Page number, starting at 1. Default: 1. |
domain_id | string | Target domain. |
Returns
| Field | Type | Description |
|---|
channel | string | The channel listed: 'email' or 'sms'. |
window | object | The date window that was applied, with the days a named period resolved to. |
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. |
search | object | The search text applied; null when none was. |
messages | object[] | The messages on this page, newest first. |
message_id | object | theMarketer's id of the message. |
channel | string | 'email' or 'sms'. |
sent_at | object | When the message was sent, as the page shows it: day/month/year and hour:minute in Romanian time (Europe/Bucharest). |
status | object | Delivery status as the page shows it: for emails 'delivered', 'bounced', 'failed' or 'queued'; for SMS the provider's label such as 'Delivered', 'Sent' or 'Failed'. |
recipient | object | The recipient address or number as the page shows it, masked (e.g. 'an***@example.com') when the account masks personal data. |
sender | object | The From address the email went out with; null for SMS. |
subject | object | The email subject; null for SMS. |
opens | object | How many times the email was opened; null for SMS. |
is_copy | object | True when this row is the bcc copy of another email; null for SMS. |
content | object | The SMS text; null for emails. |
cost_eur | object | What the SMS cost, in EUR; null for emails. |
view_url | object | Link to view the email as it was sent; null for SMS. |
summary | object | Sent, delivered and bounced or failed counts with their percents for every message in the window, whatever search and page are. Or {"unavailable": <reason>} when the summary could not be loaded; the messages are unaffected. |
page | integer | Page returned, starting at 1. |
per_page | integer | Messages per page, always 15. |
total | integer | Messages in the window 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, why nothing matched and how to widen the window, and what search matches. |
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.