Skip to content

Ecommerce API

The ecommerce API lets you send purchase, cart, and product events, then query revenue metrics, attribution, and cohort data. Event ingestion accepts publishable or secret keys. Query endpoints require a secret key.

All GET ecommerce query endpoints accept the same date range parameters as the Analytics API:

ParamDescription
daysNumber of days to look back. Defaults to 30. Clamped to your plan’s retention limit.
startISO date (e.g. 2026-01-01). Used with end.
endISO date (e.g. 2026-01-31). Used with start.

Send one ecommerce event.

POST /v1/api/analytics/ecommerce/track

Auth: Any valid API key (publishable or secret)

Request body:

{
"event_type": "purchase",
"transaction_id": "order_456",
"revenue": 49.99,
"currency": "USD",
"user_id": "user_123",
"coupon_code": "SAVE10",
"discount": 5.00,
"shipping": 4.99,
"tax": 3.75,
"items": [
{
"item_id": "sku_1",
"item_name": "T-Shirt",
"item_category": "Apparel",
"item_brand": "MyBrand",
"item_variant": "Red / L",
"price": 24.99,
"quantity": 2,
"currency": "USD"
}
],
"properties": {
"campaign": "spring-sale",
"source": "email"
}
}
Event typeRequired fieldsDescription
view_itemitemsUser views a product page
add_to_cartitemsItem added to cart
remove_from_cartitemsItem removed from cart
add_to_wishlistitemsItem added to wishlist
view_cart(none)User views their cart
add_payment_info(none)Payment method entered
begin_checkout(none)Checkout flow started
purchasetransaction_id, revenueOrder completed
refundtransaction_id, revenueOrder refunded
search(none)Product search performed (pass search_term in properties)
share(none)Product shared (pass item_id in properties)
rate(none)Product rated (pass item_id, rating in properties)
spend_creditsrevenueLoyalty credits redeemed
FieldTypeRequiredDescription
event_typestringYesOne of the 13 event types above
transaction_idstringFor purchase/refundUnique order identifier. Used for deduplication.
revenuenumberFor purchase/refund/spend_creditsTotal revenue amount
currencystringNoISO 4217 currency code (e.g. USD, EUR). Defaults to your appspace’s base currency.
user_idstringNoYour application’s user ID. Required for attribution.
cart_idstringNoCart session ID. SDKs manage this automatically.
coupon_codestringNoApplied coupon or promo code
discountnumberNoDiscount amount
shippingnumberNoShipping cost
taxnumberNoTax amount
itemsarrayFor item eventsArray of item objects (see below)
propertiesobjectNoAdditional key-value pairs (string values)
FieldTypeRequiredDescription
item_idstringYesProduct SKU or identifier
item_namestringNoProduct name
item_categorystringNoProduct category
item_brandstringNoBrand name
item_variantstringNoVariant (e.g. “Red / L”)
item_list_namestringNoList or collection name (e.g. “Search Results”)
item_list_idstringNoList identifier
item_image_urlstringNoProduct image URL
pricenumberNoUnit price
quantitynumberNoQuantity (defaults to 1)
currencystringNoItem-level currency
coupon_codestringNoItem-level coupon
discountnumberNoItem-level discount

Response 200:

{ "ok": true }

Errors:

StatusError
400event_type is required
400Invalid ecommerce event_type
400transaction_id is required for purchase events
400revenue is required for purchase events
403Ecommerce events are not available on the free tier
429Ecommerce event quota exceeded

Events are automatically checked against fraud rules (bot detection, impossible revenue, velocity limits, currency restrictions). Flagged events (severity 1) are stored but marked. Blocked events (severity 2) are silently rejected with { "ok": true } to avoid leaking detection signals.

Purchase and refund events are deduplicated by transaction_id. If the same transaction ID is sent twice within 24 hours, the second event is silently ignored. This prevents revenue double-counting from network retries.


Send up to 100 ecommerce events in a single request. This is the primary endpoint used by SDKs.

POST /v1/api/analytics/ecommerce/batch

Auth: Any valid API key (publishable or secret)

Request body:

