Skip to content
Coritan Docs

Organization API: Org Staff Marketing: Staff

The 45 Organization API operations for staff.

View as Markdown

Part of Org Staff Marketing.

Method Path Summary
GET /api/v1/orgs/{org_slug}/staff/marketing/ads Get ads
DELETE /api/v1/orgs/{org_slug}/staff/marketing/ads/connections/{connection_id} Disconnect one ad account
POST /api/v1/orgs/{org_slug}/staff/marketing/ads/connections/{connection_id}/sync Read one ad account now
GET /api/v1/orgs/{org_slug}/staff/marketing/ads/return Get ad return
GET /api/v1/orgs/{org_slug}/staff/marketing/ads/spend What was spent, grouped by platform, campaign or day
GET /api/v1/orgs/{org_slug}/staff/marketing/ads/spend/manual Spend entered by hand, newest first
POST /api/v1/orgs/{org_slug}/staff/marketing/ads/spend/manual Enter spend for a channel that has no connection
DELETE /api/v1/orgs/{org_slug}/staff/marketing/ads/spend/manual/{entry_id} Remove an entry of spend entered by hand
POST /api/v1/orgs/{org_slug}/staff/marketing/ads/{platform}/accounts Pick which of the platform's accounts to read
POST /api/v1/orgs/{org_slug}/staff/marketing/ads/{platform}/connect Start signing in to an ad platform
GET /api/v1/orgs/{org_slug}/staff/marketing/announcements Read the Discord webhook settings for announcements
PUT /api/v1/orgs/{org_slug}/staff/marketing/announcements Save or remove the Discord webhook for announcements
GET /api/v1/orgs/{org_slug}/staff/marketing/announcements/history Read the announcements that were posted
POST /api/v1/orgs/{org_slug}/staff/marketing/announcements/post Post an announcement to Discord
GET /api/v1/orgs/{org_slug}/staff/marketing/campaigns List the campaign links
POST /api/v1/orgs/{org_slug}/staff/marketing/campaigns Save a campaign link
POST /api/v1/orgs/{org_slug}/staff/marketing/campaigns/preview Check a campaign link and build its address without saving it
GET /api/v1/orgs/{org_slug}/staff/marketing/campaigns/results Read what each campaign brought in
PATCH /api/v1/orgs/{org_slug}/staff/marketing/campaigns/{campaign_id} Change or archive a campaign link
DELETE /api/v1/orgs/{org_slug}/staff/marketing/campaigns/{campaign_id} Delete a campaign link
GET /api/v1/orgs/{org_slug}/staff/marketing/campaigns/{campaign_id}/results Read what one campaign brought in
GET /api/v1/orgs/{org_slug}/staff/marketing/conversions List the ad platforms purchases are sent to, and how each is doing
GET /api/v1/orgs/{org_slug}/staff/marketing/conversions/deliveries Read what each platform was sent, and why anything was not
PUT /api/v1/orgs/{org_slug}/staff/marketing/conversions/{kind} Turn an ad platform on or off and change its settings
POST /api/v1/orgs/{org_slug}/staff/marketing/conversions/{kind}/rotate-feed-token Replace the token in the Microsoft Ads file address
POST /api/v1/orgs/{org_slug}/staff/marketing/conversions/{kind}/test Send a made-up purchase to an ad platform in test mode
GET /api/v1/orgs/{org_slug}/staff/marketing/flows List the automatic email flows, with their settings and how many emails each sent
GET /api/v1/orgs/{org_slug}/staff/marketing/flows/messages Read the log of flow emails, newest first
PUT /api/v1/orgs/{org_slug}/staff/marketing/flows/{key} Turn an email flow on or off and change its settings
POST /api/v1/orgs/{org_slug}/staff/marketing/flows/{key}/test Send a flow's sample email to yourself
GET /api/v1/orgs/{org_slug}/staff/marketing/referrals List the organization's referrals and what the program has paid
GET /api/v1/orgs/{org_slug}/staff/marketing/referrals/codes List referral codes, customers' and partners'
POST /api/v1/orgs/{org_slug}/staff/marketing/referrals/codes Make a partner code for a customer
PATCH /api/v1/orgs/{org_slug}/staff/marketing/referrals/codes/{code_id} Stop or restart a code, or change a partner's commission or label
POST /api/v1/orgs/{org_slug}/staff/marketing/referrals/{referral_id}/void Void a referral that has not been paid
GET /api/v1/orgs/{org_slug}/staff/marketing/reviews Read the Trustpilot review settings and how the invitations are doing
PUT /api/v1/orgs/{org_slug}/staff/marketing/reviews Change the Trustpilot review settings
GET /api/v1/orgs/{org_slug}/staff/marketing/subscribers List the newsletter's leads and count who can be mailed
GET /api/v1/orgs/{org_slug}/staff/marketing/subscribers/export.csv Download the addresses that can be mailed as a CSV file
GET /api/v1/orgs/{org_slug}/staff/marketing/subscribers/suppressions List the addresses that get no marketing email
POST /api/v1/orgs/{org_slug}/staff/marketing/subscribers/suppressions Add an address to the suppression list
DELETE /api/v1/orgs/{org_slug}/staff/marketing/subscribers/suppressions/{suppression_id} Take an address off the suppression list
DELETE /api/v1/orgs/{org_slug}/staff/marketing/subscribers/{lead_id} Delete a lead
GET /api/v1/orgs/{org_slug}/staff/marketing/tags The tags the storefront loads, and what an editor needs to draw them
PUT /api/v1/orgs/{org_slug}/staff/marketing/tags Replace the tags the storefront loads with the ones sent

GET /api/v1/orgs/{org_slug}/staff/marketing/ads

Every ad platform with its status, every connected ad account, and the last 30 days of spend.

