← Help center

API reference

The ROASaurus REST API, webhooks, SQL, warehouse exports, Google Sheets and Looker Studio.

Authentication

Create API keys under Store settings › API & data. Each key belongs to one store and has scopes. Send it as Authorization: Bearer rsk_…. Keys can be revoked at any time; the list shows when each was last used. The older store key pair (X-Roasaurus-Key plus Authorization: Bearer <key>) keeps working with every scope except pii.

ScopeGives
orders:readOrders with attribution and profit per order, order items
customers:readCustomers with LTV and predicted LTV
ads:readAd spend per platform, campaign and day
attribution:readAttribution by channel and campaign under any model
profit:readP&L by day, products and cohorts
subscriptions:readSubscription analytics
leads:readLeads, pipeline and lead attribution
events:readStorefront and offline events of consenting visitors
metrics:readCustom dashboards and metrics
reports:readReady-made reports as JSON or CSV (Looker Studio, Sheets); each report also needs its area scope
sql:readRead-only SQL over the store views
mcpThe MCP server (the Ask AI tools)
piiUnmasked emails, phone numbers, names, addresses, IP addresses and user agents
writePOST orders, offline events, survey answers and expenses
actions:writeMCP clients may propose ad changes to the Actions inbox (an owner or admin, or a rule, still applies them)

Conventions

Endpoints

Account

GET /api/v1/openapi.json · no key

This OpenAPI document.

GET /api/v1/me · scope any

The store and scopes of the key. Works with a key of any scope.

Returns: store, key

Orders

GET /api/v1/orders · scope orders:read

Orders with attribution and profit. Oldest first. Each order carries its profit (revenue, COGS, fees, gross profit, contribution margin), line items with their costs, and its attribution: the model credits plus first and last click inside the lookback.

fromStart: a store-local day (YYYY-MM-DD) or an ISO 8601 timestamp.
toEnd (exclusive for timestamps; a day includes that whole day).
updated_sinceOnly rows changed at or after this time (incremental sync).
modelAttribution model. (last_click, first_click, last_non_direct, linear, linear_paid, position, time_decay, markov, shapley, total_impact, any_click, clicks_views)
lookbackClick lookback in days (1–365) or "all"; default the store setting.
limitPage size (1–1000).
cursorThe next_cursor of the previous page.

Returns: has_more, next_cursor, data[].id, data[].name, data[].created_at, data[].updated_at, data[].currency, data[].financial_status, data[].fulfillment_status, data[].cancelled_at, data[].sales_channel, data[].order_type, data[].total_price, data[].gross_sales, data[].discounts, data[].shipping_charged, data[].taxes, data[].tips, data[].new_customer, data[].profit, data[].customer, data[].discount_codes, data[].tags, data[].utm, data[].landing_site, data[].referring_site, data[].client, data[].attribution, data[].items

GET /api/v1/orders/{id} · scope orders:read

One order.

id *Order id
modelAttribution model. (last_click, first_click, last_non_direct, linear, linear_paid, position, time_decay, markov, shapley, total_impact, any_click, clicks_views)
lookbackClick lookback in days (1–365) or "all"; default the store setting.

Returns: id, name, created_at, updated_at, currency, financial_status, fulfillment_status, cancelled_at, sales_channel, order_type, total_price, gross_sales, discounts, shipping_charged, taxes, tips, new_customer, profit, customer, discount_codes, tags, utm, landing_site, referring_site, client, attribution, items

Customers

GET /api/v1/customers · scope customers:read

Customers with LTV and predicted LTV. `from`/`to` filter on the first order, `updated_since` on the last order.

fromStart: a store-local day (YYYY-MM-DD) or an ISO 8601 timestamp.
toEnd (exclusive for timestamps; a day includes that whole day).
updated_sinceOnly rows changed at or after this time (incremental sync).
limitPage size (1–1000).
cursorThe next_cursor of the previous page.

Returns: has_more, next_cursor, data[].id, data[].email, data[].email_sha256, data[].orders, data[].revenue, data[].gross_profit, data[].contribution, data[].aov, data[].first_order_at, data[].last_order_at, data[].first_order_id, data[].last_order_id, data[].first_order, data[].predicted_ltv, data[].expected_next_12m

GET /api/v1/customers/{id} · scope customers:read

One customer with their orders.

id *Customer id

Returns: id, email, email_sha256, orders, revenue, gross_profit, contribution, aov, first_order_at, last_order_at, first_order_id, last_order_id, first_order, predicted_ltv, expected_next_12m, recent_orders

GET /api/v1/cohorts · scope customers:read

Cohorts by first-order period.

byCohort period. (month, week, quarter, year)
metricCohort metric (revenue, gross_profit, contribution, retention, ...).
countNumber of cohorts (1–60).

