Use reports to read aggregated sales, product, acquisition, traffic and journey results or manage report definitions shared with a store. The API base is https://api-store.tringify.com/api/2025-01. Authenticate with a store API token or an installed app credential. Every request is scoped to the credential's store; do not send a store ID or a staff user ID.
Permissions and merchant control#
Reads and query execution require read_reports. Creating, updating or deleting a saved report requires write_reports, together with its read scope. The permission applies to aggregate reporting; it does not grant access to individual customer or order records. Request additional resource permissions only when your integration needs those records.
Merchants can select report permissions when creating or updating a store API token. Apps declare the scopes in the Developer Portal and follow the release and installation approval flow for a changed permission request. Existing credentials do not acquire report access automatically.
API-created reports are always shared with the store team. Staff who can edit reports can change or delete them after the creating token is revoked or the app is uninstalled. API credentials cannot read a staff member's personal reports or inherit the creator's personal favorites. Personal visibility and favorites are managed in Store Admin or the mobile app.
Endpoints#
Method and path |
Scope |
Behavior |
|---|---|---|
GET /reports/catalog |
read_reports |
Supported datasets, fields, editable query presets, descriptions and limits. |
POST /reports/query |
read_reports |
Execute the supplied query. Body: query, optional page and limit. |
GET /reports |
read_reports |
List shared definitions. Query: search, page, limit. |
POST /reports |
write_reports |
Create a shared definition. Body: name and query. |
GET /reports/{id} |
read_reports |
Read a shared definition. |
PUT /reports/{id} |
write_reports |
Replace name and query, supplying the current revision. |
DELETE /reports/{id}?revision=1 |
write_reports |
Delete the saved definition at its current revision. |
POST /reports/{id}/run |
read_reports |
Run the current saved query. Body: optional page and limit; use {} for defaults. |
POST /reports/exports |
read_reports |
Queue a complete CSV export. Body: query. Returns HTTP 202 and a job. |
GET /reports/exports |
read_reports |
List this credential owner’s jobs. Query: page (1–10000), limit (1–50; default 20). |
GET /reports/exports/{jobId} |
read_reports |
Read job state, query, snapshot metadata, row count and expiry. |
GET /reports/exports/{jobId}/download |
read_reports |
Get a short-lived download URL for a completed, unexpired job. |
Start from a preset#
The catalog includes a presets array. Each entry has an id, label, description, and complete query. Copy its query into a query, saved-report or export request, adjusting supported fields and filters as needed. Most presets start with the last 30 days; view_to_purchase_journey starts with the last 7 days. All presets initially include every sales channel. Reading or opening a preset does not create a saved report, export, or schedule. A saved query remains independent of later preset changes. Use the catalog returned to your integration rather than treating the preset list as fixed.
{
"presets": [
{
"id": "order_operations",
"label": "Order operations",
"description": "Current cancellations and full or partial refunds for orders created in the selected period.",
"query": {
"version": 1,
"dataset": "order_operations",
"measures": [
"orders",
"cancelled_orders",
"cancellation_rate",
"refunded_orders",
"partially_refunded_orders"
],
"dimensions": [
"day"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "day",
"direction": "asc"
},
"view": "table"
}
},
{
"id": "payment_outcomes",
"label": "Payment outcomes",
"description": "Current outcomes of payment records created in the selected period, including split tenders and retries.",
"query": {
"version": 1,
"dataset": "payment_operations",
"measures": [
"payment_records",
"payment_orders"
],
"dimensions": [
"provider",
"payment_status"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "payment_records",
"direction": "desc"
},
"view": "table"
}
},
{
"id": "refund_outcomes",
"label": "Refund outcomes",
"description": "Current outcomes of refund requests, with known completed amounts and amount coverage.",
"query": {
"version": 1,
"dataset": "refund_operations",
"measures": [
"refund_records",
"completed_refunds",
"pending_refunds",
"failed_refunds",
"unknown_refunds",
"completed_refund_amount",
"refund_amount_coverage"
],
"dimensions": [
"method"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "refund_records",
"direction": "desc"
},
"view": "table"
}
},
{
"id": "fulfillment_outcomes",
"label": "Fulfilment outcomes",
"description": "Current shipment outcomes and tracking-number coverage for fulfilments created in the selected period.",
"query": {
"version": 1,
"dataset": "fulfillment_operations",
"measures": [
"fulfillment_records",
"fulfillment_orders",
"pending_fulfillments",
"in_transit_fulfillments",
"delivered_fulfillments",
"returning_fulfillments",
"returned_fulfillments",
"failed_fulfillments",
"cancelled_fulfillments",
"tracking_coverage"
],
"dimensions": [
"fulfillment_status"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "fulfillment_records",
"direction": "desc"
},
"view": "table"
}
},
{
"id": "sales_over_time",
"label": "Sales over time",
"description": "Daily net sales, total sales and orders.",
"query": {
"version": 1,
"dataset": "sales",
"measures": [
"net",
"total",
"orders"
],
"dimensions": [
"day"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "day",
"direction": "asc"
},
"view": "table"
}
},
{
"id": "product_economics",
"label": "Product economics",
"description": "Net sales, known product costs and covered margin, with cost coverage visible.",
"query": {
"version": 1,
"dataset": "products",
"measures": [
"units",
"net",
"cogs",
"margin",
"cost_coverage"
],
"dimensions": [
"product"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "net",
"direction": "desc"
},
"view": "table"
}
},
{
"id": "frequently_bought_together",
"label": "Frequently bought together",
"description": "Product pairs present in at least five qualifying orders.",
"query": {
"version": 1,
"dataset": "product_pairs",
"measures": [
"pair_orders"
],
"dimensions": [
"product_a",
"product_b"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "pair_orders",
"direction": "desc"
},
"view": "table"
}
},
{
"id": "repeat_purchases",
"label": "Repeat purchases and replenishment",
"description": "Repeat-customer rate and time between product purchases for identified customers.",
"query": {
"version": 1,
"dataset": "repeat_purchases",
"measures": [
"customers",
"repeat_customers",
"repeat_rate",
"repeat_cycles",
"median_days_between_orders"
],
"dimensions": [
"product"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "repeat_customers",
"direction": "desc"
},
"view": "table"
}
},
{
"id": "traffic_by_source",
"label": "Traffic by source",
"description": "Observed sessions and events grouped by referrer.",
"query": {
"version": 1,
"dataset": "traffic",
"measures": [
"sessions",
"events"
],
"dimensions": [
"referrer"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "sessions",
"direction": "desc"
},
"view": "table"
}
},
{
"id": "campaign_conversion",
"label": "Campaign conversion",
"description": "Sessions, carts, checkouts and purchases by recorded entry source and campaign.",
"query": {
"version": 1,
"dataset": "campaigns",
"measures": [
"sessions",
"cart_sessions",
"checkout_sessions",
"purchase_sessions",
"purchase_rate",
"source_coverage"
],
"dimensions": [
"source",
"medium",
"campaign"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "sessions",
"direction": "desc"
},
"view": "table"
}
},
{
"id": "acquisition_quality",
"label": "Acquisition quality",
"description": "Orders, sales and attribution coverage by recorded campaign details.",
"query": {
"version": 1,
"dataset": "acquisition",
"measures": [
"orders",
"total",
"attributed_orders",
"unattributed_orders",
"attribution_coverage"
],
"dimensions": [
"source",
"medium",
"campaign"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "total",
"direction": "desc"
},
"view": "table",
"attribution_model": "last_touch"
}
},
{
"id": "view_to_purchase_journey",
"label": "Product view to purchase",
"description": "Sessions completing product view, cart, checkout and purchase in order within 30 minutes.",
"query": {
"version": 1,
"dataset": "journeys",
"measures": [
"sessions",
"step_rate",
"overall_rate",
"linkage_coverage"
],
"dimensions": [
"step"
],
"filter": {
"range": "7d"
},
"sort": {
"field": "step",
"direction": "asc"
},
"view": "table",
"journey": {
"steps": [
"product_viewed",
"cart_add",
"begin_checkout",
"purchase"
],
"window_minutes": 30
}
}
}
]
}
Product economics selects units, net sales, cost of goods, covered margin and cost coverage by product, sorted by net sales. Costs and margin cover only remaining units with a known cost snapshot. A zero recorded cost is known; a missing cost is unknown. Coverage is a unit share, not a revenue share. Covered margin does not deduct payment fees, fulfilment expenses, advertising or other operating costs, and is not contribution profit. All financial measures remain in the store base currency.
Run a report#
{
"limit": 25,
"page": 1,
"query": {
"version": 1,
"dataset": "sales",
"measures": [
"orders",
"net"
],
"dimensions": [
"day"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "day",
"direction": "asc"
},
"view": "table"
}
}
Successful responses use {"success":true,"data":...}. Creating a definition returns HTTP 201; queueing an export returns HTTP 202; other successful operations return HTTP 200. Query data contains the executed query, currency, timezone, from, to_exclusive, generated_at, columns, rows, total, page and limit. Dates and timestamps use ISO formats. from is inclusive and to_exclusive is exclusive.
Operational outcomes#
Datasets order_operations, payment_operations, refund_operations and fulfillment_operations describe current outcomes of records created in the requested period. Each dataset filters by its own record creation time, so payment, refund and fulfilment rows can belong to older orders. All exclude test orders and include cancelled and archived orders. The sales-channel filter uses the channel recorded with the order. Days use the store timezone.
These are current-outcome cohorts, not historical status snapshots or counts of status transitions during the period. Later cancellations, payment updates and refund settlements can revise earlier periods. Comparisons with previous_period or previous_year evaluate both cohorts using current outcomes. Order operations includes unpaid orders, so its order count differs from recognized sales.
Payment records retain their own grain: retries and split tenders can create several records per order. payment_orders is distinct within each row and must not be added across rows to calculate unique orders. payment_status is pending, authorized, captured, failed, refunded, partially_refunded or unknown. Refunded payments are not also counted as currently captured. payment_failure_share divides failed records by all records; it is not a checkout failure rate. Provider and method values are recorded identifiers, not localized labels.
refund_status is completed, pending, failed or unknown. Completion requires confirmed provider refund or gift-card settlement and completed order effects; store-credit refunds additionally require confirmation that credit was issued. Manual refunds require completed order effects. Unconfirmed historical store-credit refunds remain unknown. Each partial refund is a separate record. Free-text reasons, notes, customer data and provider payloads are not report fields.
completed_refund_amount sums only known non-negative base-currency amounts of completed refunds, including refunded charges. It is null if no completed amount is known. refund_amount_coverage is the number of completed records with a known amount divided by all completed records; a saved zero is known. Coverage is null when no refunds are complete. This request-date total differs from sales measures that attribute refunds to the original order creation date. Monetary values use the same currency precision and canonical decimal strings as other reports.
Fulfilment operations retain fulfilment-record grain: partial fulfilments count separately and fulfillment_orders is distinct only within each returned row. Current statuses are the canonical fulfilment states. in_transit_fulfillments includes in_transit, out_for_delivery and delivery_failed; failed_fulfillments includes failed, lost, damaged and destroyed. tracking_coverage divides records with a non-empty tracking number by all fulfilment records.
Fulfilment operations do not expose transit or delivery duration. Manual status changes record projection time rather than an immutable carrier event time, so combining them would produce misleading performance metrics. Carrier identifiers are returned as recorded strings and can be blank.
Operational reports support the existing saved definitions, permissions, comparisons, stable pagination and CSV export contract. Missing earlier groups compare integer counts with zero; unknown refund amounts and ratios remain null. API outcomes remain canonical identifiers; clients can translate their labels.
Ordered journeys#
{
"limit": 25,
"page": 1,
"query": {
"version": 1,
"dataset": "journeys",
"measures": [
"sessions",
"step_rate",
"overall_rate",
"linkage_coverage"
],
"dimensions": [
"step"
],
"filter": {
"range": "7d"
},
"sort": {
"field": "step",
"direction": "asc"
},
"view": "table",
"journey": {
"steps": [
"product_viewed",
"cart_add",
"begin_checkout",
"purchase"
],
"window_minutes": 30
}
}
}
Use dataset journeys with journey.steps and journey.window_minutes. Steps must contain 2–8 supported event IDs in their required order. Repeated event types are allowed; purchase may appear only as the final step. The window must be an integer from 1 to 1440 minutes. Strings, fractional minutes, unknown event IDs and journey configuration on another dataset are rejected.
Event ID |
Event |
Retained days |
|---|---|---|
session_started |
Session started |
30 |
page_view |
Page viewed |
30 |
product_viewed |
Product viewed |
30 |
search |
Search |
30 |
cart_add |
Added to cart |
400 |
wishlist_add |
Added to wishlist |
400 |
begin_checkout |
Checkout started |
400 |
customer_login |
Customer signed in |
30 |
customer_register |
Customer registered |
30 |
purchase |
Purchase |
400 |
The journeys dataset in GET /reports/catalog includes journey_options: events with id, label and raw_retention_days, min_steps, max_steps, min_window_minutes and max_window_minutes. Require the single breakdown step, whose canonical value is a one-based integer string. Match that index to the query steps for its event label. Table display accepts multiple measures; a bar chart accepts one. Line charts and comparison periods are not supported.
A session enters once at its earliest first-step event at or after from and before to_exclusive. Each subsequent step must occur strictly after the preceding matched step, at or before entry plus window_minutes, and before to_exclusive. A later repeated entry does not restart the window. Equal timestamps do not establish sequence. Sessions entering near to_exclusive may not have had their full completion window, so recent periods can show incomplete journeys.
Matching requires the same storefront, sales channel and nonempty session identifier, with analytics consent true on every matched event. Sessions are not stitched across devices or storefronts. Test and identified automated events are excluded. Purchase counts the recorded sale event, independent of a later cancellation or refund; these completion counts are not current order counts or sales revenue.
sessions counts entries reaching a step. step_rate divides that count by the preceding step count, while overall_rate divides by entries. The first step returns 1 when entries exist; a zero denominator returns null. recorded_events counts all permitted occurrences of the step event in the period, including events without a linkable session or analytics consent. linked_events counts occurrences with a nonempty session and analytics consent; linkage_coverage is linked_events / recorded_events, or null with no recorded events. Event counts are not distinct session counts, and repeated steps can show the same event coverage. Results contain aggregates, not session IDs or customer identities.
The earliest report instant must still be retained when the query or export is processed. The limit is the shortest raw_retention_days among selected steps. Browsing observations retain 30 days, so a journey containing one rejects 90d and older custom dates. Commerce-only steps retain 400 days; custom selections remain capped at 366 calendar days. Source expiry produces an invalid-input response instead of zero conversions. Queued exports whose source expires fail with REPORT_SOURCE_EXPIRED and provide no partial file; choose recent dates and queue another export.
Saved definitions and queued exports preserve the complete journey configuration. CSV exports append report_journey_steps as a JSON array and report_journey_window_minutes. Keep these with the one-based step column and snapshot metadata when interpreting an export.
Acquisition and attribution coverage#
{
"limit": 25,
"page": 1,
"query": {
"version": 1,
"dataset": "acquisition",
"measures": [
"orders",
"total",
"attributed_orders",
"unattributed_orders",
"attribution_coverage"
],
"dimensions": [
"source",
"medium",
"campaign"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "total",
"direction": "desc"
},
"view": "table",
"attribution_model": "last_touch"
}
}
Campaign performance#
Use dataset campaigns for consented active sessions grouped by their first recorded entry source. Each scoped session is counted once per selected period. Sessions are not unique people and are not joined across stores, storefronts, channels or devices. Entry sources remain attached when a session continues on a later day.
Measures include sessions, product_sessions, cart_sessions, checkout_sessions, purchase_sessions, cart_rate, checkout_rate, purchase_rate and source_coverage. Stage counts describe sessions with each activity during the period, without requiring an ordered sequence. Multiple purchases in one session count once, and later refunds or cancellations do not erase purchase events. Use acquisition for recognized financial amounts and journeys for ordered steps.
Campaign breakdowns include source, medium, campaign, campaign_id, term, content, source_platform, creative_format, marketing_tactic, referrer, landing_page, day and channel. Day is the session's first activity within the selected period in the store timezone. Source uses the entry campaign tag or external referrer; unavailable and historical origins are blank. Source coverage is the share of sessions with a named campaign or referral source. Campaign fields depend on the permissions in effect at capture.
Campaign queries support saved definitions, comparisons, CSV exports and staff schedules. Compared session counts use zero for missing prior rows; rates remain unavailable without a denominator. There is no campaign revenue, ad spend, ROAS or causal lift measure in this dataset.
Dataset acquisition uses the same qualifying orders, creation-date filters and base-currency total sales as sales reports. Select attribution_model as first_touch or last_touch; omission defaults to last_touch. Query results return the effective model. An explicit null, empty string, unknown value or non-string model is rejected with HTTP 400. Other datasets reject this field.
Each model uses its recorded qualifying touch. If that touch is missing, timestamped acquisition history supplies the earliest or latest qualifying touch. If only one touch is known, both models use it. A recorded UTM field, referrer, click identifier or campaign metadata is an acquisition signal. A session ID or landing page alone is not. Missing or malformed history timestamps are ignored. Switching models changes source allocation, not the qualifying order set or total revenue.
Dimensions source, medium and campaign contain the chosen touch's recorded utm_source, utm_medium and utm_campaign. Missing values are empty strings. They are not inferred from click identifiers, and an empty source is not classified as direct traffic. An order can have another acquisition signal despite empty UTM fields. Use attributed_orders, unattributed_orders, attributed_total, unattributed_total and attribution_coverage to distinguish that coverage. Coverage is attributed orders divided by qualifying orders, rounded to at most six decimal places; it is null when there are no qualifying orders.
Both comparison periods use the same selected model. A missing earlier group has zero additive counts and sales, while its coverage remains null. CSV exports always include report_attribution_model for this dataset. Saved definitions and export queries preserve the model; staff schedules reuse the saved choice. Results are aggregates, without individual touch histories or customer identities. They do not measure advertising spend, ROAS or causal campaign lift.
Compare periods#
Set the optional query field comparison to previous_period or previous_year for sales, product and acquisition reports, or operational outcome reports. Omit it when no comparison is required. Explicit null, an empty string, unknown values, and comparisons on traffic reports are rejected.
{
"columns": [],
"comparison": {
"from": "2026-07-15T00:00:00-04:00",
"mode": "previous_period",
"to_exclusive": "2026-08-13T09:00:00-04:00"
},
"currency": "USD",
"from": "2026-08-14T00:00:00-04:00",
"generated_at": "2026-09-12T13:00:00Z",
"limit": 25,
"page": 1,
"query": {
"version": 1,
"dataset": "sales",
"measures": [
"orders",
"net"
],
"dimensions": [
"day"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "day",
"direction": "asc"
},
"view": "table",
"comparison": "previous_period"
},
"rows": [
{
"comparison": {
"change": {
"net": "25.50",
"orders": "1"
},
"change_rate": {
"net": "0.255000",
"orders": "0.500000"
},
"values": {
"net": "100.00",
"orders": "2"
}
},
"values": {
"day": "2026-09-01",
"net": "125.50",
"orders": "3"
}
}
],
"timezone": "America/New_York",
"to_exclusive": "2026-09-12T09:00:00-04:00",
"total": 1
}
Comparison windows use the store timezone and local calendar dates. previous_period shifts both resolved boundaries backward by the number of inclusive local dates in the selection, preserving their local wall-clock times. previous_year uses the corresponding local dates one year earlier; February 29 maps to February 28 when the earlier year is not a leap year. Daily rows use those dates directly. Weekly and monthly rows align by their position within the current and earlier windows.
The current period controls rows, total, sorting and pagination. A group found only in the earlier period is not returned. Each current row adds comparison.values, comparison.change, and comparison.change_rate; the top-level comparison contains mode, from, and to_exclusive. Pages are still independent queries, so use an export when both periods must come from one consistent snapshot.
For additive measures such as orders, units and money totals, a current group with no earlier activity has an earlier value of zero. Values that cannot be derived without observations, including average order value, cost, margin and cost coverage, remain null. If the current value is null and the earlier value is known, the earlier value is retained while change and change rate are null. Change is current minus earlier. Change rate is (current - earlier) / abs(earlier), returned with six decimal places; it is null when either value is unavailable or the earlier value is zero. Money values and changes keep the currency precision and their sign.
Frequently bought together#
Use dataset product_pairs with measure pair_orders, both product_a and product_b dimensions, and view table. Sort by any selected field. The product identifiers are an unordered pair: product_a is the lower numeric product ID, and product_b the higher. Rows include labels.product_a and labels.product_b from the order-item titles. All variants of one product are combined before pairs are counted.
{
"limit": 25,
"page": 1,
"query": {
"version": 1,
"dataset": "product_pairs",
"measures": [
"pair_orders"
],
"dimensions": [
"product_a",
"product_b"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "pair_orders",
"direction": "desc"
},
"view": "table"
}
}
Each pair is counted once per qualifying order, independent of line quantity and variant count. Paid or cash-on-delivery orders qualify, including imports. Test, cancelled and fully refunded orders are excluded. Each product must retain at least one unit after completed refunds. Gift-card products and custom items are excluded. The selected order-creation window and sales channel apply before counting. Only pairs present in at least 5 orders are returned; total counts qualifying pair rows, not orders. An absent pair is not evidence of zero orders.
Product-pair reports reject comparison periods with HTTP 400: a suppressed earlier count must not be presented as zero. Both product dimensions are required; charts and other breakdowns are rejected. Pagination, saved definitions and complete exports use the same pair rules. CSV adds product_a_name and product_b_name in the selected dimension order. Results contain aggregate product relationships, not customer identities, recommendation lift or an audience definition.
Repeat purchases and replenishment#
Use dataset repeat_purchases with the product dimension and table view. Available measures are customers, repeat_customers, repeat_rate, repeat_cycles, average_days_between_orders, and median_days_between_orders. Variants are combined under their product ID and rows include labels.product.
{
"limit": 25,
"page": 1,
"query": {
"version": 1,
"dataset": "repeat_purchases",
"measures": [
"customers",
"repeat_customers",
"repeat_rate",
"repeat_cycles",
"median_days_between_orders"
],
"dimensions": [
"product"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "repeat_customers",
"direction": "desc"
},
"view": "table"
}
}
Only recognized, non-test and non-cancelled orders linked to a customer ID are included. Guest orders are excluded. A repeat cycle is each qualifying product purchase after that customer's first qualifying purchase inside the selected order-creation window. Time-between-purchase measures therefore describe consecutive purchases inside that window, not a customer's lifetime purchase history. Products with fewer than 5 distinct identified buyers are suppressed.
Repeat-purchase reports reject comparison periods, charts and breakdowns other than product. An absent product can mean that it did not meet the minimum sample; it does not prove zero purchases. These aggregate rows do not expose customer identities or create an audience.
Exact amounts and missing values#
Each row has a values object keyed by the selected field IDs. Money, integer and ratio values are decimal strings. Money uses a decimal point, no grouping or currency symbol, and the currency's full decimal precision: for example INR 1234.50, JPY 1234, or KWD 9.590. Keep these values as decimals in calculations. Store Admin's General display preferences do not change the API values.
Financial measures use the store base currency. A currency breakdown groups orders by their order currency but does not change the currency of the measures. null means unavailable; it is not zero. In product reports, a recorded zero cost is known, while an item without a cost snapshot contributes no known cost or covered margin. cost_coverage is a ratio, not a percent string. Product rows can include labels.product alongside the product identifier.
Query rules and limits#
Field |
Accepted values and rules |
|---|---|
version |
|
dataset |
sales, products, product_pairs, repeat_purchases, acquisition, campaigns, traffic, journeys, order_operations, payment_operations, refund_operations or fulfillment_operations. Read the catalog for compatible fields. |
journey |
Required only for journeys: steps is an array of 2–8 event IDs; window_minutes is an integer from 1–1440. Read datasets[].journey_options for events, retention and limits. |
attribution_model |
Acquisition only: first_touch or last_touch. Omission defaults to last_touch; explicit null, empty, unknown and non-string values are rejected. |
measures |
1–10 distinct measure IDs from the selected dataset. |
dimensions |
0–3 distinct breakdown IDs. Traffic requires exactly one. Choose at most one of day, week and month. |
filter.range |
today, yesterday, 7d, 30d, 90d or custom. |
filter.from / filter.to |
Required only for custom, as YYYY-MM-DD. Inclusive start and end dates, in order, covering at most 366 calendar days. The start cannot be in the future. The actual query end is capped at the current time. |
filter.channel_id |
Optional sales-channel UUID. Omitting it includes all channels. Channel filtering does not change the authenticated store. |
comparison |
Optional previous_period or previous_year for sales, products, acquisition, campaigns and operational outcomes. Traffic, product-pair, repeat-purchase and journey comparisons are not supported. |
sort |
field must be a selected measure or breakdown; direction must be asc or desc. |
view |
table, line or bar. Charts require one measure. Bar requires one breakdown; line requires exactly one day, week or month breakdown. The API still returns rows. |
page / limit |
Page starts at 1, defaults to 1 and cannot exceed 100000. Limit defaults to 25; allowed range 1–250. |
Request body |
At most 32768 bytes. Unknown fields, malformed JSON and extra JSON values are rejected. |
Time, pagination and reconciliation#
The store timezone defines calendar boundaries. Today starts at local midnight. Yesterday covers the previous complete local day. The 7d, 30d and 90d presets include today and end at the time of the request. Relative ranges are reevaluated on every run. Weeks start on Monday.
Each page reports the full matching row count in total. Continue requesting pages until all rows have been read. Pages are separate queries, not a frozen export: new events, orders, refunds or a moving relative date range can change later results. Custom dates keep the calendar range fixed but do not freeze the underlying data. Use a report export job when you need a complete result from one consistent snapshot.
Sales reports exclude test and cancelled orders. Refunds affect the original order period. Merchandise refunds reduce net sales, while a shipping-only refund affects total sales without reducing merchandise net sales. Tax charged and shipping charged describe the amounts recorded on the recognized orders; they are not presented as net tax or shipping receipts. Traffic sessions are distinct within each row, so adding rows can count the same session more than once.
Gift-card purchases are issuance value, not sales revenue. Their allocated completed refunds are excluded from recognized revenue as well. Merchandise paid for with a gift card remains included. Orders containing only gift cards still contribute to the order count. Pending and failed refunds do not reduce revenue. Refunds without returned items affect total sales but cannot be attributed to merchandise returns. Cumulative recognized refund amounts are settled per order at its currency precision using ties-to-even rounding before revenue is aggregated.
Complete CSV exports#
{
"query": {
"version": 1,
"dataset": "sales",
"measures": [
"orders",
"net"
],
"dimensions": [
"day"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "day",
"direction": "asc"
},
"view": "table"
}
}
Read the returned job ID with GET /reports/exports/{jobId}. Typical states are pending, processing, completed and failed. Wait a few seconds between status requests and increase the interval while a job remains pending. Only request the download after completion. A saved report can be exported by first reading its query and passing that query to the export endpoint; later changes to the saved definition do not change the queued query.
An export contains all matching rows, up to 100000, rather than just the current preview page. A larger result fails with REPORT_EXPORT_TOO_LARGE; reduce its range or choose a coarser breakdown. One active report export is allowed per store across staff and API credentials. A competing request fails with an export-in-progress error. Export history defaults to page 1, limit 20, and returns jobs, total, page and limit.
The query period, currency and timezone are fixed when the job is accepted. The data is read from a consistent snapshot when processing starts, recorded as metadata.generated_at. A retried worker can produce a later snapshot but keeps the accepted period. Read metadata.from and metadata.to_exclusive for the evaluated boundaries. CSV columns use canonical decimal values and include currency, timezone and snapshot metadata; display preferences do not change them.
For a compared export, the accepted job also freezes metadata.comparison_from and metadata.comparison_to_exclusive. The CSV reads the current and earlier periods in the same consistent snapshot, preserves the current row order, adds {measure}_comparison, {measure}_change, and {measure}_change_rate, and records comparison_mode plus both earlier boundaries. When comparison is omitted, the existing CSV columns are unchanged.
Jobs belong to the API token or app installation that created them, not to the staff member who granted access. A different token, another app installation, and staff export history cannot read that job. Credentials for the same app installation share its jobs; reinstalling creates a different owner. Revocation, uninstallation or loss of read_reports prevents further API access. Existing signed links remain usable until their short expiry, so treat them as bearer links and do not publish them.
Completed files are available for 24 hours after completion. Status includes expires_at; after that time it includes REPORT_EXPORT_EXPIRED and no download is available. Download responses contain download_url and expires_at. Links last at most five minutes and never outlive the file’s availability. Downloading an unfinished job returns HTTP 409. Missing, inaccessible or expired files return HTTP 404. Failed jobs report REPORT_EXPORT_FAILED, REPORT_EXPORT_TOO_LARGE or REPORT_SOURCE_EXPIRED; they do not provide partial CSV files. API-created exports do not send staff notifications.
Before retrying an export start after an uncertain response, list this credential’s recent jobs and compare their query, creation time and evaluated metadata. A successful response is not a delivery notification. There is no export webhook or scheduled delivery in this API; check the job status.
Report schedules and threshold notifications belong to individual staff members in Store Admin and the mobile app. They are not Store API resources and an app cannot choose a staff recipient or inherit staff notification preferences. An integration that needs an alert can run its permitted report query on its own schedule, compare canonical decimal values itself, and deliver through channels it is separately authorized to use.
Save, update and delete#
{
"name": "Sales by day",
"query": {
"version": 1,
"dataset": "sales",
"measures": [
"orders",
"net"
],
"dimensions": [
"day"
],
"filter": {
"range": "30d"
},
"sort": {
"field": "day",
"direction": "asc"
},
"view": "table"
}
}
A saved definition contains id, name, query, revision, created_at and updated_at. Names contain 1–80 characters after trimming; the same credential cannot reuse a name without regard to letter case. A store can keep up to 100 active reports, including personal reports created by staff. The list search is a literal, case-insensitive match on the name, with at most 80 characters.
Saving stores the choices, not a frozen set of results. For an update, send the complete name and query plus the current revision. For deletion, supply revision in the URL query. If another writer changed the definition, HTTP 409 prevents an overwrite. Read the current report and reconcile your change before retrying. Deleted reports are no longer returned; deletion does not remove orders, customers or events.
Errors and retries#
HTTP status |
Meaning |
Next step |
|---|---|---|
400 |
Invalid query, body, pagination, name or revision; or the saved report limit was reached. |
Correct the request using the error message and catalog. |
401 |
Missing, expired or invalid credential context. |
Use a current credential. |
403 |
Required report scope is missing. |
Obtain the merchant's explicit permission through the token or app grant flow. |
404 |
The report or export does not exist, is not visible to this credential, or its file has expired. |
Check the report ID and its shared visibility. |
409 |
The supplied revision is stale, or an export download is not ready. |
Reload and reconcile changes; do not blindly overwrite. |
429 |
Request rate or simultaneous report capacity was exceeded. |
Honor Retry-After. Reduce concurrent report queries. |
503 |
Report data is temporarily unavailable or the query could not complete. |
Retry with backoff or reduce the requested time range. |
Errors use {"success":false,"error":{"code":"...","message":"..."}}, with details or public parameters when applicable. Read operations can be retried. Before retrying a create after an uncertain response, search for the saved definition and confirm whether it was created.
Sales fields#
Field |
Kind |
Type |
Definition |
|---|---|---|---|
orders |
Measure |
integer |
Recognized, non-cancelled orders; excludes test orders. |
gross |
Measure |
money |
Merchandise before discounts and completed merchandise refunds; excludes gift-card purchases. |
discounts |
Measure |
money |
Discounts on merchandise in recognized orders; excludes gift-card purchases. |
returns |
Measure |
money |
Completed refunds allocated to merchandise. |
net |
Measure |
money |
Merchandise after discounts and merchandise refunds. |
tax |
Measure |
money |
Tax recorded on recognized orders. |
shipping |
Measure |
money |
Shipping recorded on recognized orders. |
total |
Measure |
money |
Recognized revenue after completed refunds, including charges; excludes gift-card purchases and their allocated refunds. Merchandise paid for with gift cards is included. |
aov |
Measure |
money |
Total sales divided by recognized orders. |
day |
Breakdown |
date |
The order creation date in the store timezone. |
week |
Breakdown |
date |
Monday of the order creation week in the store timezone. |
month |
Breakdown |
date |
The order creation month in the store timezone. |
country |
Breakdown |
string |
Country from the shipping address saved with the order; empty if unavailable. |
channel |
Breakdown |
string |
The sales channel recorded with the order. |
currency |
Breakdown |
string |
The currency used by the order. Measures remain in the store base currency. |
Products fields#
Field |
Kind |
Type |
Definition |
|---|---|---|---|
units |
Measure |
integer |
Sold units less refunded units; excludes gift cards. |
gross |
Measure |
money |
Item values before discounts and merchandise refunds. |
discounts |
Measure |
money |
Discounts allocated to these items. |
returns |
Measure |
money |
Completed merchandise refunds allocated to these items. |
net |
Measure |
money |
Item values after discounts and merchandise refunds. |
cogs |
Measure |
money |
Cost snapshots for remaining units with a known cost; unavailable when no cost is known. |
margin |
Measure |
money |
Net sales less costs for items with a known cost; unavailable when no cost is known. |
cost_coverage |
Measure |
ratio |
Share of remaining units with a known cost. An explicit zero cost is known. |
product |
Breakdown |
entity |
The product saved with the order item. |
day |
Breakdown |
date |
The order creation date in the store timezone. |
country |
Breakdown |
string |
Country saved with the order's shipping address. |
Frequently bought together fields#
Field |
Kind |
Type |
Definition |
|---|---|---|---|
pair_orders |
Measure |
integer |
Distinct qualifying orders containing both products. Each unordered pair counts once per order, regardless of quantities or variants. Only pairs present in at least five orders are shown. |
product_a |
Breakdown |
entity |
The lower product ID in the unordered pair. Includes all variants of that product. |
product_b |
Breakdown |
entity |
The higher product ID in the unordered pair. Includes all variants of that product. |
Repeat purchases and replenishment fields#
Field |
Kind |
Type |
Definition |
|---|---|---|---|
customers |
Measure |
integer |
Distinct identified customers who bought the product in the selected period. Guest orders without a customer ID are excluded. |
repeat_customers |
Measure |
integer |
Distinct identified customers with at least two qualifying orders for the product in the selected period. |
repeat_rate |
Measure |
ratio |
Repeat customers divided by identified customers for the product. |
repeat_cycles |
Measure |
integer |
Qualifying purchases after a customer's first purchase of the product in the selected period. |
average_days_between_orders |
Measure |
decimal |
Average elapsed days between consecutive qualifying purchases of the product. |
median_days_between_orders |
Measure |
decimal |
Median elapsed days between consecutive qualifying purchases of the product. |
product |
Breakdown |
entity |
The product saved with the order item. All variants are combined. |
Acquisition fields#
Field |
Kind |
Type |
Definition |
|---|---|---|---|
orders |
Measure |
integer |
Recognized, non-cancelled orders; excludes test orders. |
total |
Measure |
money |
Recognized revenue after completed refunds, including charges; excludes gift-card purchases and their allocated refunds. |
aov |
Measure |
money |
Total sales divided by recognized orders. |
attributed_orders |
Measure |
integer |
Orders with a recorded campaign or referral signal in the selected attribution model. |
unattributed_orders |
Measure |
integer |
Orders without a recorded acquisition signal. A session or landing page alone is not attribution. |
attributed_total |
Measure |
money |
Total sales from orders with a recorded acquisition signal. |
unattributed_total |
Measure |
money |
Total sales from orders without a recorded acquisition signal. |
attribution_coverage |
Measure |
ratio |
Attributed orders divided by all qualifying orders; unavailable when no orders qualify. |
source |
Breakdown |
string |
Recorded utm_source for the selected touch; blank when unavailable. It is not inferred from click identifiers. |
medium |
Breakdown |
string |
Recorded utm_medium for the selected touch; blank when unavailable. |
campaign |
Breakdown |
string |
Recorded utm_campaign for the selected touch; blank when unavailable. |
campaign_id |
Breakdown |
string |
Recorded utm_id for the selected attribution touch; blank when unavailable. |
term |
Breakdown |
string |
Recorded utm_term for the selected attribution touch; blank when unavailable. |
content |
Breakdown |
string |
Recorded utm_content for the selected attribution touch; blank when unavailable. |
source_platform |
Breakdown |
string |
Recorded utm_source_platform for the selected attribution touch; blank when unavailable. |
creative_format |
Breakdown |
string |
Recorded utm_creative_format for the selected attribution touch; blank when unavailable. |
marketing_tactic |
Breakdown |
string |
Recorded utm_marketing_tactic for the selected attribution touch; blank when unavailable. |
day |
Breakdown |
date |
The order creation date in the store timezone. |
country |
Breakdown |
string |
Country saved with the order's shipping address; blank when unavailable. |
channel |
Breakdown |
string |
The sales channel recorded with the order. |
Campaign performance fields#
Field |
Kind |
Type |
Definition |
|---|---|---|---|
sessions |
Measure |
integer |
Distinct consented sessions with activity in the selected period; not unique people. |
product_sessions |
Measure |
integer |
Sessions with at least one product view in the period. |
cart_sessions |
Measure |
integer |
Sessions adding a product to the cart in the period. |
checkout_sessions |
Measure |
integer |
Sessions starting checkout in the period. |
purchase_sessions |
Measure |
integer |
Sessions with a recorded purchase in the period. Multiple purchases count once; subsequent refunds do not erase the event. |
cart_rate |
Measure |
ratio |
Cart sessions divided by active sessions. |
checkout_rate |
Measure |
ratio |
Checkout sessions divided by active sessions. |
purchase_rate |
Measure |
ratio |
Purchasing sessions divided by active sessions. This is observed session conversion, not orders divided by visitors. |
source_coverage |
Measure |
ratio |
Share of active sessions with a recorded campaign or external referral source. |
source |
Breakdown |
string |
Recorded session-entry campaign source or external referring source; blank for direct or unavailable. |
medium |
Breakdown |
string |
Recorded session-entry campaign medium or referral category. |
campaign |
Breakdown |
string |
Recorded session-entry campaign name. |
campaign_id |
Breakdown |
string |
Recorded utm_id. |
term |
Breakdown |
string |
Recorded utm_term. |
content |
Breakdown |
string |
Recorded utm_content. |
source_platform |
Breakdown |
string |
Recorded utm_source_platform. |
creative_format |
Breakdown |
string |
Recorded utm_creative_format. |
marketing_tactic |
Breakdown |
string |
Recorded utm_marketing_tactic. |
referrer |
Breakdown |
string |
External referring hostname; store-owned hosts are excluded. |
landing_page |
Breakdown |
string |
First consented observed landing path. |
day |
Breakdown |
date |
First activity in the selected period, in the store timezone. Each session belongs to one day. |
channel |
Breakdown |
string |
The session's sales channel. |
Traffic fields#
Field |
Kind |
Type |
Definition |
|---|---|---|---|
events |
Measure |
integer |
Recorded events for the selected breakdown; repeated events are included. |
sessions |
Measure |
integer |
Distinct observed sessions for each breakdown. A session may belong to several rows. |
page |
Breakdown |
string |
Visited page path. |
search |
Breakdown |
string |
Recorded search terms. |
search_zero |
Breakdown |
string |
Search terms with no results. |
country |
Breakdown |
string |
Observed country. |
city |
Breakdown |
string |
Observed city. |
referrer |
Breakdown |
string |
Recorded referring source. |
Ordered journeys fields#
Field |
Kind |
Type |
Definition |
|---|---|---|---|
sessions |
Measure |
integer |
Consented sessions completing this and every preceding step in order, within the selected time window from their first entry. |
step_rate |
Measure |
ratio |
Sessions reaching this step divided by sessions reaching the preceding step. Unavailable when none reached the preceding step. |
overall_rate |
Measure |
ratio |
Sessions reaching this step divided by sessions entering the journey. Unavailable when no sessions entered. |
recorded_events |
Measure |
integer |
All recorded non-test human or commerce events of this step's type in the selected period, including repeated and unlinked events. |
linked_events |
Measure |
integer |
Recorded events of this type carrying a session ID and analytics consent. These are events, not distinct sessions or completed steps. |
linkage_coverage |
Measure |
ratio |
Events with a session ID and analytics consent divided by recorded events of this type. Unavailable when no events were recorded. |
step |
Breakdown |
integer |
One-based position in the configured journey. Read query.journey.steps for its event type. |
Order operations fields#
Field |
Kind |
Type |
Definition |
|---|---|---|---|
orders |
Measure |
integer |
All non-test orders created in the period, including unpaid and cancelled orders. Archived orders remain included. |
cancelled_orders |
Measure |
integer |
Orders from the selected creation period that are currently cancelled. |
cancellation_rate |
Measure |
ratio |
Currently cancelled orders divided by all non-test orders created in the period. |
refunded_orders |
Measure |
integer |
Orders from the selected creation period whose current financial status is refunded. |
partially_refunded_orders |
Measure |
integer |
Orders from the selected creation period whose current financial status is partially refunded. |
day |
Breakdown |
date |
The order creation date. In the store timezone. |
week |
Breakdown |
date |
Monday of the record creation week in the store timezone. |
month |
Breakdown |
date |
The record creation month in the store timezone. |
country |
Breakdown |
string |
Country saved with the order; blank when unavailable. |
channel |
Breakdown |
string |
The sales channel recorded with the order. |
cancellation_status |
Breakdown |
string |
Current cancellation state: cancelled or not_cancelled. This is independent of the merchant's workflow status. |
Payment outcomes fields#
Field |
Kind |
Type |
Definition |
|---|---|---|---|
payment_records |
Measure |
integer |
Payment records created in the period for non-test orders. Split tenders and retries can create several records per order. Includes cancelled orders; not a count of checkout attempts. |
payment_orders |
Measure |
integer |
Distinct orders represented by these payment records. An order can appear in several breakdown rows. |
captured_payments |
Measure |
integer |
Records whose current status is captured. Records subsequently refunded belong to their current refund status instead. |
failed_payments |
Measure |
integer |
Records whose current status is failed. |
pending_payments |
Measure |
integer |
Records whose current status is pending or authorized. |
refunded_payments |
Measure |
integer |
Records whose current status is refunded or partially_refunded. |
unknown_payments |
Measure |
integer |
Records with a missing or unrecognized current payment status. |
payment_failure_share |
Measure |
ratio |
Currently failed payment records divided by all payment records created in the period. This is not a checkout failure rate. |
day |
Breakdown |
date |
The payment record creation date. In the store timezone. |
week |
Breakdown |
date |
Monday of the record creation week in the store timezone. |
month |
Breakdown |
date |
The record creation month in the store timezone. |
country |
Breakdown |
string |
Country saved with the order; blank when unavailable. |
channel |
Breakdown |
string |
The sales channel recorded with the order. |
payment_status |
Breakdown |
string |
Current recorded payment status; unrecognized or missing values are unknown. |
provider |
Breakdown |
string |
Recorded provider identifier; blank when unavailable. |
method |
Breakdown |
string |
Recorded payment method identifier. |
Refund outcomes fields#
Field |
Kind |
Type |
Definition |
|---|---|---|---|
refund_records |
Measure |
integer |
Refund records created in the period for non-test orders, including cancelled orders. Multiple partial refunds count separately. |
completed_refunds |
Measure |
integer |
Refund requests whose settlement and order effects are complete. |
pending_refunds |
Measure |
integer |
Refund requests awaiting settlement or completion of their order effects. |
failed_refunds |
Measure |
integer |
Refund requests whose recorded settlement failed. |
unknown_refunds |
Measure |
integer |
Refund requests without a recognized settlement outcome. |
completed_refund_amount |
Measure |
money |
Sum of saved base-currency amounts for completed refunds with known non-negative amounts. Includes merchandise and other charges. Unavailable if no completed amount is known; read amount coverage alongside it. |
refund_amount_coverage |
Measure |
ratio |
Completed refund requests with a known non-negative base-currency amount divided by all completed requests. A saved zero is known; unavailable when no refunds are complete. |
day |
Breakdown |
date |
The refund request creation date. In the store timezone. |
week |
Breakdown |
date |
Monday of the record creation week in the store timezone. |
month |
Breakdown |
date |
The record creation month in the store timezone. |
country |
Breakdown |
string |
Country saved with the order; blank when unavailable. |
channel |
Breakdown |
string |
The sales channel recorded with the order. |
refund_status |
Breakdown |
string |
Current completion outcome: completed, pending, failed or unknown. |
method |
Breakdown |
string |
Recorded refund method; missing or unrecognized methods are unknown. |
Fulfilment outcomes fields#
Field |
Kind |
Type |
Definition |
|---|---|---|---|
fulfillment_records |
Measure |
integer |
Fulfilment records created in the period for non-test orders. Partial fulfilments count separately; cancelled orders remain included. |
fulfillment_orders |
Measure |
integer |
Distinct orders represented by these fulfilment records. An order can appear in several breakdown rows. |
pending_fulfillments |
Measure |
integer |
Fulfilments whose current status is pending. |
in_transit_fulfillments |
Measure |
integer |
Fulfilments currently in transit, out for delivery, or awaiting another attempt after a failed delivery attempt. |
delivered_fulfillments |
Measure |
integer |
Fulfilments whose current status is delivered. |
returning_fulfillments |
Measure |
integer |
Fulfilments currently returning to the sender. |
returned_fulfillments |
Measure |
integer |
Fulfilments returned to the sender. |
failed_fulfillments |
Measure |
integer |
Fulfilments currently failed, lost, damaged, or destroyed. |
cancelled_fulfillments |
Measure |
integer |
Fulfilments whose current status is cancelled. |
tracking_coverage |
Measure |
ratio |
Fulfilments with a non-empty tracking number divided by all fulfilment records. |
day |
Breakdown |
date |
The fulfilment record creation date. In the store timezone. |
week |
Breakdown |
date |
Monday of the record creation week in the store timezone. |
month |
Breakdown |
date |
The record creation month in the store timezone. |
country |
Breakdown |
string |
Country saved with the order; blank when unavailable. |
channel |
Breakdown |
string |
The sales channel recorded with the order. |
fulfillment_status |
Breakdown |
string |
Current canonical fulfilment status. |
carrier |
Breakdown |
string |
Carrier saved with the fulfilment; blank when unavailable. |