Needs the Admin or Owner role. platforms lists Google Ads, Meta Ads, TikTok Ads, Microsoft Ads and Reddit Ads. A platform's status is not_configured (Coritan has not added its app credentials, so it cannot be connected), not_connected, pending (signed in, no account picked yet), connected, failing (an account has had errors and no successful read for an hour) or reauth (the sign-in ended, so connect again). connections has one entry for each ad account the sign-in found, with the same status words (an account that is found but not picked reads pending), when it was last read, the last error, how far its 13 month history has been read and its spend per currency. summary is the last 30 days of spend per currency, with entered spend included. warning is set when a sign-in ends within 14 days. Nothing here carries a token.

Name In Type Required
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

DELETE /api/v1/orgs/{org_slug}/staff/marketing/ads/connections/{connection_id}

Disconnect one ad account.

Needs the Admin or Owner role. The account's saved sign-in is deleted and nothing is read from it again. The spend already imported stays in your reports. Connect the platform again to read the account again.

Name In Type Required
connection_id path integer yes
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

POST /api/v1/orgs/{org_slug}/staff/marketing/ads/connections/{connection_id}/sync

Read one ad account now.

Needs the Admin or Owner role. With no body it reads today and the two days before. With from and to it reads those days again (at most 400, none before 13 months ago), which is how to refresh a month after the platform adjusts its numbers. The read runs in the background: check last_sync_at on the account. Answers 409 when the account's sign-in has ended or the account is not picked, and 429 after 4 requests an hour for one account.

Name In Type Required
connection_id path integer yes
org_slug path string yes

application/json

Field Type Required Description
from string (date) or null no The first day to read again. Send it with to, or send neither.
to string (date) or null no The last day to read again.
Status Meaning
202 Success.
422 The request is not valid. detail lists each problem.

GET /api/v1/orgs/{org_slug}/staff/marketing/ads/return

What the ad spend returned: orders, new customers, revenue, CAC and ROAS per platform, and per campaign.

Needs the Admin or Owner role. An order counts for the platform its last touch came from, when its invoice is paid and it is not free: the touch's source and medium name the platform, and when they do not, its click ids do. Within a platform an order counts for the campaign whose name (or id) equals its utm_campaign, ignoring case. new_customers counts customers whose first paid order it was. roas is revenue without tax over spend, cac_minor is spend over new customers, and platform_roas is the value the platform reports over spend. Each is empty when its divisor is zero. Rows are per currency: spend and revenue meet only when they are in the same currency, so an ad account billed in one currency and customers paying in another show as separate rows with no CAC or ROAS. Payback is not computed, because it needs a gross margin that is not kept. truncated is true when more than 50,000 orders were in the range.

Name In Type Required Description
org_slug path string yes
from query string (date) or null no The first day, as YYYY-MM-DD. The default is 30 days before to.
to query string (date) or null no The last day, as YYYY-MM-DD, included. The default is today in the organization's time zone.
group query string no platform or campaign. Default: platform.
currency query string or null no Only this currency.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

What was spent, grouped by platform, campaign or day

Section titled What was spent, grouped by platform, campaign or day

GET /api/v1/orgs/{org_slug}/staff/marketing/ads/spend

What was spent, grouped by platform, campaign or day.

Needs the Admin or Owner role. Every row is in one currency, and a platform that spent in two currencies has two rows: amounts in different currencies are never added. totals is the whole range per currency, even when limit (rows for each currency, by campaign) cuts the rows. Spend entered by hand is included, spread evenly over its days. The range is at most 400 days. Days follow each ad account's own time zone (Microsoft Ads and Reddit Ads follow the organization's), so a day's spend can differ a little from the platform's own report in another zone.

Name In Type Required Description
org_slug path string yes
from query string (date) or null no The first day, as YYYY-MM-DD. The default is 30 days before to.
to query string (date) or null no The last day, as YYYY-MM-DD, included. The default is today in the organization's time zone.
group query string no platform, campaign or day. Default: platform.
currency query string or null no Only this currency.
limit query integer no Rows to return for each currency when grouping by campaign. Default: 100.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Spend entered by hand, newest first

Section titled Spend entered by hand, newest first

GET /api/v1/orgs/{org_slug}/staff/marketing/ads/spend/manual

Spend entered by hand, newest first.

Needs the Admin or Owner role. ignored is true for an entry whose channel has since been connected, which reports leave out because the platform's own numbers cover it.

Name In Type Required Description
org_slug path string yes
limit query integer no Entries to return, newest first. Default: 100.
offset query integer no Entries to skip. Default: 0.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Enter spend for a channel that has no connection

Section titled Enter spend for a channel that has no connection

POST /api/v1/orgs/{org_slug}/staff/marketing/ads/spend/manual

Enter spend for a channel that has no connection.

Needs the Admin or Owner role. amount_minor is the whole amount over starts_on to ends_on (at most 400 days), and reports spread it evenly over those days. A platform with a picked account, or one that was already read for some of these days, is refused with 409 because its own numbers cover it. Answers 422 for a channel, currency, amount or dates that do not fit.

Name In Type Required
org_slug path string yes

application/json (required)

Field Type Required Description
channel string yes Where the money was spent: a platform key or another network such as x, linkedin, snapchat, pinterest or other.
label string yes What the spend was for, in your words.
currency string yes The three letter code of the currency it was paid in.
amount_minor integer yes The whole amount over the days, in the currency's smallest unit (cents for USD).
starts_on string (date) yes The first day the spend covers.
ends_on string (date) yes The last day the spend covers.
Status Meaning
201 Success.
422 The request is not valid. detail lists each problem.

Remove an entry of spend entered by hand

Section titled Remove an entry of spend entered by hand

DELETE /api/v1/orgs/{org_slug}/staff/marketing/ads/spend/manual/{entry_id}

Remove an entry of spend entered by hand. Needs the Admin or Owner role.

Name In Type Required
entry_id path integer yes
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Pick which of the platform's accounts to read

Section titled Pick which of the platform's accounts to read

POST /api/v1/orgs/{org_slug}/staff/marketing/ads/{platform}/accounts

Pick which of the platform's accounts to read.

Needs the Admin or Owner role. account_ids is the whole list: accounts you name start being read (their 13 month history first), and accounts of this platform you leave out stop being read but keep the spend already imported. At most 50 accounts for one platform. Answers 422 for an account that is not on the sign-in. Pick only the accounts that belong to this organization: a sign-in to a manager account can list accounts that are not yours.

