Skip to content

API reference Store reports and costs

API reference

Store reports and costs

The API operations about store reports and costs, each with its input, its output and an example.

The operations about store reports and costs. Each one is a POST with a JSON object as its body: Making a request has the rules they share.

Which ads earned sales #

POST /api/v1/store.attribution · Read

Spend and the orders it earned, by channel, campaign, ad set or ad (level), for a period: spend, ROAS, the platform's own ROAS, orders, revenue, CPA, NC-ROAS, new customer orders, impressions, clicks and more per row, with the comparison period. Get the siteId from sites.list first. A visit is matched to an ad by the utm_id of its ad click first, then by campaign, ad set and ad names. Rows come sorted by spend, then revenue. Amounts are whole minor units (cents) of one currency, named in labels.currency; spend in another currency is listed in otherCurrencySpend, costs from the cost settings in another currency in otherCurrencyCosts, and neither is added in. Every number names what it covers in its scope: orders_paid (Orders paid in the period, before refunds), credited (Orders credited by the chosen model), credited_estimated (Credited by the chosen model; view credit is an estimate from daily platform totals), platform_reported (As the ad platform reports it), spend_synced (Spend as synced or uploaded, in the account currency), cost_settings (From the cost settings and cost lines of this site), refunds_dated (Refunds dated in the period). Answers 402 workspace_locked while the workspace's dashboards are locked.

Needs a token with the Read permission. Answers 402 while the dashboards of the workspace are locked.

Input #

Field Type Required Description
siteId string required The site id, from sites.list.
range "today" | "yesterday" | "30m" | "12h" | "24h" | "week" | "7d" | "30d" | "60d" | "90d" | "mtd" | "ytd" | "12mo" | "all" | "custom" optional The period: today, yesterday, 30m, 12h, 24h, week, 7d, 30d, 60d, 90d, mtd, ytd, 12mo, all. Left out, the workspace default. For dates send from and to instead.
from string optional First day of a custom period, YYYY-MM-DD in the site's time zone, sent with to.
to string optional Last day of a custom period, inclusive, YYYY-MM-DD, sent with from.
compare "prev" | "week" | "month" | "quarter" | "year" | "custom" | "off" optional prev (the default), week, month, quarter, year, custom (with cfrom and cto) or off.
cfrom string optional First day of a custom comparison, YYYY-MM-DD.
cto string optional Last day of a custom comparison, inclusive, YYYY-MM-DD.
currency string optional The currency to report, ISO 4217 such as USD. Left out, the one with the most orders.
model "last_click" | "last_click_views" | "clicks_views" | "last_touch" | "first_touch" | "linear" optional The attribution model: last_click (the default), last_click_views, clicks_views, last_touch, first_touch or linear. The two view models also credit orders no click explains from the platforms' daily purchases after a view, an estimate.
level "channel" | "campaign" | "adset" | "ad" optional The level of the rows: channel (the default), campaign, adset or ad.
search string, 1 to 100 characters optional Keep the rows whose name contains this text, ignoring case. 1 to 100 characters.

Output #

Field Type Present Description
serverNow number always The clock the period was resolved with: the start of the next whole minute, milliseconds since 1970 UTC.
serverTime number always When the answer was built, milliseconds since 1970 UTC.
window object always The period the numbers cover: from and to in milliseconds since 1970 UTC (to is exclusive), the time zone, a label and the bucket size.
compare object | null always The comparison period in the same form, or null when there is none.
rawFrom number | null always The earliest time detailed data is kept from, or null when nothing was trimmed.
truncated boolean always True when a filtered answer could only cover the part of the period that still has detailed data.
labels object always What the report covers: the period and the comparison period as the dashboard names them, the currency of every amount (ISO 4217; amounts are whole minor units), the attribution model and the lookback in days.
level "channel" | "campaign" | "adset" | "ad" always The level the rows are at: channel, campaign, adset or ad.
rows array of object always One row per channel, campaign, ad set or ad, sorted by spend and then by revenue, highest first. key names the row, parent the key of the row above it, ids the platform's own ids. hasSpend false means traffic no spend row matched (an email flow), hasTraffic false means spend no visit matched. metrics are the numbers of the period, compare those of the comparison period or null. spendMinor, impressions, clicks, ctr (clicks over impressions), cpcMinor and cpmMinor come from the ad platform, null where there is no spend. orders and revenueMinor are credited by the model, newOrders and newRevenueMinor the part from first orders of new customers; under linear a row holds its share of each order, so orders can be a fraction. roas is revenueMinor over spendMinor, ncRoas newRevenueMinor over spendMinor, cpaMinor spend per order and costPerNewCustomerMinor spend per new customer order; platformConversions, platformRevenueMinor and platformRoas are what the platform itself reports, viewConversions its purchases after a view. estimated is true when some credit came from a view model, which spreads daily platform view totals over orders.
totals object always Credit to the ad platforms and every spend row: roas is the blended ROAS, cpaMinor, ncRoas and costPerNewCustomerMinor match the Store tiles; mer, storeRevenueMinor and storeOrders cover every order in the period, credited or not.
unmatched object always Spend at this level that matched no visit: its amount in minor units and the number of rows it came from.
otherCurrencySpend array of object always Spend in a currency other than the report's: listed here by currency, in minor units of that currency, and never added into any number of this answer.
availableColumns array of string always The column keys that have a value in at least one row at this level, such as spend, roas or platform_roas.

Example #

curl -s -X POST https://clearsaga.com/api/v1/store.attribution \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456"}'

