The Analytics API gives you programmatic, read-only access to your store’s analytics: raw data tables (orders, claims) and pre-computed metrics (attach rate, claim rate, and more). Use it to feed OrderProtection data into your own dashboards, BI tools, or reports.
Authentication
Every request needs a Bearer token carrying the analytics:read scope. Two token types work:
curl -X GET "https://api.production.orderprotection.com/v1/analytics/metrics/order_attach_rate/timeseries?granularity=month" \
-H "Authorization: Bearer op_pat_8508b7432c45f79827460fea_ajhnyH..."
A token without the analytics:read scope receives 403 Forbidden. Requesting a store outside your token’s authorized set receives 403 with code STORE_OUT_OF_SCOPE.
Store scoping
Results are always limited to your account and the stores your token is authorized for. By default an endpoint returns data for all of the token’s authorized stores. Pass store_ids to narrow to specific stores:
?store_ids=store_abc123&store_ids=store_def456
The store_ids you receive back in the response meta reflect the exact scope that was applied.
Data freshness
Analytics tables are rebuilt on a batch schedule (roughly every 8 hours), so data is not real-time and can be up to ~8 hours behind your live store data. Every response includes a data_freshness_at timestamp in its meta block — the time the underlying table was last rebuilt by the batch job (not a per-row timestamp):
"meta": { "data_freshness_at": "2026-07-08T06:00:00.000Z" }
Tables
Tables return raw, row-level records.
No PII is exposed. Each table has a fixed allowlist of safe columns; personally identifiable fields (customer name, email, etc.) are never included and cannot be requested. The fields parameter can only ever narrow to columns within that allowlist — asking for a field outside it is dropped, and a request for only disallowed fields returns 400 INVALID_FIELDS.
List tables
Returns the available tables, each with its selectable columns.
{
"data": [
{ "key": "orders", "safeColumns": ["order_id", "store_id", "created_at", "..."], "sortColumns": ["created_at", "order_total"] },
{ "key": "claims", "safeColumns": ["claim_id", "order_id", "claim_state", "..."], "sortColumns": ["created_at", "updated_at"] }
],
"meta": { "data_freshness_at": "2026-07-08T06:00:00.000Z" }
}
Get rows
GET /v1/analytics/tables/{name}
| Parameter | Description |
|---|
store_ids | Repeatable. Restrict to specific stores within your scope. |
from | Start of the time window (ISO 8601). Defaults to 30 days ago. |
to | End of the time window (ISO 8601). Defaults to now. |
fields | Comma-separated subset of the table’s columns. Defaults to all safe columns. |
limit | Page size. Defaults to 1000, maximum 10000. |
cursor | Opaque cursor from a previous response’s meta.next_cursor. |
{
"data": [
{ "order_id": "ord_...", "store_id": "store_abc123", "created_at": "2026-07-01T12:00:00.000Z", "order_total": 84.99, "currency": "USD" }
],
"meta": {
"data_freshness_at": "2026-07-08T06:00:00.000Z",
"store_ids": ["store_abc123"],
"next_cursor": "eyJ2Ijpbl...",
"has_more": true
}
}
To page through results, resend the request with cursor set to meta.next_cursor until has_more is false.
Available tables
| Table | Columns |
|---|
orders | order_id, store_id, account_id, policy_id, created_at, order_total, currency, platform, source_order_number |
claims | claim_id, order_id, store_id, account_id, claim_type, claim_state, claim_category, created_at, updated_at |
addresses | order_id, claim_id, customer_id, store_id, account_id, city, state, state_abr, zip_code, country, country_abr, latitude, longitude, address_type, order_date, claim_date |
addresses is geo-only. Customer identity fields — name, email, phone, and street lines (address1/address2) — are excluded and cannot be requested. Coordinates are rounded to ~1.1 km (2 decimal places), so latitude/longitude support regional mapping but never pinpoint an individual address. Its time column is order_date.
Metrics
Metrics are pre-defined aggregations computed at query time over the batch-refreshed tables. Query them as a time series or fetch the latest single value.
List metrics
GET /v1/analytics/metrics
{
"data": [
{ "key": "order_attach_rate", "description": "Share of orders that carry an Order Protection policy.", "granularitySupport": ["day", "week", "month", "quarter", "year"] }
],
"meta": { "data_freshness_at": "2026-07-08T06:00:00.000Z" }
}
Time series
GET /v1/analytics/metrics/{key}/timeseries
| Parameter | Description |
|---|
store_ids | Repeatable. Restrict to specific stores within your scope. |
from | Start of the window (ISO 8601). Defaults to 30 days ago. |
to | End of the window (ISO 8601). Defaults to now. Windows are capped at 366 days. |
granularity | Bucket size: day, week, month, quarter, or year. |
group_by | Set to store_id to return one series per store instead of an aggregate. |
{
"data": [
{ "bucket": "2026-05-01T00:00:00.000Z", "value": 0.3712 },
{ "bucket": "2026-06-01T00:00:00.000Z", "value": 0.3302 }
],
"meta": {
"data_freshness_at": "2026-07-08T06:00:00.000Z",
"store_ids": ["store_abc123"],
"granularity": "month"
}
}
When group_by=store_id, each data point also includes a store_id field.
Latest value
GET /v1/analytics/metrics/{key}
Returns the single most recent value for the metric.
{
"data": { "key": "order_attach_rate", "value": 0.3302 },
"meta": {
"data_freshness_at": "2026-07-08T06:00:00.000Z",
"store_ids": ["store_abc123"],
"from": "2026-06-08T00:00:00.000Z",
"to": "2026-07-08T00:00:00.000Z"
}
}
Available metrics
| Metric | Description |
|---|
order_attach_rate | Share of orders that carry an Order Protection policy. |
protected_order_count | Count of protected orders (distinct policies). |
claim_count | Count of claims filed. |
claim_rate | Claims per protected order, bucketed by granularity. |
Limits
| Limit | Value |
|---|
| Default time window | 30 days |
| Maximum metric window | 366 days |
| Default table page size | 1000 rows |
| Maximum table page size | 10000 rows |
For pulls larger than these limits, page through tables with the cursor parameter, or narrow your from/to window and combine the results.