Name In Type Required Description
platform path string yes One of google, meta, tiktok, microsoft, reddit.
org_slug path string yes

application/json (required)

Field Type Required Description
account_ids array of string yes The accounts to read, by the platform's own ids. Accounts of the platform that are not listed stop being read.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Start signing in to an ad platform

Section titled Start signing in to an ad platform

POST /api/v1/orgs/{org_slug}/staff/marketing/ads/{platform}/connect

Start signing in to an ad platform. Answers authorization_url, the platform's own page.

Needs the Admin or Owner role. Send the person to authorization_url. The platform sends the browser back to Coritan, which finds the accounts the sign-in can read and returns the person to return_path (a page of the console on the host of this request) with ads=connected or ads=error in the address. The link is good for 15 minutes. Answers 409 not_configured when the platform's app credentials have not been added to Coritan, and 422 when the request does not come from one of your console's hosts.

Name In Type Required Description
platform path string yes One of google, meta, tiktok, microsoft, reddit.
org_slug path string yes

application/json

Field Type Required Description
return_path string or null no The page of the console to come back to when the sign-in is done, such as /staff/marketing/ads. It is a path on the host the request came from.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Read the Discord webhook settings for announcements

Section titled Read the Discord webhook settings for announcements

GET /api/v1/orgs/{org_slug}/staff/marketing/announcements

Whether a Discord webhook is saved for announcements, and its channel label.

Needs the Admin or Owner role. configured says whether a webhook address is saved, channel_label is the name your team gave the channel (null for none) and webhook_hint is the last four characters of the webhook's ID, so you can tell which webhook is saved. The address is a secret and is never answered.

Name In Type Required
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Save or remove the Discord webhook for announcements

Section titled Save or remove the Discord webhook for announcements

PUT /api/v1/orgs/{org_slug}/staff/marketing/announcements

Save the Discord webhook address and the channel label. Send only what changes.

Needs the Admin or Owner role. webhook_url must be an https address on Discord's own hosts that starts with https://discord.com/api/webhooks/, or 422 answers with detail and field. It is sealed and never shown again, and null or an empty string removes it. channel_label is at most 80 characters. The answer is the one GET gives. Saving what is already saved changes nothing and writes no audit entry. A change is recorded as announcements.updated with the settings that changed and never the address.

Name In Type Required
org_slug path string yes

application/json (required)

Field Type Required Description
webhook_url string or null no The Discord webhook address, which starts with https://discord.com/api/webhooks/. It is sealed and never shown again. Null or empty removes the saved one. Left out, the saved one stays.
channel_label string or null no A name for the channel, such as #announcements, shown to your team. At most 80 characters. Null or empty removes it. Left out, the saved one stays.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Read the announcements that were posted

Section titled Read the announcements that were posted

GET /api/v1/orgs/{org_slug}/staff/marketing/announcements/history

The announcements posted or refused, newest first.

Needs the Admin or Owner role. Each entry has status (posted or failed), the title, content and link that were sent, the channel_label then saved, error (why a failed post failed, never what Discord said), actor_type (staff, user or admin for platform staff), actor ({id, name}, null when it is unknown) and created_at. The webhook address is never in an entry.

Name In Type Required Description
org_slug path string yes
limit query integer no Announcements to return, newest first, 1 to 100. Left out, 20. Default: 20.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Post an announcement to Discord

Section titled Post an announcement to Discord

POST /api/v1/orgs/{org_slug}/staff/marketing/announcements/post

Post one message to the saved Discord webhook.

Needs the Admin or Owner role. content is the message, 1 to 1,800 characters. title (at most 120 characters) becomes a bold first line, and link (an https address) goes after the message. The title, text and link together fit Discord's 2,000 characters, or 422 answers. Nothing in the message can mention a role or a person. The answer is {posted: true}. 409 means no webhook is saved. 502 means Discord did not take the message, with detail saying so in a sentence, and nothing was posted. At most 10 messages an hour for the organization, and the 11th answers 429. Every attempt is recorded in the audit log as announcement.posted or announcement.failed with the words and the channel label, never the address.

Name In Type Required
org_slug path string yes

application/json (required)

Field Type Required Description
content string or null no The message, 1 to 1,800 characters. Discord's own formatting works in it. Nothing in it can mention a role or a person.
title string or null no A bold first line, at most 120 characters.
link string or null no A link added after the message. It starts with https://, at most 500 characters.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

GET /api/v1/orgs/{org_slug}/staff/marketing/campaigns

The organization's saved campaign links, newest first.

Needs the Billing, Admin or Owner role. A campaign is a landing page with the UTM words that tag it and an optional coupon. Every campaign has all its fields, archived (true once it was archived) and url, the full link to copy: the storefront address, base_path, the UTM words in the order utm_source, utm_medium, utm_campaign, utm_term, utm_content, then coupon. The words are percent encoded. An organization with no storefront address gets the path and query alone. count is how many campaigns match before limit and offset apply, and max_campaigns is the most an organization keeps.

Name In Type Required Description
org_slug path string yes
status query string no all (the default), active or archived. Default: all.
q query string or null no Only campaigns whose name or campaign word holds this text, ignoring capitals.
limit query integer no Campaigns to return, 1 to 200. Left out, 100. Default: 100.
offset query integer no Campaigns to skip, for the next page. Default: 0.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

POST /api/v1/orgs/{org_slug}/staff/marketing/campaigns

Save a campaign link and answer it, with its url.

Needs the Billing, Admin or Owner role. name, utm_source, utm_medium and utm_campaign are required. A bad value answers 422 with detail, the sentence to show, and field, the input it belongs to. A name another campaign already has, in any capitals, answers 409 with field name. An organization keeps at most 500 campaigns, and the 501st answers 409. A coupon_code must be a coupon of this organization. The change is recorded in the audit log as campaign.created.

Name In Type Required
org_slug path string yes

application/json (required)