Run clearsaga help store attribution for one flag per field.

Store costs #

POST /api/v1/store.costs · Read

The costs the Profit report is computed with: the cost rules (shipping per order, payment fees, a default product cost), the unit cost of each product and the other cost lines. Get the siteId from sites.list first. Every cost is in one currency, named in currency. It still answers while the workspace's dashboards are locked.

Needs a token with the Read permission. Keeps answering while the dashboards of the workspace are locked.

Input #

Field Type Required Description
siteId string required The site id, from sites.list.

Output #

Field Type Present Description
settings object always The cost rules: currency (the currency of every cost of the site, null until the first cost is saved), shippingPerOrderMinor (what shipping one order costs the store), paymentFeeBps and paymentFeeFixedMinor (the payment fee of an order: basis points of its amount, 290 is 2.9%, plus a fixed amount) and defaultCogsBps (the product cost of a line whose product has none, in basis points of its price).
products array of object always Each product cost: its id, the store it sells through (provider), the product id there and its name, the unit cost in minor units of currency, where it came from (form, csv or seed) and when it last changed (milliseconds since 1970 UTC).
lines array of object always The other costs of the site: id, label, kind, amount, currency, startsOn, endsOn and updatedAt, as store.createCostLine answers them.
currency string always The currency of every cost: the one pinned by the first cost write, or the currency of the site's orders before that.

Example #

curl -s -X POST https://clearsaga.com/api/v1/store.costs \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456"}'

Run clearsaga help store costs for one flag per field.

Add a cost line #

POST /api/v1/store.createCostLine · Write

Adds a cost the store carries besides product cost, shipping, fees and ad spend: rent and software per month, a photoshoot once, or returns handling as a share of revenue. Get the siteId from sites.list first. A site holds at most 100 cost lines. Each call adds a line, so sending it twice adds two. Profit changes for every period the line covers.

Needs a token with the Write permission.

Input #

Field Type Required Description
siteId string required The site id, from sites.list.
label string, 1 to 80 characters required What the cost is, 1 to 80 characters: Rent, Shopify plan, Returns handling.
kind "monthly" | "one_off" | "percent_of_revenue" required monthly: an amount per month, spread over the days it covers. one_off: an amount once, on startsOn. percent_of_revenue: a share of the revenue of the days it covers.
amount integer, 0 to 1000000000 required Minor units of the site's cost currency for monthly and one_off; basis points for percent_of_revenue (150 is 1.5%, at most 10000).
startsOn string required The first day the cost counts, YYYY-MM-DD; the day of a one_off cost.
endsOn string | null required The last day it counts, inclusive, YYYY-MM-DD, or null for no end. Must be null for one_off and may not be before startsOn.

Output #

Field Type Present Description
id string always The cost line id.
label string always What the cost is, as the dashboard shows it.
kind "monthly" | "one_off" | "percent_of_revenue" always monthly: a cost per month, spread over its days. one_off: once, on startsOn. percent_of_revenue: a share of the revenue of the days it covers.
amount number always Minor units for monthly and one_off; basis points (1 is 0.01%) for percent_of_revenue.
currency string always The currency of the amount: the site's cost currency.
startsOn string always The first day it counts, YYYY-MM-DD; the day of a one_off cost.
endsOn string | null always The last day it counts, inclusive, or null when it has no end. Always null for one_off.
updatedAt number always When it last changed, milliseconds since 1970 UTC.

Example #

curl -s -X POST https://clearsaga.com/api/v1/store.createCostLine \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456","label":"example","kind":"monthly","amount":0,"startsOn":"2026-10-01","endsOn":"2026-10-01"}'

Run clearsaga help store createCostLine for one flag per field.

Creative report #

POST /api/v1/store.creatives · Read

Every ad the platforms report for a site, with its thumbnail, format, status, ad set and campaign, and its spend, credited orders and revenue, ROAS, CTR and the platform's own numbers for a period. Get the siteId from sites.list first. Spend uploaded as a CSV has no ads, so it is not here. Amounts are whole minor units (cents) of one currency, named in labels.currency; spend in another currency is listed in otherCurrencySpend, costs from the cost settings in another currency in otherCurrencyCosts, and neither is added in. Every number names what it covers in its scope: orders_paid (Orders paid in the period, before refunds), credited (Orders credited by the chosen model), credited_estimated (Credited by the chosen model; view credit is an estimate from daily platform totals), platform_reported (As the ad platform reports it), spend_synced (Spend as synced or uploaded, in the account currency), cost_settings (From the cost settings and cost lines of this site), refunds_dated (Refunds dated in the period). Answers 402 workspace_locked while the workspace's dashboards are locked.

Needs a token with the Read permission. Answers 402 while the dashboards of the workspace are locked.

Input #