{
"events": [
{
"event_type": "add_to_cart",
"items": [{ "item_id": "sku_1", "item_name": "T-Shirt", "price": 24.99 }],
"user_id": "user_123"
},
{
"event_type": "purchase",
"transaction_id": "order_456",
"revenue": 49.99,
"currency": "USD",
"user_id": "user_123",
"items": [{ "item_id": "sku_1", "price": 24.99, "quantity": 2 }]
}
]
}

Response 200:

{
"ok": true,
"accepted": 2
}

If some events are invalid, they are skipped:

{
"ok": true,
"accepted": 1,
"errors": [
"events[0]: transaction_id is required for purchase events"
]
}

Errors:

StatusError
400events array is required and must not be empty
400Maximum 100 events per batch
403Ecommerce events are not available on the free tier

Get aggregate revenue metrics for the date range.

GET /v1/api/analytics/ecommerce/overview

Auth: Secret key required

Response 200:

{
"total_revenue": 12450.00,
"net_revenue": 11200.00,
"total_orders": 245,
"total_refunds": 12,
"refund_amount": 1250.00,
"avg_order_value": 50.82,
"total_items_sold": 512,
"cart_abandonment_rate": 68.5,
"add_to_cart_rate": 32.1,
"days": 30
}

Get daily revenue grouped by date.

GET /v1/api/analytics/ecommerce/revenue-timeseries

Auth: Secret key required

Response 200:

{
"series": [
{ "date": "2026-01-01", "revenue": 450.00, "orders": 8 },
{ "date": "2026-01-02", "revenue": 620.00, "orders": 12 }
],
"days": 30
}

Get step-by-step conversion funnel from product views to purchase.

GET /v1/api/analytics/ecommerce/funnel

Auth: Secret key required

Response 200:

{
"steps": [
{ "name": "view_item", "count": 5000, "percentage": 100 },
{ "name": "add_to_cart", "count": 1600, "percentage": 32.0 },
{ "name": "view_cart", "count": 1200, "percentage": 75.0 },
{ "name": "begin_checkout", "count": 800, "percentage": 66.7 },
{ "name": "add_payment_info", "count": 600, "percentage": 75.0 },
{ "name": "purchase", "count": 400, "percentage": 66.7 }
],
"days": 30
}

Each percentage is relative to the previous step (except view_item, which is always 100).


Get best-selling products by revenue.

GET /v1/api/analytics/ecommerce/top-products

Auth: Secret key required

Query parameters:

ParamDefaultMaxDescription
limit20100Number of products to return

Response 200:

{
"products": [
{ "item_id": "sku_1", "item_name": "T-Shirt", "revenue": 2499.00, "quantity": 100, "orders": 85 },
{ "item_id": "sku_2", "item_name": "Hoodie", "revenue": 1899.00, "quantity": 38, "orders": 35 }
],
"days": 30
}

Get revenue breakdown by campaign, source, and medium.

GET /v1/api/analytics/ecommerce/revenue-by-channel

Auth: Secret key required

Response 200:

{
"channels": [
{
"campaign": "spring-sale",
"source": "email",
"medium": "newsletter",
"revenue": 4500.00,
"orders": 90,
"conversion_rate": 3.2
}
],
"days": 30
}

Get revenue and usage stats per coupon code.

GET /v1/api/analytics/ecommerce/revenue-by-coupon

Auth: Secret key required

Response 200:

{
"coupons": [
{ "coupon_code": "SAVE10", "revenue": 1200.00, "orders": 40, "avg_discount": 12.50 }
],
"days": 30
}

Get revenue breakdown by device type.

GET /v1/api/analytics/ecommerce/revenue-by-device

Auth: Secret key required

Response 200:

{
"devices": [
{ "device_type": "mobile", "revenue": 8200.00, "orders": 165 },
{ "device_type": "desktop", "revenue": 4250.00, "orders": 80 }
],
"days": 30
}

Get revenue breakdown by operating system platform.

GET /v1/api/analytics/ecommerce/revenue-by-platform

Auth: Secret key required

Response 200:

{
"platforms": [
{ "platform": "ios", "revenue": 6500.00, "orders": 130 },
{ "platform": "android", "revenue": 3900.00, "orders": 78 },
{ "platform": "web", "revenue": 2050.00, "orders": 37 }
],
"days": 30
}

Get revenue breakdown by country.

GET /v1/api/analytics/ecommerce/revenue-by-country

Auth: Secret key required

Response 200:

{
"countries": [
{ "country": "US", "revenue": 9200.00, "orders": 185 },
{ "country": "GB", "revenue": 2100.00, "orders": 42 }
],
"days": 30
}

Get cart abandonment metrics.

GET /v1/api/analytics/ecommerce/cart-abandonment

Auth: Secret key required

Response 200:

{
"abandonment_rate": 68.5,
"abandoned_carts": 520,
"abandoned_revenue": 32000.00,
"completed_carts": 238,
"days": 30
}

Get revenue attribution by campaign with configurable attribution model and window.

GET /v1/api/analytics/ecommerce/attribution

Auth: Secret key required

Query parameters:

ParamDefaultOptionsDescription
modellast_clicklast_click, linear, time_decayAttribution model
window307, 14, 30, 60, 90Attribution window in days

Response 200:

{
"attributed": [
{
"campaign": "spring-sale",
"source": "email",
"medium": "newsletter",
"revenue": 4500.00,
"orders": 90,
"pct_of_total": 36.1
}
],
"unattributed": {
"revenue": 2100.00,
"orders": 45
},
"model": "last_click",
"window_days": 30
}
  • Last Click: 100% of revenue credit goes to the last campaign the user clicked before purchasing.
  • Linear: Revenue is split equally across all campaigns the user clicked within the attribution window.
  • Time Decay: More recent clicks receive proportionally more credit, with older clicks decaying exponentially.

Get a cohort matrix showing revenue by acquisition month across subsequent months.

GET /v1/api/analytics/ecommerce/cohorts

Auth: Secret key required

Query parameters:

ParamDefaultDescription
months6Number of cohort months to include

Response 200:

{
"cohorts": [
{
"month": "2026-01",
"users": 120,
"revenue_by_month": {
"0": 3200.00,
"1": 1800.00,
"2": 900.00
}
},
{
"month": "2025-12",
"users": 95,
"revenue_by_month": {
"0": 2800.00,
"1": 1500.00,
"2": 750.00,
"3": 400.00
}
}
],
"avg_ltv": 82.50,
"total_purchasing_users": 580
}

Each revenue_by_month key is the number of months after the user’s first purchase. Month 0 is the acquisition month.


Get a single user’s ecommerce event history.

GET /v1/api/analytics/ecommerce/user-journey?user_id=user_123

Auth: Secret key required

Query parameters:

ParamRequiredDescription
user_idYesThe user ID to look up

Response 200:

{
"events": [
{
"event_type": "view_item",
"timestamp": "2026-01-15T10:30:00Z",
"items": [{ "item_id": "sku_1", "item_name": "T-Shirt" }]
},
{
"event_type": "add_to_cart",
"timestamp": "2026-01-15T10:31:00Z",
"items": [{ "item_id": "sku_1" }]
},
{
"event_type": "purchase",
"timestamp": "2026-01-15T10:35:00Z",
"transaction_id": "order_456",
"revenue": 49.99
}
],
"user_id": "user_123"
}

Delete all analytics events for a specific user. This removes the user’s data from all ClickHouse tables (events, event_items, event_properties).

DELETE /v1/api/analytics/user/:userId

Auth: Secret key required

URL parameters: :userId is the user ID to delete.

Response 200:

{ "ok": true, "deleted_user_id": "user_123" }

The deletion is asynchronous. Data is typically removed within minutes.


All revenue values are automatically converted to your appspace’s base currency using live exchange rates (updated hourly from Open Exchange Rates, 200+ currencies supported).

If a purchase event does not include a currency field, the appspace’s base currency is used as the default. Configure your base currency in Appspace Settings > Ecommerce.

Zero-decimal currencies (JPY, KRW, VND, etc.) are handled automatically. Revenue is stored internally in cents for precision.