Returns: by, metric, currency, customers, average_cac, payback_period, average, data[].cohort, data[].start, data[].customers, data[].cac, data[].spend, data[].repeat_rate, data[].first_order, data[].payback_period, data[].values, data[].predicted

Ads

GET /api/v1/ad-spend · scope ads:read

Ad spend per platform, campaign and day.

fromFirst store-local day (YYYY-MM-DD).
toLast store-local day (YYYY-MM-DD).
platformOnly this platform (meta, google, tiktok, ...).
limitPage size (1–5000).
cursorThe next_cursor of the previous page.

Returns: has_more, next_cursor, data[].day, data[].platform, data[].campaign_id, data[].campaign, data[].spend, data[].impressions, data[].clicks, data[].account_id, data[].account_currency, data[].spend_original, data[].manual

GET /api/v1/campaigns · scope ads:read

Spend, clicks, CTR and CPC per campaign.

periodA period like the dashboard; from and to (days) win over it. (today, yesterday, 7, 14, 30, 90, mtd, last_month, ytd, 365)
fromFirst store-local day (YYYY-MM-DD).
toLast store-local day (YYYY-MM-DD).
platformOnly this platform.

Returns: from, to, currency, data[].platform, data[].campaign_id, data[].campaign, data[].spend, data[].impressions, data[].clicks, data[].ctr, data[].cpc, data[].first_day, data[].last_day, data[].days

Attribution

GET /api/v1/attribution · scope attribution:read

Attribution by channel and campaign.

periodA period like the dashboard; from and to (days) win over it. (today, yesterday, 7, 14, 30, 90, mtd, last_month, ytd, 365)
fromFirst store-local day (YYYY-MM-DD).
toLast store-local day (YYYY-MM-DD).
modelAttribution model. (last_click, first_click, last_non_direct, linear, linear_paid, position, time_decay, markov, shapley, total_impact, any_click, clicks_views)
lookbackClick lookback in days (1–365) or "all"; default the store setting.
date_basisCount conversions on the order date or the click date. (order, click)
conversionWhat counts as a conversion: orders (default) or a lead stage such as leads or won.
viewsInclude view-through credit (1 or true).
view_weightsPer-platform view weights, e.g. meta:30.
view_windowView window in days. (1, 7)
survey_lookbackTotal Impact survey lookback.
positionPosition-based weights, e.g. 40,20,40.
half_lifeTime decay half-life in days.

Returns: currency, from, to, model, modelLabel, additive, totals, channels, campaigns

GET /api/v1/view-through · scope attribution:read

View-through conversions per platform and campaign. Reported by the platforms, placed on orders (modelled or verified) and credited after the view weights.

periodA period like the dashboard; from and to (days) win over it. (today, yesterday, 7, 14, 30, 90, mtd, last_month, ytd, 365)
fromFirst store-local day (YYYY-MM-DD).
toLast store-local day (YYYY-MM-DD).
lookbackClick lookback in days (1–365) or "all"; default the store setting.
view_weightsPer-platform view weights, e.g. meta:30.
view_windowView window in days. (1, 7)

GET /api/v1/leads · scope leads:read

Leads and pipeline by channel and campaign. Leads, cost per lead, MQL/SQL/win rates, pipeline and won revenue, and leads per channel and campaign under any attribution model.

periodA period like the dashboard; from and to (days) win over it. (today, yesterday, 7, 14, 30, 90, mtd, last_month, ytd, 365)
fromFirst store-local day (YYYY-MM-DD).
toLast store-local day (YYYY-MM-DD).
modelAttribution model. (last_click, first_click, last_non_direct, linear, linear_paid, position, time_decay, markov, shapley, total_impact, any_click, clicks_views)
lookbackClick lookback in days (1–365) or "all"; default the store setting.

Returns: currency, from, to, model, note, totals, channels, campaigns, sources

Profit

GET /api/v1/profit · scope profit:read

P&L totals and days for a period.

periodA period like the dashboard; from and to (days) win over it. (today, yesterday, 7, 14, 30, 90, mtd, last_month, ytd, 365)
fromFirst store-local day (YYYY-MM-DD).
toLast store-local day (YYYY-MM-DD).

Returns: currency, from, to, totals, metrics, days

GET /api/v1/profit/daily · scope profit:read

P&L by day.

periodA period like the dashboard; from and to (days) win over it. (today, yesterday, 7, 14, 30, 90, mtd, last_month, ytd, 365)
fromFirst store-local day (YYYY-MM-DD).
toLast store-local day (YYYY-MM-DD).
limitPage size (1–366).
cursorThe next_cursor of the previous page.

Returns: has_more, next_cursor, data[].day, data[].currency, data[].orders, data[].revenue, data[].cogs, data[].ad_spend, data[].gross_profit, data[].contribution_margin, data[].net_profit, data[].total_costs, currency