Field Type Required Description
name string or null no What you call the campaign, at most 120 characters. Each campaign in an organization has its own name, and two names that differ only in capitals count as one.
base_path string or null no The page the link opens: a path on your storefront that starts with /, at most 400 characters, such as /pricing. It holds no host, scheme, fragment, backslash, space or control character, and at most one ?. A query in it is kept and the UTM words go after it. Left out when you create a campaign, it is /.
utm_source string or null no Where the visit comes from, such as newsletter. At most 80 characters, with no &, =, #, ? or control character.
utm_medium string or null no How the link is delivered, such as email. At most 80 characters, with the same limits as the source.
utm_campaign string or null no The word the reports group by, at most 120 characters, with the same limits as the source. A visit or order whose campaign is this word belongs to the campaign, whatever its capitals.
utm_term string or null no The keyword or audience, at most 120 characters. Empty or null for none.
utm_content string or null no Tells two links of one campaign apart, at most 120 characters. Empty or null for none.
coupon_code string or null no A coupon of this organization that the link applies, as ?coupon=. It must exist. Empty or null for none.
notes string or null no A note for your team, at most 500 characters. Empty or null for none.
Status Meaning
201 Success.
422 The request is not valid. detail lists each problem.

Check a campaign link and build its address without saving it

Section titled Check a campaign link and build its address without saving it

POST /api/v1/orgs/{org_slug}/staff/marketing/campaigns/preview

Build the link for the fields sent, and list what is wrong with them. Saves nothing.

Needs the Billing, Admin or Owner role. Send the same body as a save; name may be left out. The answer is {url, problems}. problems is a list of {field, detail} with every problem found, and url is null while there is one. The check is the one a save makes, a repeated name and an unknown coupon included.

Name In Type Required
org_slug path string yes

application/json (required)

Field Type Required Description
name string or null no What you call the campaign, at most 120 characters. Each campaign in an organization has its own name, and two names that differ only in capitals count as one.
base_path string or null no The page the link opens: a path on your storefront that starts with /, at most 400 characters, such as /pricing. It holds no host, scheme, fragment, backslash, space or control character, and at most one ?. A query in it is kept and the UTM words go after it. Left out when you create a campaign, it is /.
utm_source string or null no Where the visit comes from, such as newsletter. At most 80 characters, with no &, =, #, ? or control character.
utm_medium string or null no How the link is delivered, such as email. At most 80 characters, with the same limits as the source.
utm_campaign string or null no The word the reports group by, at most 120 characters, with the same limits as the source. A visit or order whose campaign is this word belongs to the campaign, whatever its capitals.
utm_term string or null no The keyword or audience, at most 120 characters. Empty or null for none.
utm_content string or null no Tells two links of one campaign apart, at most 120 characters. Empty or null for none.
coupon_code string or null no A coupon of this organization that the link applies, as ?coupon=. It must exist. Empty or null for none.
notes string or null no A note for your team, at most 500 characters. Empty or null for none.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Read what each campaign brought in

Section titled Read what each campaign brought in

GET /api/v1/orgs/{org_slug}/staff/marketing/campaigns/results

What every saved campaign brought in over a period, and the campaign words no saved campaign names.

Needs the Billing, Admin or Owner role. The period is from to to in the brand's time zone, the last 30 days when left out, and at most 366 days. A campaign owns the visits, sign-ups and orders whose utm_campaign is its own, ignoring capitals. The figures are the acquisition report's: a visit is a stored session with bots left out, a sign-up is a customer whose last touch named the campaign, an order is a paid order that is not free, and revenue_minor is the invoice total without tax in currency's minor units. Orders and revenue are counted in one currency and never added across currencies: currencies names every currency with an order in the period. conversion_rate_bp is orders over visits in basis points, so 123 is 1.23 percent. visits_complete is false when the period starts more than 180 days ago, because sessions are kept for 180 days. unmatched lists the campaign words of the period that no saved campaign names, the biggest first, at most limit.

Name In Type Required Description
org_slug path string yes
from query string (date) or null no First day of the period, YYYY-MM-DD, in the brand's time zone. Left out, 29 days before the last day, so the period is the last 30 days. A period is at most 366 days.
to query string (date) or null no Last day of the period, YYYY-MM-DD, in the brand's time zone. Left out, today.
currency query string or null no A three letter currency code. Orders and revenue are counted in this one currency and never added across currencies. Left out, the currency with the most revenue in the period, else the brand's own.
limit query integer no Campaign words in unmatched, 1 to 200. Left out, 20. The saved campaigns are always all listed. Default: 20.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Change or archive a campaign link

Section titled Change or archive a campaign link

PATCH /api/v1/orgs/{org_slug}/staff/marketing/campaigns/{campaign_id}

Change the fields of a campaign that were sent, or archive it with archived, and answer it.

Needs the Billing, Admin or Owner role. Only the fields sent are checked and changed, by the rules of a save. A null or empty utm_term, utm_content, coupon_code or notes clears it. Saving what is already there changes nothing and writes no audit entry. A change is recorded as campaign.updated with the names of the fields that changed. A campaign of another organization answers 404.

Name In Type Required
campaign_id path integer yes
org_slug path string yes

application/json (required)

Field Type Required Description
name string or null no What you call the campaign, at most 120 characters. Each campaign in an organization has its own name, and two names that differ only in capitals count as one.
base_path string or null no The page the link opens: a path on your storefront that starts with /, at most 400 characters, such as /pricing. It holds no host, scheme, fragment, backslash, space or control character, and at most one ?. A query in it is kept and the UTM words go after it. Left out when you create a campaign, it is /.
utm_source string or null no Where the visit comes from, such as newsletter. At most 80 characters, with no &, =, #, ? or control character.
utm_medium string or null no How the link is delivered, such as email. At most 80 characters, with the same limits as the source.
utm_campaign string or null no The word the reports group by, at most 120 characters, with the same limits as the source. A visit or order whose campaign is this word belongs to the campaign, whatever its capitals.
utm_term string or null no The keyword or audience, at most 120 characters. Empty or null for none.
utm_content string or null no Tells two links of one campaign apart, at most 120 characters. Empty or null for none.
coupon_code string or null no A coupon of this organization that the link applies, as ?coupon=. It must exist. Empty or null for none.
notes string or null no A note for your team, at most 500 characters. Empty or null for none.
archived boolean or null no true archives the campaign and false brings it back. An archived campaign keeps its link and its results.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