Field Type Required Description
siteId string required The site id, from sites.list.
range "today" | "yesterday" | "30m" | "12h" | "24h" | "week" | "7d" | "30d" | "60d" | "90d" | "mtd" | "ytd" | "12mo" | "all" | "custom" optional The period: today, yesterday, 30m, 12h, 24h, week, 7d, 30d, 60d, 90d, mtd, ytd, 12mo, all. Left out, the workspace default. For dates send from and to instead.
from string optional First day of a custom period, YYYY-MM-DD in the site's time zone, sent with to.
to string optional Last day of a custom period, inclusive, YYYY-MM-DD, sent with from.
compare "prev" | "week" | "month" | "quarter" | "year" | "custom" | "off" optional prev (the default), week, month, quarter, year, custom (with cfrom and cto) or off.
cfrom string optional First day of a custom comparison, YYYY-MM-DD.
cto string optional Last day of a custom comparison, inclusive, YYYY-MM-DD.
currency string optional The currency to report, ISO 4217 such as USD. Left out, the one with the most orders.
model "last_click" | "last_click_views" | "clicks_views" | "last_touch" | "first_touch" | "linear" optional The attribution model: last_click (the default), last_click_views, clicks_views, last_touch, first_touch or linear. The two view models also credit orders no click explains from the platforms' daily purchases after a view, an estimate.
platform "meta" | "google_ads" | "tiktok" | "pinterest" | "amazon_ads" optional Only the ads of this platform: meta, google_ads, tiktok, pinterest or amazon_ads. Left out, every platform.
search string, 1 to 100 characters optional Keep the rows whose name contains this text, ignoring case. 1 to 100 characters.

Output #

Field Type Present Description
serverNow number always The clock the period was resolved with: the start of the next whole minute, milliseconds since 1970 UTC.
serverTime number always When the answer was built, milliseconds since 1970 UTC.
window object always The period the numbers cover: from and to in milliseconds since 1970 UTC (to is exclusive), the time zone, a label and the bucket size.
compare object | null always The comparison period in the same form, or null when there is none.
rawFrom number | null always The earliest time detailed data is kept from, or null when nothing was trimmed.
truncated boolean always True when a filtered answer could only cover the part of the period that still has detailed data.
labels object always What the report covers: the period and the comparison period as the dashboard names them, the currency of every amount (ISO 4217; amounts are whole minor units), the attribution model and the lookback in days.
rows array of object always One row per ad the platforms report: its ids, name, headline, format, status, thumbnail (an https address, or an inline SVG on the demo), ad set and campaign, when the platform last reported it (updatedAt), its numbers for the period and the comparison period, and spend per bucket (spark). spendMinor, impressions, clicks, ctr (clicks over impressions), cpcMinor and cpmMinor come from the ad platform, null where there is no spend. orders and revenueMinor are credited by the model, newOrders and newRevenueMinor the part from first orders of new customers; under linear a row holds its share of each order, so orders can be a fraction. roas is revenueMinor over spendMinor, ncRoas newRevenueMinor over spendMinor, cpaMinor spend per order and costPerNewCustomerMinor spend per new customer order; platformConversions, platformRevenueMinor and platformRoas are what the platform itself reports, viewConversions its purchases after a view. estimated is true when some credit came from a view model, which spreads daily platform view totals over orders.
totals object always The totals of every row.
platforms array of "meta" | "google_ads" | "tiktok" | "pinterest" | "amazon_ads" always The ad platforms that reported at least one ad.

Example #

curl -s -X POST https://clearsaga.com/api/v1/store.creatives \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456"}'

Run clearsaga help store creatives for one flag per field.

New customers #

POST /api/v1/store.customers · Read

New and returning customers of a period: their orders and revenue, the repeat rate and the days to a second order, weekly or monthly cohorts with how many came back, and lifetime value by the product and by the channel of the first order. Get the siteId from sites.list first. An order is new when it is its customer's first, by the customer key the store sends; without one it is unknown. The model decides the channel of a first order. Amounts are whole minor units of the currency in labels. Answers 402 workspace_locked while the workspace's dashboards are locked.

Needs a token with the Read permission. Answers 402 while the dashboards of the workspace are locked.

Input #

Field Type Required Description
siteId string required The site id, from sites.list.
range "today" | "yesterday" | "30m" | "12h" | "24h" | "week" | "7d" | "30d" | "60d" | "90d" | "mtd" | "ytd" | "12mo" | "all" | "custom" optional The period: today, yesterday, 30m, 12h, 24h, week, 7d, 30d, 60d, 90d, mtd, ytd, 12mo, all. Left out, the workspace default. For dates send from and to instead.
from string optional First day of a custom period, YYYY-MM-DD in the site's time zone, sent with to.
to string optional Last day of a custom period, inclusive, YYYY-MM-DD, sent with from.
compare "prev" | "week" | "month" | "quarter" | "year" | "custom" | "off" optional prev (the default), week, month, quarter, year, custom (with cfrom and cto) or off.
cfrom string optional First day of a custom comparison, YYYY-MM-DD.
cto string optional Last day of a custom comparison, inclusive, YYYY-MM-DD.
currency string optional The currency to report, ISO 4217 such as USD. Left out, the one with the most orders.
model "last_click" | "last_click_views" | "clicks_views" | "last_touch" | "first_touch" | "linear" optional The attribution model: last_click (the default), last_click_views, clicks_views, last_touch, first_touch or linear. The two view models also credit orders no click explains from the platforms' daily purchases after a view, an estimate.

Output #