GET /api/v1/products · scope profit:read

Units, revenue, COGS and profit per product or variant.

periodA period like the dashboard; from and to (days) win over it. (today, yesterday, 7, 14, 30, 90, mtd, last_month, ytd, 365)
fromFirst store-local day (YYYY-MM-DD).
toLast store-local day (YYYY-MM-DD).
byGroup by product (default) or variant. (product, variant)
limitPage size (1–1000).
cursorThe next_cursor of the previous page.

Returns: has_more, next_cursor, data[].key, data[].product_id, data[].variant_id, data[].title, data[].sku, data[].units, data[].orders, data[].revenue, data[].refunds, data[].cogs, data[].gross_profit, data[].net_profit, data[].gross_margin, from, to, currency, by

GET /api/v1/subscriptions · scope subscriptions:read

Subscription analytics.

monthsMonths of MRR history.
daysDays for churn and conversion.

Events

GET /api/v1/events · scope events:read

Storefront events of consenting visitors, or offline events. `source=storefront` (default): page views, product views, adds to cart, checkouts and purchases from the store, only for visitors who consented; contact fields, IP and user agent need `pii`. `source=offline`: events sent to POST /api/v1/events.

sourceWhich events. (storefront, offline)
nameOnly this event name.
fromStart: a store-local day (YYYY-MM-DD) or an ISO 8601 timestamp.
toEnd (exclusive for timestamps; a day includes that whole day).
limitPage size (1–1000).
cursorThe next_cursor of the previous page.

Returns: has_more, next_cursor, data[].id, data[].name, data[].event_id, data[].visitor_id, data[].url, data[].created_at, data[].data, data[].ip, data[].user_agent, data[].email_sha256, data[].value, data[].currency, data[].properties, data[].occurred_at

Metrics

GET /api/v1/metrics · scope metrics:read

Built-in and custom dashboard metrics.

Returns: data[].key, data[].label, data[].format, data[].category, data[].description, data[].custom, data[].formula

GET /api/v1/metrics/{key} · scope metrics:read

Evaluate a metric.

key *A built-in or custom metric key.
periodA period like the dashboard; from and to (days) win over it. (today, yesterday, 7, 14, 30, 90, mtd, last_month, ytd, 365)
compareComparison period. (previous, yoy, none)
channelOnly orders whose last ad click was on this channel.
sales_channelOnly this sales channel.
countryOnly this shipping country.
customerNew or returning customers. (new, returning)

Returns: metric, label, format, currency, period, comparison, value, formatted, previous, change

GET /api/v1/dashboards · scope metrics:read

Custom dashboards shared with the workspace.

Reports

GET /api/v1/reports · scope reports:read

The ready-made reports.

Returns: data[].key, data[].label, data[].description, data[].scope, data[].available, data[].params, data[].columns

GET /api/v1/reports/{report} · scope reports:read

Run a report (JSON or CSV). Also needs the report's own scope. Reports: `pnl_daily` (profit:read), `attribution_channels` (attribution:read), `attribution_campaigns` (attribution:read), `ad_spend_daily` (ads:read), `campaigns` (ads:read), `orders` (orders:read), `products` (profit:read), `customers` (customers:read), `cohorts` (customers:read).

report *Report key. (pnl_daily, attribution_channels, attribution_campaigns, ad_spend_daily, campaigns, orders, products, customers, cohorts)
periodA period like the dashboard; from and to (days) win over it. (today, yesterday, 7, 14, 30, 90, mtd, last_month, ytd, 365)
fromFirst store-local day (YYYY-MM-DD).
toLast store-local day (YYYY-MM-DD).
modelAttribution model. (last_click, first_click, last_non_direct, linear, linear_paid, position, time_decay, markov, shapley, total_impact, any_click, clicks_views)
lookbackClick lookback in days (1–365) or "all"; default the store setting.
byCohorts: month, week, quarter or year.
metricCohorts: the cohort metric.
formatjson (default) or csv. (json, csv)

Returns: report, label, currency, from, to, columns, rows

GET /api/v1/feeds/{file} · no key

A signed CSV link (for Google Sheets IMPORTDATA). Created under Store settings › API & data. The URL carries the report parameters and an HMAC signature (`sig`); changing a parameter or revoking the link makes it invalid. No API key needed.

file *<link id>.csv
sig *Signature

SQL

POST /api/v1/sql · scope sql:read

Run a read-only SQL query over the store views. One SELECT over the views orders, order_items, refunds, customers, ad_spend, touches, events, offline_events, products and survey_responses. Read-only, at most 5000 rows, cost-limited and time-limited.

Body: sql, max_rows

Returns: columns, rows, row_count, truncated, elapsed_ms

Write

POST /api/v1/orders · scope write

