Skip to main content
POST
Required scope: analytics:read Use this to compare customers by when you acquired them. For example, check whether customers acquired in January have spent more per head after three months than customers acquired in March, or watch how many of each month’s new customers order again.

Request rules

  • Send timezone. The schema marks it optional, but a request without it fails with 500 and the message Timezone is required.
  • measures is a list of plain measure id strings, limited to the cohort measures listed below. Run an analytics query takes objects instead.
  • granularity is week, month, or year. Each period in dateRange becomes one cohort.
  • Only orders.* filter fields work here. A malformed filters tree returns 400, but a field that isn’t valid for cohort analysis returns 500 with the reason in message. Check fields with List filter fields (cohort_analysis).
  • Saved order settings aren’t applied for you. Pass the object from Get order settings as orderSettings to match the web app.

Reading the response

  • results has one entry. Its data.primary holds one row per cohort and period pair: cohort_month is the cohort’s first day and order_month is the period the values cover, both as YYYY-MM-DD. The keys keep the _month names for every granularity. Only periods on or after the cohort’s start appear.
  • Each measure is keyed by its id. Revenue, CM1, and CM2 measures are cumulative per customer: the cohort’s total since its first period divided by its customer count.
  • A period with no orders repeats that cohort’s previous values, so cumulative figures never drop back to zero.
  • Measure values can come back as numeric strings (for example "84.37"). Parse them before doing math.
  • measureDetails is always empty, and there’s no comparison period.
  • The orders.lifetime_value_90, _180, and _365 measures extend the periods covered by 90, 180, or 365 days past dateRange.end.

Authorizations

x-api-key
string
header
required

Your Upstack API key. Starts with upstack_.

x-pixel-id
string
header
required

The pixel id the request targets.

Body

application/json
pixelId
string
required

Must match the x-pixel-id header.

granularity
enum<string>
required

Cohort period length. Each period in dateRange is one cohort.

Available options:
week,
month,
year
measures
enum<string>[]
required

Cohort-specific measure ids. Pass measure ids as strings (this endpoint differs from /api/query, which takes objects with pacing).

Maximum array length: 30
Available options:
orders.ltv_cohort_gross_revenue,
orders.ltv_cohort_net_revenue,
orders.customers_cohort,
orders.avg_order_value_cohort,
orders.cohort_retention_percent,
orders.cohort_cm1,
orders.cohort_cm2,
orders.lifetime_value_90,
orders.lifetime_value_180,
orders.lifetime_value_365
dateRange
object
required

The cohorts to include. Customers are grouped by the period of their first order.

timezone
string

IANA timezone (e.g. America/New_York) used to bucket orders into periods. Required in practice: a request without it fails with 500.

Example:

"America/New_York"

currency
string
default:USD

ISO 4217 code to convert cohort money values to (revenue, AOV, CM1/CM2). Each amount converts at the rate for the day the order occurred. Defaults to USD when omitted — if your store sells in another currency, pass this explicitly.

filters
All of (and) · object

Filter applied to the orders in the cohort. Only orders.* fields are valid here; any other field fails with 500.

orderSettings
object

Order settings to apply to this query. The query endpoints don't read the account's saved order settings, so pass them here to match the web app's numbers. The orderSettings object returned by Get order settings can be passed as-is.

Response

Cohort results.

results
object[]
required

Query results. A cohort analysis always returns exactly one entry.