Authentication
API tokens are created in workspace settings by an owner or admin on a plan with API access. Tokens are shown once, scoped to one organization and shop, and checked on every request for billing, entitlements, token status, expiry, scope, Shopify readiness, and daily quota.
Authorization: Bearer rda_live_api_tok_...| Scope | Grants |
|---|---|
| read:dashboard | Selector discovery, summaries, and leaderboards. |
| read:reports | The expanded report model and time series. |
| read:exports | CSV export (also requires the data_export entitlement). |
| read:alerts | The workspace alert and notification feed. |
Endpoints
GET /api/v1/entities
Enumerate the catalog (SKUs, products, product groups) with cursor pagination, or search it with a q term. Returns customer-safe selectors for the other endpoints.
GET /api/v1/summary
Sold units, returned units, and cohort return rate for one selected entity over a month range.
GET /api/v1/report
The expanded report view model: trends, return reasons, refunds, timing buckets, and lifecycle coverage.
GET /api/v1/timeseries
The monthly return-rate series for one entity: one row per order-cohort month with sold units, returned units, and rate.
GET /api/v1/leaderboards/return-rate
Rank SKUs by highest return rate over a trailing month or year, with optional min-rate, min-sold-units, and vendor filters.
GET /api/v1/leaderboards/return-cost
Rank SKUs by returns cost (refund subtotal plus label spend where usable) over a cohort month range, with min-cost and vendor filters.
GET /api/v1/alerts
Poll the workspace alert feed: watchlist spikes, backfill completions, connection staleness, and report-ready events, with a since floor and keyset cursor.
GET /api/v1/export/report.csv
A machine-oriented CSV with summary, trend, return reason, refund, timing, label cost, and lifecycle rows.
POST /api/v1/mcp
Model Context Protocol server wrapping the endpoints above as tools, so AI agents can query the workspace directly. See the MCP guide.
Examples
Discover selectors
curl -sS "https://app.returnsintel.com/api/v1/entities?q=essential&type=sku&limit=10" \
-H "Authorization: Bearer $RETURNS_API_TOKEN" \
-H "X-Request-ID: ri-docs-entities-001"Read cohort summary
curl -sS "https://app.returnsintel.com/api/v1/summary?sku=TSH-100-BLK-M&start_month=2026-01&end_month=2026-03&window=primary" \
-H "Authorization: Bearer $RETURNS_API_TOKEN"Rank worst SKUs by return rate
curl -sS "https://app.returnsintel.com/api/v1/leaderboards/return-rate?period=year&min_return_rate=0.3&limit=50" \
-H "Authorization: Bearer $RETURNS_API_TOKEN"Pull one SKU's 12-month trend
curl -sS "https://app.returnsintel.com/api/v1/timeseries?sku=TSH-100-BLK-M&start_month=2025-07&end_month=2026-06&window=primary" \
-H "Authorization: Bearer $RETURNS_API_TOKEN"Poll the alert feed
curl -sS "https://app.returnsintel.com/api/v1/alerts?since=2026-07-01T00:00:00Z&limit=50" \
-H "Authorization: Bearer $RETURNS_API_TOKEN"Download report CSV
curl -L "https://app.returnsintel.com/api/v1/export/report.csv?product_gid=gid://shopify/Product/123&start_month=2026-01&end_month=2026-03&window=lifetime" \
-H "Authorization: Bearer $RETURNS_API_TOKEN" \
-o returns-report.csvPagination
/api/v1/entities without a q term enumerates the full catalog behind an opaque cursor. Read meta.next_cursor and pass it back as cursor on the next request until it is null, and you have synced every SKU, product, and product group. With a q term the endpoint is a ranked type-ahead instead (top matches, no pagination). limit accepts 1 to 100 (default 20).
/api/v1/alerts paginates the same way: poll with a since timestamp floor, or follow meta.next_cursor for keyset pagination through older notifications.
Cursors are opaque; pass the value back verbatim and do not construct or parse them. Leaderboards return a single ranked page sized by limit.
# Sync the whole catalog by following the cursor
cursor=""
while : ; do
resp=$(curl -sS "https://app.returnsintel.com/api/v1/entities?limit=100&cursor=$cursor" \
-H "Authorization: Bearer $RETURNS_API_TOKEN")
echo "$resp" | jq -c '.data[]'
cursor=$(echo "$resp" | jq -r '.meta.next_cursor // empty')
[ -z "$cursor" ] && break
doneConnect an AI agent (MCP)
The same data is available to AI agents through a Model Context Protocol server. Point Claude, Cursor, ChatGPT, or any MCP client at /api/v1/mcp and ask questions like “what were my worst SKUs last month?” against a workspace.
Metric Contract
Return rate is cohort-based: units sold for the selected entity in an order month form the denominator, and units from that same order-month cohort classified as returned within the selected observation window form the numerator.
Supported windows are primary, 30d, 90d, and lifetime. The default decision window is the workspace primary return window, which starts at 30 days unless an owner/admin changes it. Lifetime is lifetime-to-date and is open ended as of the response date in the reporting data.
Order-cohort months use YYYY-MM. Cohort months are bucketed in UTC. Incomplete finite-window cohorts are excluded unless include_incomplete=true is sent intentionally.
Shopify-native return requests count only after Shopify marks the return CLOSED. REQUESTED, OPEN, declined, and canceled requests do not count unless a SKU-attributable refund independently supports the return.
Freshness And Readiness
Returns Intelligence syncs tenant data through protected backend reconciliation jobs, so API numbers can trail the store. Every JSON response carries a freshness object in meta: data_updated_at is the “as of” timestamp for the numbers, and each connected source reports whether it is stale. A 409 (not_ready) response means the shop is still installing, reconnecting, or backfilling; retry after the next sync or contact support with the request id.
Responses And Errors
Errors are a nested JSON object with a stable machine-readable code and a human-readable message. Branch on code, not on message (wording may change).
{ "error": { "code": "forbidden", "message": "Forbidden" } }| Code | HTTP | Meaning |
|---|---|---|
| invalid_request | 400 | Invalid selector, date range, window, or pagination cursor. |
| unauthorized | 401 | Missing, malformed, expired, revoked, or unknown token. |
| forbidden | 403 | Missing scope, inactive billing, or missing entitlement. |
| not_ready | 409 | Tenant data is not ready for API reads. |
| rate_limited | 429 | Daily API quota exceeded. |
| internal_error | 500 | Unexpected backend error, logged server-side. |
Every response includes X-Returns-API-Version and X-Request-ID. Plans with a finite daily quota also receive X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset after authentication and quota evaluation.
Security Guidance
Use tokens only from server-side systems.
Create least-privilege tokens and rotate them regularly.
Treat CSV exports as sensitive tenant analytics.
Do not use dashboard or internal routes as customer APIs.