DELETE /api/v1/orgs/{org_slug}/staff/marketing/campaigns/{campaign_id}

Delete a campaign link. The visits and orders that carried its words stay in the reports.

Needs the Billing, Admin or Owner role. Archive a campaign instead to keep its link and its results in the list. A campaign of another organization answers 404. Recorded as campaign.deleted.

Name In Type Required
campaign_id path integer yes
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Read what one campaign brought in

Section titled Read what one campaign brought in

GET /api/v1/orgs/{org_slug}/staff/marketing/campaigns/{campaign_id}/results

What one campaign brought in over a period and over the period before it.

Needs the Billing, Admin or Owner role. The figures and their definitions are those of GET results. totals holds visits, signups, orders, new_customers, revenue_minor and conversion_rate_bp, and totals.previous holds the same for the comparison period, or null when compare is none. A campaign of another organization answers 404.

Name In Type Required Description
campaign_id path integer yes
org_slug path string yes
from query string (date) or null no First day of the period, YYYY-MM-DD, in the brand's time zone. Left out, 29 days before the last day, so the period is the last 30 days. A period is at most 366 days.
to query string (date) or null no Last day of the period, YYYY-MM-DD, in the brand's time zone. Left out, today.
compare query string or null no previous (the default) sets every total against the same number of days just before the period, and a calendar month against the month before it. none leaves the comparison out. Default: previous.
currency query string or null no A three letter currency code. Orders and revenue are counted in this one currency and never added across currencies. Left out, the currency with the most revenue in the period, else the brand's own.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

List the ad platforms purchases are sent to, and how each is doing

Section titled List the ad platforms purchases are sent to, and how each is doing

GET /api/v1/orgs/{org_slug}/staff/marketing/conversions

Every ad platform the organization can send purchases to, with its settings and how it is doing.

Needs the Admin or Owner role. There is one entry for each of ga4, google_ads, meta_capi, tiktok_events, microsoft_ads, reddit_ads and x_ads, whether or not it was ever set up. An entry has enabled, test_mode, config (the settings that are not secret), secret_set (whether a secret is saved; the secret is never answered), fields and secret (what a form for the kind asks), last_delivery (the newest event the kind was sent, with its status) and coverage: orders is how many first purchases were paid in the last 30 days, sent how many of them the kind was sent, and rate is sent over orders (null with no orders). Microsoft Ads has no secret. Its entry has feed_url_masked, the address of its file with the token hidden, and when Microsoft Advertising last fetched it.

Name In Type Required
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Read what each platform was sent, and why anything was not

Section titled Read what each platform was sent, and why anything was not

GET /api/v1/orgs/{org_slug}/staff/marketing/conversions/deliveries

What each platform was sent, newest first, and why anything was not.