Field Type Present Description
serverNow number always The clock the period was resolved with: the start of the next whole minute, milliseconds since 1970 UTC.
serverTime number always When the answer was built, milliseconds since 1970 UTC.
window object always The period the numbers cover: from and to in milliseconds since 1970 UTC (to is exclusive), the time zone, a label and the bucket size.
compare object | null always The comparison period in the same form, or null when there is none.
rawFrom number | null always The earliest time detailed data is kept from, or null when nothing was trimmed.
truncated boolean always True when a filtered answer could only cover the part of the period that still has detailed data.
labels object always What the report covers: the period and the comparison period as the dashboard names them, the currency of every amount (ISO 4217; amounts are whole minor units), the attribution model and the lookback in days.
split array of object always Orders of the period by customer: new (the customer's first order ever), returning, and unknown (the order carries no customer key), with revenue, customers and the average order.
series array of object always New and returning orders and revenue per bucket of the period.
repeatRate number | null always Of the customers whose first order is in the period, the share with two orders or more, a fraction.
medianDaysToSecond number | null always The median number of days from a first order to the second, over those customers.
cohortGrain "week" | "month" always Whether cohorts are weeks (while the site's first order is under 180 days old) or months.
cohorts array of object always The last 8 weekly or 6 monthly cohorts of new customers, whatever the period: start (YYYY-MM-DD, a Monday or the first of a month), the customers, then per period from the first one the customers who ordered and their revenue. Periods after today are 0.
ltvByFirstProduct array of object always Lifetime value by the product of the first order: customers, orders per customer, revenue per customer over all time, repeat rate and the average first order.
ltvByFirstChannel array of object always The same by the channel the model credits with the first order.

Example #

curl -s -X POST https://clearsaga.com/api/v1/store.customers \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456"}'

Run clearsaga help store customers for one flag per field.

Orders and their channels #

POST /api/v1/store.orders · Read

The orders of a period, newest first, each with the channels its journey touched and the one the model credits, and whether the customer was new or returning. Get the siteId from sites.list first. It pages by cursor: the answer holds limit rows (20 unless set, 100 at most) and nextCursor; send that as cursor for the next, older page, until it is null. There is no comparison. Answers 402 workspace_locked while the workspace's dashboards are locked.

Needs a token with the Read permission. Answers 402 while the dashboards of the workspace are locked.

Input #

Field Type Required Description
siteId string required The site id, from sites.list.
range "today" | "yesterday" | "30m" | "12h" | "24h" | "week" | "7d" | "30d" | "60d" | "90d" | "mtd" | "ytd" | "12mo" | "all" | "custom" optional The period: today, yesterday, 30m, 12h, 24h, week, 7d, 30d, 60d, 90d, mtd, ytd, 12mo, all. Left out, the workspace default. For dates send from and to instead.
from string optional First day of a custom period, YYYY-MM-DD in the site's time zone, sent with to.
to string optional Last day of a custom period, inclusive, YYYY-MM-DD, sent with from.
compare "prev" | "week" | "month" | "quarter" | "year" | "custom" | "off" optional Accepted and ignored: this list has no comparison.
cfrom string optional Accepted and ignored: this list has no comparison.
cto string optional Accepted and ignored: this list has no comparison.
currency string optional The currency to report, ISO 4217 such as USD. Left out, the one with the most orders.
model "last_click" | "last_click_views" | "clicks_views" | "last_touch" | "first_touch" | "linear" optional The attribution model: last_click (the default), last_click_views, clicks_views, last_touch, first_touch or linear. The two view models also credit orders no click explains from the platforms' daily purchases after a view, an estimate.
cursor string, at most 200 characters optional Where to continue: the nextCursor of the page before. Leave it out for the newest orders.
limit integer, 1 to 100 optional Rows per page, 1 to 100. 20 when left out.

Output #

Field Type Present Description
labels object always What the report covers: the period and the comparison period as the dashboard names them, the currency of every amount (ISO 4217; amounts are whole minor units), the attribution model and the lookback in days.
rows array of object always The orders of the period, newest first: when it was paid (milliseconds since 1970 UTC), the order number at the store and a short label, the amount in minor units, the product and number of items, whether the customer was new or returning (unknown without a customer key), every channel the journey touched oldest first, the channel the model credits, and estimated when that credit came from platform-reported views.
nextCursor string | null always Send this as cursor to get the next, older page. Null on the last page.

Example #

curl -s -X POST https://clearsaga.com/api/v1/store.orders \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456"}'

Run clearsaga help store orders for one flag per field.

Channel overlap #

POST /api/v1/store.overlap · Read

How the channels of a period share their orders: per channel the orders whose journey touched it, per pair of channels the orders that touched both, and how many orders touched one channel, several, or none. Get the siteId from sites.list first. An order that touched several channels counts fully in each, so the channel rows add up to more than the store's orders. Amounts are whole minor units of the currency in labels. Answers 402 workspace_locked while the workspace's dashboards are locked.

Needs a token with the Read permission. Answers 402 while the dashboards of the workspace are locked.

Input #

Field Type Required Description
siteId string required The site id, from sites.list.
range "today" | "yesterday" | "30m" | "12h" | "24h" | "week" | "7d" | "30d" | "60d" | "90d" | "mtd" | "ytd" | "12mo" | "all" | "custom" optional The period: today, yesterday, 30m, 12h, 24h, week, 7d, 30d, 60d, 90d, mtd, ytd, 12mo, all. Left out, the workspace default. For dates send from and to instead.
from string optional First day of a custom period, YYYY-MM-DD in the site's time zone, sent with to.
to string optional Last day of a custom period, inclusive, YYYY-MM-DD, sent with from.
compare "prev" | "week" | "month" | "quarter" | "year" | "custom" | "off" optional prev (the default), week, month, quarter, year, custom (with cfrom and cto) or off.
cfrom string optional First day of a custom comparison, YYYY-MM-DD.
cto string optional Last day of a custom comparison, inclusive, YYYY-MM-DD.
currency string optional The currency to report, ISO 4217 such as USD. Left out, the one with the most orders.
model "last_click" | "last_click_views" | "clicks_views" | "last_touch" | "first_touch" | "linear" optional The attribution model: last_click (the default), last_click_views, clicks_views, last_touch, first_touch or linear. The two view models also credit orders no click explains from the platforms' daily purchases after a view, an estimate.

Output #

Field Type Present Description
serverNow number always The clock the period was resolved with: the start of the next whole minute, milliseconds since 1970 UTC.
serverTime number always When the answer was built, milliseconds since 1970 UTC.
window object always The period the numbers cover: from and to in milliseconds since 1970 UTC (to is exclusive), the time zone, a label and the bucket size.
compare object | null always The comparison period in the same form, or null when there is none.
rawFrom number | null always The earliest time detailed data is kept from, or null when nothing was trimmed.
truncated boolean always True when a filtered answer could only cover the part of the period that still has detailed data.
labels object always What the report covers: the period and the comparison period as the dashboard names them, the currency of every amount (ISO 4217; amounts are whole minor units), the attribution model and the lookback in days.
channels array of object always Per channel, the orders whose journey touched it at least once and their revenue. An order that touched three channels counts fully in each.
pairs array of object always Per pair of channels, the orders whose journey touched both and their revenue.
singleChannelOrders number always Orders whose journey touched one channel.
multiChannelOrders number always Orders whose journey touched two channels or more.
unattributedOrders number always Orders with no recorded visit.

Example #

curl -s -X POST https://clearsaga.com/api/v1/store.overlap \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456"}'

Run clearsaga help store overlap for one flag per field.

Profit report #

POST /api/v1/store.profit · Read

What the store kept in a period: gross sales, then refunds, product cost, shipping, payment fees, ad spend and the other costs, down to contribution and net profit, with margin, MER and the same lines per bucket. Get the siteId from sites.list first. The costs come from the site's cost rules, product costs and cost lines (store.costs); coverage says how many order lines had a product cost, since a missing cost overstates profit. Tax is inside gross, as the store charged it. Amounts are whole minor units (cents) of one currency, named in labels.currency; spend in another currency is listed in otherCurrencySpend, costs from the cost settings in another currency in otherCurrencyCosts, and neither is added in. Answers 402 workspace_locked while the workspace's dashboards are locked.

Needs a token with the Read permission. Answers 402 while the dashboards of the workspace are locked.

Input #

Field Type Required Description
siteId string required The site id, from sites.list.
range "today" | "yesterday" | "30m" | "12h" | "24h" | "week" | "7d" | "30d" | "60d" | "90d" | "mtd" | "ytd" | "12mo" | "all" | "custom" optional The period: today, yesterday, 30m, 12h, 24h, week, 7d, 30d, 60d, 90d, mtd, ytd, 12mo, all. Left out, the workspace default. For dates send from and to instead.
from string optional First day of a custom period, YYYY-MM-DD in the site's time zone, sent with to.
to string optional Last day of a custom period, inclusive, YYYY-MM-DD, sent with from.
compare "prev" | "week" | "month" | "quarter" | "year" | "custom" | "off" optional prev (the default), week, month, quarter, year, custom (with cfrom and cto) or off.
cfrom string optional First day of a custom comparison, YYYY-MM-DD.
cto string optional Last day of a custom comparison, inclusive, YYYY-MM-DD.
currency string optional The currency to report, ISO 4217 such as USD. Left out, the one with the most orders.
model "last_click" | "last_click_views" | "clicks_views" | "last_touch" | "first_touch" | "linear" optional Accepted and passed on: nothing in this report depends on the model.

Output #

Field Type Present Description
serverNow number always The clock the period was resolved with: the start of the next whole minute, milliseconds since 1970 UTC.
serverTime number always When the answer was built, milliseconds since 1970 UTC.
window object always The period the numbers cover: from and to in milliseconds since 1970 UTC (to is exclusive), the time zone, a label and the bucket size.
compare object | null always The comparison period in the same form, or null when there is none.
rawFrom number | null always The earliest time detailed data is kept from, or null when nothing was trimmed.
truncated boolean always True when a filtered answer could only cover the part of the period that still has detailed data.
labels object always What the report covers: the period and the comparison period as the dashboard names them, the currency of every amount (ISO 4217; amounts are whole minor units), the attribution model and the lookback in days.
lines array of object always The profit lines in order, each in minor units with what it covers (scope): gross, refunds, cogs (product cost), shipping, payment_fees, ad_spend, custom_costs, contribution (gross minus refunds, product cost, shipping, fees and ad spend) and net_profit (contribution minus the other costs). previousMinor is the comparison period, delta the change.
marginRatio number | null always Net profit over gross minus refunds, a fraction; null when that is not positive.
contributionRatio number | null always Contribution over gross minus refunds, a fraction; null when that is not positive.
mer number | null always Every order's revenue over all ad spend in the period; null without spend.
series array of object always One point per bucket of the period: gross, costs (product cost, shipping, fees and the other costs spread over their days), ad spend and net, in minor units.
customCosts array of object always What each cost line of the site came to in the period.
coverage object always How complete the costs are: order lines with a product cost out of all lines, up to 20 products without one (most lines first), and whether a shipping and a payment fee rule are set. Missing costs overstate profit.
otherCurrencySpend array of object always Spend in a currency other than the report's: listed here by currency, in minor units of that currency, and never added into any number of this answer.
otherCurrencyCosts array of object always Costs from the cost settings (cost lines, and the fixed shipping and fee per order) in a currency other than the report's: listed here by currency, in minor units of that currency, and never added into net profit or any other number of this answer.

Example #

curl -s -X POST https://clearsaga.com/api/v1/store.profit \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456"}'

Run clearsaga help store profit for one flag per field.

Revenue reconciliation #

POST /api/v1/store.reconciliation · Read

Checks, day by day, that the revenue the model credits to every channel (including not attributed) adds up to the revenue the store took. Get the siteId from sites.list first. ok is true when every day matches; days lists each day with the store's revenue, the credited revenue and the difference, in whole minor units of the currency in labels. Answers 402 workspace_locked while the workspace's dashboards are locked.

Needs a token with the Read permission. Answers 402 while the dashboards of the workspace are locked.

Input #

Field Type Required Description
siteId string required The site id, from sites.list.
range "today" | "yesterday" | "30m" | "12h" | "24h" | "week" | "7d" | "30d" | "60d" | "90d" | "mtd" | "ytd" | "12mo" | "all" | "custom" optional The period: today, yesterday, 30m, 12h, 24h, week, 7d, 30d, 60d, 90d, mtd, ytd, 12mo, all. Left out, the workspace default. For dates send from and to instead.
from string optional First day of a custom period, YYYY-MM-DD in the site's time zone, sent with to.
to string optional Last day of a custom period, inclusive, YYYY-MM-DD, sent with from.
compare "prev" | "week" | "month" | "quarter" | "year" | "custom" | "off" optional prev (the default), week, month, quarter, year, custom (with cfrom and cto) or off.
cfrom string optional First day of a custom comparison, YYYY-MM-DD.
cto string optional Last day of a custom comparison, inclusive, YYYY-MM-DD.
currency string optional The currency to report, ISO 4217 such as USD. Left out, the one with the most orders.
model "last_click" | "last_click_views" | "clicks_views" | "last_touch" | "first_touch" | "linear" optional The attribution model: last_click (the default), last_click_views, clicks_views, last_touch, first_touch or linear. The two view models also credit orders no click explains from the platforms' daily purchases after a view, an estimate.

Output #

Field Type Present Description
serverNow number always The clock the period was resolved with: the start of the next whole minute, milliseconds since 1970 UTC.
serverTime number always When the answer was built, milliseconds since 1970 UTC.
window object always The period the numbers cover: from and to in milliseconds since 1970 UTC (to is exclusive), the time zone, a label and the bucket size.
compare object | null always The comparison period in the same form, or null when there is none.
rawFrom number | null always The earliest time detailed data is kept from, or null when nothing was trimmed.
truncated boolean always True when a filtered answer could only cover the part of the period that still has detailed data.
labels object always What the report covers: the period and the comparison period as the dashboard names them, the currency of every amount (ISO 4217; amounts are whole minor units), the attribution model and the lookback in days.
ok boolean always True when credited revenue equals the store's revenue on every day of the period.
maxDriftMinor number always The largest difference of one day, in minor units.
days array of object always Per day (YYYY-MM-DD in the site's time zone): the store's revenue, the revenue credited to every channel, the part credited to no channel, and the difference.

Example #

curl -s -X POST https://clearsaga.com/api/v1/store.reconciliation \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456"}'

Run clearsaga help store reconciliation for one flag per field.

Save cost rules #

POST /api/v1/store.saveCostSettings · Write

Changes the cost rules of a site: what shipping one order costs, the payment fee (a share of the order plus a fixed amount) and the product cost of a line whose product has none. Get the siteId from sites.list first. Only the rules sent change. Amounts are minor units of the site's cost currency, which the first cost write pins to the currency of its orders. Profit changes for every past period. Sending the same rules twice changes nothing.

Needs a token with the Write permission.

Input #

Field Type Required Description
siteId string required The site id, from sites.list.
shippingPerOrderMinor integer, 0 to 100000000 optional What shipping one order costs the store, in minor units, 0 to 100000000.
paymentFeeBps integer, 0 to 2000 optional The payment fee as a share of the order, in basis points: 290 is 2.9%. 0 to 2000.
paymentFeeFixedMinor integer, 0 to 100000 optional The fixed part of the payment fee per order, in minor units: 30 is $0.30. 0 to 100000.
defaultCogsBps integer, 0 to 10000 optional The product cost of a line whose product has no unit cost, in basis points of its price: 3500 is 35%. 0 to 10000.

Output #

Field Type Present Description
settings object always The cost rules as saved. The cost rules: currency (the currency of every cost of the site, null until the first cost is saved), shippingPerOrderMinor (what shipping one order costs the store), paymentFeeBps and paymentFeeFixedMinor (the payment fee of an order: basis points of its amount, 290 is 2.9%, plus a fixed amount) and defaultCogsBps (the product cost of a line whose product has none, in basis points of its price).

Example #

curl -s -X POST https://clearsaga.com/api/v1/store.saveCostSettings \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456"}'

Run clearsaga help store saveCostSettings for one flag per field.

Set product costs #

POST /api/v1/store.setProductCosts · Write

Saves the unit cost of up to 500 products of a site, each by its product id at the store. A product that already has a cost gets the new one. Get the siteId from sites.list first. Costs are minor units of the site's cost currency. A site holds at most 5,000 product costs. Sending the same costs twice changes nothing.

Needs a token with the Write permission.

Input #

Field Type Required Description
siteId string required The site id, from sites.list.
costs array of object, 1 to 500 items required The products and their unit costs, 1 to 500.

Fields of costs

Field Type Required Description
provider "stripe" | "paddle" | "shopify" | "polar" | "creem" | "mollie" | "revolut" | "whop" | "revenuecat" | "superwall" | "manual" | "demo" optional Where the product is sold: shopify unless set. The orders of a Shopify store carry its product ids. Default: "shopify".
productId string, 1 to 200 characters required The product id at that store, as the orders carry it, such as 8215530291462.
productName string, at most 200 characters optional The product name, for the dashboard. Optional.
unitCostMinor integer, 0 to 1000000000 required What one unit costs the store, in minor units of the site's cost currency.

Output #

Field Type Present Description
written number always How many product costs were saved: one per distinct product of the input.
products array of object always The product costs as saved. Each product cost: its id, the store it sells through (provider), the product id there and its name, the unit cost in minor units of currency, where it came from (form, csv or seed) and when it last changed (milliseconds since 1970 UTC).

Example #

curl -s -X POST https://clearsaga.com/api/v1/store.setProductCosts \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456","costs":[{"productId":"ID","unitCostMinor":0}]}'

Run clearsaga help store setProductCosts for one flag per field.

Store summary #

POST /api/v1/store.summary · Read

The store's numbers for a period in one answer: revenue, orders, average order, new customers, the returning share, refunds, net profit and margin, ad spend, blended ROAS, MER, CPA and cost per new customer, then the same kind of tiles for each ad platform, each with its change and a sparkline. Get the siteId from sites.list first. Amounts are whole minor units (cents) of one currency, named in labels.currency; spend in another currency is listed in otherCurrencySpend, costs from the cost settings in another currency in otherCurrencyCosts, and neither is added in. Every number names what it covers in its scope: orders_paid (Orders paid in the period, before refunds), credited (Orders credited by the chosen model), credited_estimated (Credited by the chosen model; view credit is an estimate from daily platform totals), platform_reported (As the ad platform reports it), spend_synced (Spend as synced or uploaded, in the account currency), cost_settings (From the cost settings and cost lines of this site), refunds_dated (Refunds dated in the period). reconciliation says whether credited revenue adds up to the store's revenue every day. The store reports take no filter. Answers 402 workspace_locked while the workspace's dashboards are locked.

Needs a token with the Read permission. Answers 402 while the dashboards of the workspace are locked.

Input #

Field Type Required Description
siteId string required The site id, from sites.list.
range "today" | "yesterday" | "30m" | "12h" | "24h" | "week" | "7d" | "30d" | "60d" | "90d" | "mtd" | "ytd" | "12mo" | "all" | "custom" optional The period: today, yesterday, 30m, 12h, 24h, week, 7d, 30d, 60d, 90d, mtd, ytd, 12mo, all. Left out, the workspace default. For dates send from and to instead.
from string optional First day of a custom period, YYYY-MM-DD in the site's time zone, sent with to.
to string optional Last day of a custom period, inclusive, YYYY-MM-DD, sent with from.
compare "prev" | "week" | "month" | "quarter" | "year" | "custom" | "off" optional prev (the default), week, month, quarter, year, custom (with cfrom and cto) or off.
cfrom string optional First day of a custom comparison, YYYY-MM-DD.
cto string optional Last day of a custom comparison, inclusive, YYYY-MM-DD.
currency string optional The currency to report, ISO 4217 such as USD. Left out, the one with the most orders.
model "last_click" | "last_click_views" | "clicks_views" | "last_touch" | "first_touch" | "linear" optional The attribution model: last_click (the default), last_click_views, clicks_views, last_touch, first_touch or linear. The two view models also credit orders no click explains from the platforms' daily purchases after a view, an estimate.

Output #

Field Type Present Description
serverNow number always The clock the period was resolved with: the start of the next whole minute, milliseconds since 1970 UTC.
serverTime number always When the answer was built, milliseconds since 1970 UTC.
window object always The period the numbers cover: from and to in milliseconds since 1970 UTC (to is exclusive), the time zone, a label and the bucket size.
compare object | null always The comparison period in the same form, or null when there is none.
rawFrom number | null always The earliest time detailed data is kept from, or null when nothing was trimmed.
truncated boolean always True when a filtered answer could only cover the part of the period that still has detailed data.
labels object always What the report covers: the period and the comparison period as the dashboard names them, the currency of every amount (ISO 4217; amounts are whole minor units), the attribution model and the lookback in days.
hasOrders boolean always False when the site has no order at all, in which case every number is empty.
hasSpend boolean always False when no ad spend was ever synced or uploaded for the site: the spend, ROAS, MER and CPA tiles then have no value.
hasCosts boolean always False while the site has no cost rule, product cost or cost line: net profit and margin then leave out every cost but ad spend.
store array of object always The tiles of the Store section, by key: revenue, orders, aov, new_customers, returning_share, refunds, net_profit, margin, ad_spend, blended_roas (revenue credited to an ad platform over all spend), mer (all revenue over all spend), cpa, cost_per_new_customer. Each tile: key, label, unit (money in minor units, count, ratio as a fraction, decimal such as a ROAS of 2.4, days), value and previous (the comparison period; null when there is none), delta (the change as a fraction of the absolute previous value, new when previous was 0, null when it cannot be computed), deltaInverted (true for costs, where a drop is good), scope (what the number covers) and spark (one point per bucket of the period, oldest first).
platforms array of object always One section per ad platform with spend ever, in a fixed order: hasSpend says whether it has spend in this period, and its tiles are spend, roas, platform_roas, orders, revenue, cpa, nc_roas, impressions, clicks, ctr, cpc, cpm, platform_conversions and view_conversions, in the same form as store.
otherCurrencySpend array of object always Spend in a currency other than the report's: listed here by currency, in minor units of that currency, and never added into any number of this answer.
otherCurrencyCosts array of object always Costs from the cost settings (cost lines, and the fixed shipping and fee per order) in a currency other than the report's: listed here by currency, in minor units of that currency, and never added into net profit or any other number of this answer.
reconciliation object always Whether the revenue credited to every channel adds up to the store's revenue on every day of the period: ok, the number of days checked and the largest difference found, in minor units.

Example #

curl -s -X POST https://clearsaga.com/api/v1/store.summary \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456"}'

Run clearsaga help store summary for one flag per field.

Change a cost line #

POST /api/v1/store.updateCostLine · Write

Replaces the label, kind, amount and days of one cost line of a site, by its id from store.costs. Get the siteId from sites.list first. Every field is sent; the answer is the line as saved. An id the site does not have answers 404 with detail cost_line. Profit changes for every period the line covers.

Needs a token with the Write permission.

Input #

Field Type Required Description
siteId string required The site id, from sites.list.
id string, at least 1 characters required The cost line id, from store.costs.
label string, 1 to 80 characters required What the cost is, 1 to 80 characters: Rent, Shopify plan, Returns handling.
kind "monthly" | "one_off" | "percent_of_revenue" required monthly: an amount per month, spread over the days it covers. one_off: an amount once, on startsOn. percent_of_revenue: a share of the revenue of the days it covers.
amount integer, 0 to 1000000000 required Minor units of the site's cost currency for monthly and one_off; basis points for percent_of_revenue (150 is 1.5%, at most 10000).
startsOn string required The first day the cost counts, YYYY-MM-DD; the day of a one_off cost.
endsOn string | null required The last day it counts, inclusive, YYYY-MM-DD, or null for no end. Must be null for one_off and may not be before startsOn.

Output #

Field Type Present Description
id string always The cost line id.
label string always What the cost is, as the dashboard shows it.
kind "monthly" | "one_off" | "percent_of_revenue" always monthly: a cost per month, spread over its days. one_off: once, on startsOn. percent_of_revenue: a share of the revenue of the days it covers.
amount number always Minor units for monthly and one_off; basis points (1 is 0.01%) for percent_of_revenue.
currency string always The currency of the amount: the site's cost currency.
startsOn string always The first day it counts, YYYY-MM-DD; the day of a one_off cost.
endsOn string | null always The last day it counts, inclusive, or null when it has no end. Always null for one_off.
updatedAt number always When it last changed, milliseconds since 1970 UTC.

Example #

curl -s -X POST https://clearsaga.com/api/v1/store.updateCostLine \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456","id":"STORE_ID","label":"example","kind":"monthly","amount":0,"startsOn":"2026-10-01","endsOn":"2026-10-01"}'

Run clearsaga help store updateCostLine for one flag per field.

Upload product costs #

POST /api/v1/store.uploadProductCosts · Write

Saves product costs from a CSV file: a header row with product_id (or id), an optional product_name, and unit_cost (or cost) in major units such as 26.00. Get the siteId from sites.list first. Rows that cannot be read are skipped and listed with their line number. A currency column, when present, must match the site's cost currency. Uploading the same file twice changes nothing.

Needs a token with the Write permission.

Input #

Field Type Required Description
siteId string required The site id, from sites.list.
csv string, 1 to 1000000 characters required The file's text, at most 1,000,000 characters and 20,000 rows.

Output #

Field Type Present Description
rows number always The data rows of the file, without the header.
written number always The rows that were saved.
skipped array of object always Each row that was not saved: its line number in the file (the header is line 1) and why.
currency string | null always The currency the amounts were read in.
from string | null always The first day of the file, YYYY-MM-DD; null for a file without dates.
to string | null always The last day of the file, YYYY-MM-DD; null for a file without dates.

Example #

curl -s -X POST https://clearsaga.com/api/v1/store.uploadProductCosts \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456","csv":"example"}'

Run clearsaga help store uploadProductCosts for one flag per field.

Upload ad spend #

POST /api/v1/store.uploadSpend · Write

Saves ad spend from a CSV file, for platforms that are not connected: date, platform (meta, google_ads, tiktok, pinterest or amazon_ads), campaign, optional ad_set and ad, spend in major units, and optional impressions, clicks, conversions, conversion_value and view_conversions. Get the siteId from sites.list first. An upload replaces the uploaded spend of the same platforms over the days the file covers, so uploading a corrected file twice is safe. Rows that cannot be read are skipped and listed.

Needs a token with the Write permission.

Input #

Field Type Required Description
siteId string required The site id, from sites.list.
csv string, 1 to 1000000 characters required The file's text, at most 1,000,000 characters and 20,000 rows.
currency string required The currency the ad account bills in, ISO 4217 such as USD. Spend in another currency than the store's is listed beside the reports and never added in.

Output #

Field Type Present Description
rows number always The data rows of the file, without the header.
written number always The rows that were saved.
skipped array of object always Each row that was not saved: its line number in the file (the header is line 1) and why.
currency string | null always The currency the amounts were read in.
from string | null always The first day of the file, YYYY-MM-DD; null for a file without dates.
to string | null always The last day of the file, YYYY-MM-DD; null for a file without dates.

Example #

curl -s -X POST https://clearsaga.com/api/v1/store.uploadSpend \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456","csv":"example","currency":"USD"}'

Run clearsaga help store uploadSpend for one flag per field.