Send a paid order.

Body: order_id, total, currency, email, phone, first_name, last_name, country, visitor_id, click_ids, client_ip, user_agent, created_at, items, subtotal, discounts, shipping, tax, discount_codes, order_type, test

POST /api/v1/events · scope write

Send an offline event.

Body: event, email, phone, value, currency, event_id, occurred_at, properties

POST /api/v1/expenses · scope write

Send costs (bills, subscriptions) to the P&L. From Zapier, Make or an accounting tool. Amounts in another currency are converted at the day's ECB rate.

Body: id, date, amount, currency, name, category, net_of_vat, expenses

Returns: saved

DELETE /api/v1/expenses/{eid} · scope write

Remove an expense sent through the API.

eid *The id it was sent with

Returns: deleted

POST /api/v1/surveys · scope write

Send a post-purchase survey answer.

Body: order_id, question, answer, visitor_id

Extension

GET /api/v1/extension/stores · browser extension key

Stores, attribution models and periods for the browser extension.

Returns: workspace, stores, models, periods

GET /api/v1/extension/metrics · browser extension key

ROASaurus numbers per campaign, ad set or ad id, for the ads managers.

store *Store id
platform *Ad platform
level *Entity level (campaign, adset, ad)
ids *Comma-separated campaign, ad set or ad ids
modelAttribution model. (last_click, first_click, last_non_direct, linear, linear_paid, position, time_decay, markov, shapley, total_impact, any_click, clicks_views)
periodPeriod

Returns: store, currency, rows, unmatched

Webhooks

Under API & data › Webhooks, subscribe an https URL to events. ROASaurus POSTs JSON { "id", "type", "created_at", "store": { "id", "domain", "currency" }, "data": { … } }:

order.attributedAn order was recorded and matched to its clicks (last click, first click, number of touches)
daily_summary.readyYesterday's revenue, orders, ad spend, MER and net profit, each morning
alert.raisedA new alert: orders or ROAS drop, spend spike, tracking outage, failed deliveries, spend sync
spend.syncedAd spend was synced, with spend per platform for the synced days and any errors

Each request carries X-Roasaurus-Signature: t=<unix time>,v1=<hex>: v1 is the HMAC-SHA256 of "<t>.<raw body>" with the endpoint's signing secret. Compare in constant time and reject timestamps older than 5 minutes. Answer with a 2xx within 10 seconds. Other answers are retried after 1 minute, 5 minutes, 30 minutes, 2, 6, 12 and 24 hours; every attempt is in the delivery log, where a delivery can be sent again. The same event id is never delivered twice to one endpoint unless you resend it.

SQL

Reports › SQL in the dashboard and POST /api/v1/sql run one read-only SELECT over these views of the store: orders, order_items, refunds, customers, ad_spend, touches, events, offline_events, products, survey_responses. Other tables, system catalogs, writes and most functions are refused; a query whose plan is too expensive is refused before it runs, and one that runs longer than 10 seconds is stopped. At most 5,000 rows come back.

Warehouse exports

Under API & data › Warehouse, export to BigQuery, Snowflake, Amazon Redshift, Amazon S3, Google Cloud Storage or Azure Blob Storage, hourly or daily. Each run replaces the days that changed since the last run, so repeating a run is safe. Tables:

ordersEvery order with profit and attribution (last and first click, touches, match method). Partitioned by order_day.
order_itemsOrder lines with their product cost (COGS) and handling. Partitioned by order_day.
ad_spendSpend, impressions and clicks per platform, campaign and day (store currency). Partitioned by day.
touchesAd and UTM clicks of consenting visitors, the steps of each journey. Partitioned by day.
customersEvery identified customer with LTV and predicted LTV (full snapshot each run; emails as hashes). Full snapshot.
daily_pnlEvery P&L line and the derived profit figures per store-local day. Partitioned by day.

On S3, Cloud Storage and Azure each table is a folder with _schema.json and one file per day: <prefix>/orders/order_day=2026-10-01/part-00000.parquet (Parquet with gzip or uncompressed pages), or .jsonl.gz / .csv.gz. Customers are in customers/snapshot/.

Google Sheets

Two ways: connect Google under API & data › Google Sheets and pick a report or saved SQL query to keep a tab up to date hourly or daily; or create a signed CSV link under CSV links and use =IMPORTDATA("https://…") in any sheet.

Looker Studio

Looker Studio reads ROASaurus through a community connector, which Google runs as Apps Script in your own account. Download Code.gs and appsscript.json from API & data › Google Sheets & Looker Studio, paste them into a new project at script.google.com, create a test deployment, and open https://datastudio.google.com/datasources/create?connectorId=<deployment id>. Paste an API key with reports:read and the scopes of the reports you use, then pick a report and an attribution model. The data source's date range sets the period.