Needs the Admin or Owner role. Every row is one event for one platform: event is purchase (a first purchase), renewal, upgrade, free_server, sign_up, refund or chargeback; status is sent, skipped (error says why: the buyer did not allow marketing, the platform has no such event, renewals are off) or failed (http_status and error hold the platform's answer, and a timeout or a server error is tried again, three attempts in all). invoice names the invoice the row belongs to. Filter by kind, status and invoice_number; count is the total that match.

Name In Type Required Description
org_slug path string yes
kind query string or null no ga4, google_ads, meta_capi, tiktok_events, microsoft_ads, reddit_ads or x_ads.
status query string or null no sent, failed or skipped.
invoice_number query string or null no Only the deliveries of this invoice, its refunds and its chargebacks.
limit query integer no Default: 50.
offset query integer no Default: 0.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Turn an ad platform on or off and change its settings

Section titled Turn an ad platform on or off and change its settings

PUT /api/v1/orgs/{org_slug}/staff/marketing/conversions/{kind}

Turn a platform on or off, set its test mode, change its settings, set or clear its secret.

Needs the Admin or Owner role. Send only what changes. config keys replace the saved ones and a null or empty string removes one; labels (Google Ads) and events (X) replace the whole map. secret is write only: it is sealed, never answered and never written to the audit log, and an empty string clears it. X takes an object of consumer_key, consumer_secret, access_token and access_token_secret. Google Ads and Microsoft Ads take no secret, and a secret for them answers 422. A value that does not fit, or a platform turned on without what it needs, answers 422 with detail, the sentence to show, and field, the input it belongs to. Every ID is checked as the analytics and ad tags check theirs.

Turning Microsoft Ads on the first time makes the address of its file, and only that answer carries the whole address in feed_url. Copy it into a schedule in Microsoft Advertising. Later answers show it with the token hidden. The answer is {integration, changed, feed_url}. Each change is recorded in the audit log without any secret.

Name In Type Required Description
kind path string yes ga4, google_ads, meta_capi, tiktok_events, microsoft_ads, reddit_ads or x_ads.
org_slug path string yes

application/json (required)

Field Type Required Description
enabled boolean or null no Turn the integration on or off. It needs its settings and secret first (422 names the first one missing).
test_mode boolean or null no Send every event as a test: Meta and TikTok with the test event code, Google Analytics to its validation endpoint, Reddit with its test flag. Google Ads and X have no test mode.
config object or null no Settings to change. A key replaces the stored one and null removes it. labels and events replace the whole map.
secret string or object or null no The platform's secret. Write only: it is sealed and never answered, only secret_set. An empty string clears it. X takes an object of its four OAuth values.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Replace the token in the Microsoft Ads file address

Section titled Replace the token in the Microsoft Ads file address

POST /api/v1/orgs/{org_slug}/staff/marketing/conversions/{kind}/rotate-feed-token

Replace the token in the Microsoft Ads file address, so the old address stops working.

Needs the Admin or Owner role. The answer is {integration, feed_url} and the only one that shows the new address whole. Put it in the schedule in Microsoft Advertising; from now on the old address answers 404. Purchases the file already listed stay listed. Answers 409 before Microsoft Ads was first turned on, since that makes the first address.

Name In Type Required Description
kind path string yes microsoft_ads, the one platform that fetches a file from Coritan.
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Send a made-up purchase to an ad platform in test mode

Section titled Send a made-up purchase to an ad platform in test mode

POST /api/v1/orgs/{org_slug}/staff/marketing/conversions/{kind}/test

Send one made-up purchase to a platform in test mode and answer what the platform said.

Needs the Admin or Owner role. The event is for one currency unit of a product called "Test product" and carries nothing about a person. Meta and TikTok send their test event code, Google Analytics its validation endpoint and Reddit its test flag, so nothing reaches live reporting. The platform needs its settings and secret saved first (422 names the missing one). Google Ads and X have no test mode, so a test would count as a real sale and answers 422, and Microsoft Ads fetches its file and takes no events. At most ten test events an hour for each platform (429). The test is not logged as a delivery and is not counted in coverage. The answer is {kind, event, status, ok, http_status, error, event_id}.

Name In Type Required Description
kind path string yes ga4, google_ads, meta_capi, tiktok_events, microsoft_ads, reddit_ads or x_ads.
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

List the automatic email flows, with their settings and how many emails each sent

Section titled List the automatic email flows, with their settings and how many emails each sent

GET /api/v1/orgs/{org_slug}/staff/marketing/flows

Every automatic email flow of the organization, whether or not it was ever turned on.

Needs the Admin or Owner role. There is one entry for each of unpaid_invoice, stuck_setup, free_upgrade, winback, onboarding and review_invite. An entry has its label, kind (service flows are about the customer's own order and need no marketing consent, marketing flows go only to customers who agreed to marketing email) and description; enabled and config, the saved settings with the defaults filled in; fields, what a form for the settings asks (key, label, kind, default, min, max, hint); template_slugs, one for each step; blocked, the sentence that says why the flow cannot send even when on (the review invitation needs a saved Trustpilot review link), or null; and stats, how many emails are scheduled, sent, skipped, failed or canceled and last_sent_at. Every flow is off until turned on. One customer gets at most one flow email in 3 days, from any flow.

Name In Type Required
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Read the log of flow emails, newest first

Section titled Read the log of flow emails, newest first

GET /api/v1/orgs/{org_slug}/staff/marketing/flows/messages

Every email a flow scheduled, newest first, with what became of it.

Needs the Admin or Owner role. A row has flow, step, status, email, scheduled_at, sent_at, customer_id and error. scheduled waits for the next pass (at most ten minutes), sent went to the mail server, skipped was left out on purpose (error says why: the address unsubscribed, the account is not active, another flow email went to the customer in the last 3 days, or it was due more than a day ago), canceled lost its reason before it went (the invoice was paid, the server is running, the customer withdrew consent, the flow was turned off) and failed was refused by the mail server. count is the total that match, before limit and offset.

Name In Type Required Description
org_slug path string yes
flow query string or null no Only this flow: unpaid_invoice, stuck_setup, free_upgrade, winback, onboarding or review_invite.
status query string or null no Only this status: scheduled, sent, skipped, failed or canceled.
limit query integer no How many rows to answer, 1 to 200. Default: 50.
offset query integer no How many rows to skip. Default: 0.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Turn an email flow on or off and change its settings

Section titled Turn an email flow on or off and change its settings

PUT /api/v1/orgs/{org_slug}/staff/marketing/flows/{key}

Turn a flow on or off and change its settings. Send only what changes.

Needs the Admin or Owner role. config keys replace the saved ones; GET lists them in fields with their ranges. coupon_code (win-back) takes a coupon of the organization, or null to remove it. A value that does not fit answers 422 with detail, the sentence to show, and field, the input it belongs to (config.after_days, or enabled for the review invitation without a saved Trustpilot review link), and changes nothing. The answer is {flow, changed}: the flow as GET lists it and the names that differ. Saving what is already saved changes nothing and writes no audit entry. A change is audited as flows.updated with the settings before and after. A flow starts mailing at its next pass, within ten minutes, and only customers who qualify from then on.

Name In Type Required Description
key path string yes The flow: unpaid_invoice, stuck_setup, free_upgrade, winback, onboarding or review_invite.
org_slug path string yes

application/json (required)

Field Type Required Description
enabled boolean or null no Turn the flow on or off. The review invitation can only be turned on once a Trustpilot review link is saved and on (422 otherwise).
config object or null no The flow's settings to change, by name, as GET lists them in fields. A value outside its range answers 422 and changes nothing.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Send a flow's sample email to yourself

Section titled Send a flow's sample email to yourself

POST /api/v1/orgs/{org_slug}/staff/marketing/flows/{key}/test

Send the flow's email, filled with made-up facts, to the address of the signed-in member.

Needs the Admin or Owner role. The test goes out whether or not the flow is on, as service mail, with the brand's own links and the flow's coupon code, and writes nothing to the flow log. An address on the organization's unsubscribe list gets nothing (409). step picks the email of a flow with two (422 for a step the flow lacks). The member needs an address on their account (400). At most ten test emails an hour for one member (429). The answer is {sent, to, flow, step, template}; 502 when the mail server did not accept it. Audited as flows.test_sent.

Name In Type Required Description
key path string yes The flow: unpaid_invoice, stuck_setup, free_upgrade, winback, onboarding or review_invite.
org_slug path string yes

application/json

Field Type Required Description
step string or null no Which email of the flow to send, 1 or 2. The default is 1. Only unpaid_invoice and onboarding have a second step.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

List the organization's referrals and what the program has paid

Section titled List the organization's referrals and what the program has paid

GET /api/v1/orgs/{org_slug}/staff/marketing/referrals

Every referral of the organization, newest first, and the program's totals.

Needs the Admin or Owner role. A referral is one referred customer: their first paid invoice started it. status is qualified while it waits out its hold (hold_until), credited once the wallet credit is paid, and void when a rule refused it (void_reason says which, or holds the reason staff gave). referrer and referee name the two customers, code the code that was used and invoice the invoice that started it. reward_amount is what the referrer is paid and referee_reward_amount the welcome credit, both in wallet dollars (currency). count is how many referrals match the filters. totals covers the whole program and ignores the filters: the number of referrals in each status, credited_amount paid out so far and owed_amount for the open ones.

Name In Type Required Description
org_slug path string yes
status query string or null no pending, qualified, credited or void.
q query string or null no Part of either customer's email address, without regard to capitals.
limit query integer no Referrals to return, newest first. At most 200. Default: 50.
offset query integer no Referrals to skip. Default: 0.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

List referral codes, customers' and partners'

Section titled List referral codes, customers' and partners'

GET /api/v1/orgs/{org_slug}/staff/marketing/referrals/codes

The organization's referral codes, newest first, each with how many referrals it started.

Needs the Admin or Owner role. A customer code is made for each customer the first time they open their referral page. A partner code is made by your team and pays commission_bp of the referred customer's first invoice. referrals on a code is {total, credited, earned}: the referrals it started, how many were paid, and what they paid the owner in wallet dollars.

Name In Type Required Description
org_slug path string yes
kind query string or null no customer or partner.
active query boolean or null no true for codes that work, false for stopped ones.
q query string or null no Part of the code, its label or the owner's email address.
limit query integer no Codes to return, newest first. At most 200. Default: 50.
offset query integer no Codes to skip. Default: 0.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Make a partner code for a customer

Section titled Make a partner code for a customer

POST /api/v1/orgs/{org_slug}/staff/marketing/referrals/codes

Make a partner code that pays a share of the first invoice of every customer it brings.

Needs the Admin or Owner role. Name the owner with customer_id or email: an active customer of this organization. commission_bp (1 to 5000, 100 is 1 percent) is the share of the referred customer's first invoice, without tax, paid into the owner's wallet once the hold has passed. code is optional: 3 to 40 letters, digits, hyphens or underscores, and without regard to capitals it must not be in use (409). Left out, we make an 8 character code. At most 30 codes an hour. Answers 422 with detail and field for a value that does not fit. The code is recorded in the audit log as referral_code.created.

Name In Type Required
org_slug path string yes

application/json (required)

Field Type Required Description
customer_id boolean or integer or string or null no The customer who owns the code. Give this or email.
email string or null no The email address of the customer who owns the code. Give this or customer_id.
code string or null no The code, 3 to 40 letters, digits, hyphens or underscores. Left out, we make an 8 character one.
commission_bp boolean or integer or string or null no The share of the referred customer's first invoice, without tax, the owner is paid, in basis points: 1 to 5000 (100 is 1 percent).
label string or null no A note for your team, such as the partner's name.
Status Meaning
201 Success.
422 The request is not valid. detail lists each problem.

Stop or restart a code, or change a partner's commission or label

Section titled Stop or restart a code, or change a partner's commission or label

PATCH /api/v1/orgs/{org_slug}/staff/marketing/referrals/codes/{code_id}

Change whether a code works, a partner code's commission, or its label. The code itself never changes.

Needs the Admin or Owner role. active: false stops the code from starting new referrals; referrals it already started still pay. commission_bp (1 to 5000) is for a partner code only: a customer's code pays the program's reward amount. label is a note for your team, and null or an empty string removes it. Send only what changes. Answers 404 for a code of another organization and 422 with detail and field for a value that does not fit. A change is recorded as referral_code.updated with the values before and after.

Name In Type Required Description
code_id path integer yes The code's id.
org_slug path string yes

application/json (required)

Field Type Required Description
active boolean or null no false stops the code from starting new referrals. Referrals it already has still pay.
commission_bp boolean or integer or string or null no A partner code's share in basis points: 1 to 5000.
label string or null no A note for your team. null or an empty string removes it.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Void a referral that has not been paid

Section titled Void a referral that has not been paid

POST /api/v1/orgs/{org_slug}/staff/marketing/referrals/{referral_id}/void

Void a referral so it is never paid. Only a pending or qualified referral can be voided.

Needs the Admin or Owner role. reason is required, 1 to 120 characters, and is kept as the referral's void_reason. A referral that is already credited or void answers 409, and money already paid is not taken back. Answers 404 for a referral of another organization. At most 60 an hour. Recorded in the audit log as referral.voided with the reason.

Name In Type Required Description
referral_id path integer yes The referral's id.
org_slug path string yes

application/json (required)

Field Type Required Description
reason string or null no Why the referral is void, 1 to 120 characters. It is kept with the referral.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Read the Trustpilot review settings and how the invitations are doing

Section titled Read the Trustpilot review settings and how the invitations are doing

GET /api/v1/orgs/{org_slug}/staff/marketing/reviews

The Trustpilot review settings, and how the review invitation emails are doing.

Needs the Admin or Owner role. enabled is whether the storefront asks signed-in customers for a review, review_url the Trustpilot link it opens (null for none), min_account_age_days how old an account is before it asks, and dismiss_days how long it stays quiet after a customer closes the prompt. The invitation is the email flow review_invite, which uses the same link. invitations holds enabled (the flow's own switch), the number of its messages scheduled, sent, skipped and failed (all 0 until the flow has run) and last_sent_at.

Name In Type Required
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Change the Trustpilot review settings

Section titled Change the Trustpilot review settings

PUT /api/v1/orgs/{org_slug}/staff/marketing/reviews

Change the review settings. Send only what changes.

Needs the Admin or Owner role. review_url must start with https:// and be on trustpilot.com, at most 500 characters, and the prompt cannot be turned on without one. min_account_age_days is 0 to 365 and dismiss_days 1 to 365. A value that does not fit answers 422 with detail, the sentence to show, and field, the setting it belongs to. The answer is the one GET gives, with changed listing the settings that differ from before. Saving what is already saved changes nothing and writes no audit entry. A change is recorded as reviews.updated, and the storefront applies it to new page loads within a minute.

Name In Type Required
org_slug path string yes

application/json (required)

Field Type Required Description
enabled boolean or null no Turn the review prompt on or off. It needs review_url, and an on switch with no link answers 422.
review_url string or null no Your Trustpilot review link. It starts with https:// and is on trustpilot.com, at most 500 characters. Null or empty removes it.
min_account_age_days integer or null no How many days old an account is before the prompt asks, 0 to 365. The default is 1.
dismiss_days integer or null no How many days the prompt stays quiet after a customer closes it, 1 to 365. The default is 30.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

List the newsletter's leads and count who can be mailed

Section titled List the newsletter's leads and count who can be mailed

GET /api/v1/orgs/{org_slug}/staff/marketing/subscribers

The addresses visitors gave the storefront's newsletter form, newest first.

Needs the Admin or Owner role. Every row is one address: id, email, source (where it was collected), consent (whether the visitor agreed to email), consent_text (the words they agreed to), customer_id (the customer with that address, if there is one), suppressed (true when the address is on the suppression list and gets no marketing email whatever its consent says) and created_at. Filter by part of the address with q, by source and by consent; total is every lead the filters match. counts covers the whole organization: leads (every lead), consenting_customers (active customers who agreed to marketing email) and suppressed (addresses on the suppression list).

Name In Type Required Description
org_slug path string yes
q query string or null no Part of the address.
source query string or null no Only leads that came from this source.
consent query boolean or null no true for leads who agreed to email, false for the rest.
limit query integer no Default: 50.
offset query integer no Default: 0.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Download the addresses that can be mailed as a CSV file

Section titled Download the addresses that can be mailed as a CSV file

GET /api/v1/orgs/{org_slug}/staff/marketing/subscribers/export.csv

Every address the organization may send marketing email to, as a CSV file.

Needs the Admin or Owner role. The columns are email, source, consent, kind (lead or customer) and created_at. The file lists leads who agreed to email and active customers who agreed to marketing email, once for each address (an address that is both is a lead). It never lists an address on the suppression list. A cell that starts with =, +, - or @ begins with an apostrophe so a spreadsheet does not run it. A file holds at most 100,000 rows and the answer's X-Export-Truncated: true header says when a list was longer. At most 12 exports an hour (429). Every export is audited as subscribers.exported before the file is answered.

Name In Type Required
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

List the addresses that get no marketing email

Section titled List the addresses that get no marketing email

GET /api/v1/orgs/{org_slug}/staff/marketing/subscribers/suppressions

The organization's suppression list, newest first.

Needs the Admin or Owner role. An address on the list gets no marketing email, whatever its owner's consent says. Every row has id, email, reason (unsubscribed, bounced, complained or manual), source (link, account, console or api) and created_at. Filter by part of the address with q; total is every row that matches. The list belongs to this organization alone: an address another brand suppressed is not here.

Name In Type Required Description
org_slug path string yes
q query string or null no Part of the address.
limit query integer no Default: 50.
offset query integer no Default: 0.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Add an address to the suppression list

Section titled Add an address to the suppression list

POST /api/v1/orgs/{org_slug}/staff/marketing/subscribers/suppressions

Stop marketing email to one address.

Needs the Admin or Owner role. reason must be manual (the other reasons are set by an unsubscribe, a bounce or a complaint). The row's source is console. Adding an address cancels the flow emails still waiting for it, takes marketing consent back from a customer with that address and marks a lead with it as not consenting. An address already on the list stays as it was and the answer has added: false. A bad address or reason answers 422 {"detail", "field"}. The answer is {suppression, added} and a new entry is audited as suppression.added.

Name In Type Required
org_slug path string yes

application/json (required)

Field Type Required Description
email string yes The address that gets no marketing email.
reason string no Why it is on the list. A person adds an address with the reason "manual".
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Take an address off the suppression list

Section titled Take an address off the suppression list

DELETE /api/v1/orgs/{org_slug}/staff/marketing/subscribers/suppressions/{suppression_id}

Let marketing email reach an address again.

Needs the Admin or Owner role. This removes the row only: it does not give anyone's consent back, so a customer or lead who withdrew still has to agree again before they get marketing email. 404 for an id that is not on this organization's list. Audited as suppression.lifted.

Name In Type Required Description
suppression_id path integer yes The id of a row of the suppression list.
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

DELETE /api/v1/orgs/{org_slug}/staff/marketing/subscribers/{lead_id}

Delete one lead for good.

Needs the Admin or Owner role. Only the lead row goes: the customer with that address, their consent and the suppression list are not touched, so an address that unsubscribed stays unsubscribed. 404 for an id that is not this organization's lead. Audited as subscriber.deleted with the lead's id and source, never its address.

Name In Type Required Description
lead_id path integer yes The id of a lead.
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

The tags the storefront loads, and what an editor needs to draw them

Section titled The tags the storefront loads, and what an editor needs to draw them

GET /api/v1/orgs/{org_slug}/staff/marketing/tags

The tags the storefront loads, and what an editor needs to draw them.

Needs the Admin or Owner role. tags holds the platforms that are on, each with the public ids saved for it; a platform with no id is off and absent. kinds lists every platform with its label, a sentence about it and its fields (key, label, hint, pattern, example), so a form can be drawn from it. consent says whether the storefront shows its cookie banner and which page the banner links to. legacy_google_analytics is true while the Google Analytics ID shown still comes from the older single setting, which the next save replaces.

Name In Type Required
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Replace the tags the storefront loads with the ones sent

Section titled Replace the tags the storefront loads with the ones sent

PUT /api/v1/orgs/{org_slug}/staff/marketing/tags

Replace the tags the storefront loads with the ones sent.

Needs the Admin or Owner role. tags is the whole object: a platform left out is turned off. Each id is trimmed and checked against the shape its platform uses, and a platform with no id is left out. The answer is the one GET gives, with changed listing the platforms that differ from before. A bad id answers 422 with detail, the sentence to show, and field, the input it belongs to (meta.pixel_id). Saving what is already stored changes nothing. Every change is recorded in the audit log with the ids before and after. Tags apply to new page loads within a minute.

Name In Type Required
org_slug path string yes

application/json (required)

Field Type Required
tags Tags yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.