Run a cohort analysis for customer LTV and retention
Group customers by the week, month, or year of their first order and track cumulative revenue per customer, retention, AOV, and contribution margin over time.
Required scope:analytics:readUse 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.
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.
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.
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.
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.
Query results. A cohort analysis always returns exactly one entry.
Show child attributes
Was this page helpful?
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Upstack Data","colors":{"primary":"#4230b4","light":"#6366F1","dark":"#322484"},"logo":{"light":"https://mintcdn.com/upstackdata-afbed50d/40dgTTn1PLjePhJa/logo/light.svg?fit=max\u0026auto=format\u0026n=40dgTTn1PLjePhJa\u0026q=85\u0026s=598c05fb87860ddc1b6b7640b41e136c","dark":"https://mintcdn.com/upstackdata-afbed50d/40dgTTn1PLjePhJa/logo/dark.svg?fit=max\u0026auto=format\u0026n=40dgTTn1PLjePhJa\u0026q=85\u0026s=4ffdf28479b596176b69034675d783b0","href":"https://docs.upstackdata.com/get-started/overview"},"favicon":"https://mintcdn.com/upstackdata-afbed50d/a7q81tQDxtvowAUn/favicon.svg?fit=max\u0026auto=format\u0026n=a7q81tQDxtvowAUn\u0026q=85\u0026s=4e6cad1d3845d8fe1e1f8fb54b430a3f","appearance":{"default":"light","strict":true},"navbar":{"links":[{"href":"https://docs.upstackdata.com/troubleshooting/support","label":"Support"}],"primary":{"type":"button","label":"Dashboard","href":"https://app.upstackdata.com"}},"footer":{"socials":{"x":"https://x.com/upstackdata","linkedin":"https://linkedin.com/company/upstackdata"},"links":[{"header":"Product","items":[{"label":"Website","href":"https://www.upstackdata.com"},{"label":"Pricing","href":"https://www.upstackdata.com/pricing"},{"label":"Dashboard","href":"https://app.upstackdata.com"}]},{"header":"Resources","items":[{"label":"Documentation","href":"https://docs.upstackdata.com/get-started/overview"},{"label":"All troubleshooting guides","href":"https://docs.upstackdata.com/troubleshooting/overview"},{"label":"Blog","href":"https://www.upstackdata.com/blog"}]},{"header":"Support","items":[{"label":"Contact Support","href":"https://docs.upstackdata.com/troubleshooting/support"},{"label":"Install on Shopify","href":"https://docs.upstackdata.com/quickstart/install-on-shopify"},{"label":"Troubleshooting","href":"https://docs.upstackdata.com/troubleshooting/overview"}]},{"header":"Legal","items":[{"label":"Terms of Service","href":"https://www.upstackdata.com/terms"}]}]},"seo":{},"fonts":{"family":"Inter"},"integrations":{"intercom":{"appId":"y2qnvi2j"}},"contextual":{"options":["copy","view","claude"],"display":"header"},"metadata":{"timestamp":false},"styling":{"latex":true},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"upstackdata-afbed50d","hasAudioNarration":false,"actualSubdomain":"upstackdata-afbed50d","customDomains":["docs.upstackdata.com"],"gitSource":{"type":"github","owner":"upstack-data","repo":"upstack-doc-site","deployBranch":"release/dev2","isPrivate":true,"contentDirectory":"","mountPath":"","label":""},"feedback":{"thumbs":true},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6af205e1130c63682a17c260","clientVersion":"0.0.4111","searchFilterCounts":[{"language":"default","tag":"Metrics","count":803},{"language":"default","tag":"METRICS","count":803},{"language":"default","tag":"Orders","count":271},{"language":"default","tag":"Advertising","count":268},{"language":"default","tag":"Funnel","count":246},{"language":"default","tag":"Documentation","count":175},{"language":"default","tag":"Conversions","count":149},{"language":"default","tag":"Blended","count":110},{"language":"default","tag":"OVERVIEW","count":107},{"language":"default","tag":"Event Tracking","count":104}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableAskAiSearchBar":true,"deflection":{"enabled":true,"email":"support@upstackdata.com","showHelpButton":true}},"basePath":"","hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":"/* cyrillic-ext */\n@font-face {\n font-family: 'JetBrains Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/jetbrainsmono/v24/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx3cwhsk.woff2) format('woff2');\n unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n font-family: 'JetBrains Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/jetbrainsmono/v24/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxTcwhsk.woff2) format('woff2');\n unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* greek */\n@font-face {\n font-family: 'JetBrains Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/jetbrainsmono/v24/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxPcwhsk.woff2) format('woff2');\n unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;\n}\n/* vietnamese */\n@font-face {\n font-family: 'JetBrains Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/jetbrainsmono/v24/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx_cwhsk.woff2) format('woff2');\n unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n font-family: 'JetBrains Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/jetbrainsmono/v24/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx7cwhsk.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n font-family: 'JetBrains Mono';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/jetbrainsmono/v24/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxDcwg.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* cyrillic-ext */\n@font-face {\n font-family: 'JetBrains Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/jetbrainsmono/v24/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx3cwhsk.woff2) format('woff2');\n unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n font-family: 'JetBrains Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/jetbrainsmono/v24/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxTcwhsk.woff2) format('woff2');\n unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* greek */\n@font-face {\n font-family: 'JetBrains Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/jetbrainsmono/v24/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxPcwhsk.woff2) format('woff2');\n unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;\n}\n/* vietnamese */\n@font-face {\n font-family: 'JetBrains Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/jetbrainsmono/v24/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx_cwhsk.woff2) format('woff2');\n unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n font-family: 'JetBrains Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/jetbrainsmono/v24/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx7cwhsk.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n font-family: 'JetBrains Mono';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(/_mintlify/assets/fonts/google/s/jetbrainsmono/v24/tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxDcwg.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n:root{--font-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;--font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;--font-size-label: 0.6875rem;--font-size-tiny: 0.75rem;--font-size-small: 0.8125rem;--font-size-secondary: 0.875rem;--font-size-body: 0.9375rem;--font-size-h3: 1.0625rem;--font-size-h2: 1.25rem;--font-size-h1: 1.625rem;--font-size-code: 0.8125rem;--page-bg: #ffffff;--chrome-bg: #f6f7f8;--border: #e5e7eb;--accent: #4230b4;--accent-hover: #322484;--text-heading: #18181b;--text-body: #52525b;--text-muted: #71717a;--focus-ring: rgba(24, 24, 27, 0.12);--border-strong: #d4d4d8;--input-bg: #ffffff;--hover-bg: rgba(24, 24, 27, 0.04);--active-bg: rgba(24, 24, 27, 0.06)}html{background:var(--page-bg);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{background:var(--page-bg);color:var(--text-body);font-family:var(--font-sans)!important;font-size:var(--font-size-body)!important;line-height:1.6!important;font-weight:400!important}#navbar,#header{background:var(--chrome-bg)!important;border-bottom:1px solid var(--border)!important;backdrop-filter:none!important}.nav-tabs-item{font-size:var(--font-size-small)!important;font-weight:400!important;color:var(--text-muted)!important}.nav-tabs-item[data-active],.nav-tabs-item:hover{color:var(--text-heading)!important}#sidebar,#sidebar-content{background:var(--chrome-bg)!important;border-right:1px solid var(--border)!important}#sidebar{top:calc(7.1rem + var(--banner-height, 0px))!important;height:auto!important}#sidebar-content{overscroll-behavior:contain}.sidebar-group-header,.sidebar-title{font-size:var(--font-size-label)!important;font-weight:600!important;letter-spacing:0.05em;text-transform:uppercase;color:var(--text-muted)!important;margin-top:24px!important;margin-bottom:8px!important;padding-top:0!important;padding-bottom:0!important}#sidebar-content>div:first-child .sidebar-group-header,#sidebar-content>div:first-child .sidebar-title{margin-top:12px!important}#sidebar-content ul{padding-left:12px!important}#sidebar-content ul ul{padding-left:14px!important;border-left:1px solid var(--border)!important;margin-left:4px!important}.sidebar-group a,#sidebar a{font-size:var(--font-size-small)!important;font-weight:400!important;color:var(--text-body)!important;padding-top:5px!important;padding-bottom:5px!important;line-height:1.4!important;transition:color 80ms ease}.sidebar-group a:hover,#sidebar a:hover{color:var(--text-heading)!important}#navigation-items a,#navigation-items button,#sidebar-content .sidebar-group>button,#sidebar-content .sidebar-group button{border-radius:4px!important;transition:color 80ms ease, background-color 80ms ease!important}#navigation-items a:hover,#navigation-items button:hover{background:var(--hover-bg)!important}#navigation-items a[class*=\"bg-primary\"]{background:var(--active-bg)!important;color:var(--accent)!important;font-weight:500!important}.sidebar-group>button,.sidebar-group button{font-size:var(--font-size-small)!important;font-weight:400!important;color:var(--text-body)!important;padding-top:5px!important;padding-bottom:5px!important;transition:color 80ms ease}.sidebar-group>button:hover,.sidebar-group button:hover{color:var(--text-heading)!important}.eyebrow,.breadcrumb-list,.breadcrumb-item{font-size:var(--font-size-label)!important;color:var(--text-muted)!important;font-weight:500!important;text-transform:uppercase!important;letter-spacing:0.05em!important}div[class*=\"peer-[.is-not-custom]\"]{max-width:none!important}#content-area,#content,#content-container,#content-side-layout{background:var(--page-bg)!important;max-width:none!important}#navbar div[class*=\"max-w-8xl\"]{max-width:none!important}#table-of-contents-layout{max-width:none!important}#body-content{max-width:none!important}.mdx-content{max-width:none!important;overflow-wrap:break-word}h1,h2,h3,h4,h5,h6,#page-title,.mdx-content h1,.mdx-content h2,.mdx-content h3,.mdx-content h4,.mdx-content h5,.mdx-content h6{font-family:var(--font-sans)!important;text-wrap:balance}#page-title,.mdx-content h1{color:var(--text-heading)!important;font-size:var(--font-size-h1)!important;font-weight:600!important;line-height:1.2!important;letter-spacing:-0.01em;margin-top:0!important;margin-bottom:2px!important}.mdx-content>h2,.mdx-content>div>h2{color:var(--text-heading)!important;font-size:var(--font-size-h2)!important;font-weight:600!important;line-height:1.3!important;letter-spacing:-0.01em;margin-top:32px!important;margin-bottom:12px!important}.mdx-content>h3,.mdx-content>div>h3{color:var(--text-heading)!important;font-size:var(--font-size-h3)!important;font-weight:600!important;line-height:1.4!important;margin-top:24px!important;margin-bottom:8px!important}.mdx-content>h4,.mdx-content>div>h4{color:var(--text-heading)!important;font-size:var(--font-size-body)!important;font-weight:600!important;line-height:1.45!important;margin-top:20px!important;margin-bottom:6px!important}.mdx-content p,.mdx-content [data-as=\"p\"],.mdx-content li{color:var(--text-body)!important;font-size:var(--font-size-body)!important;line-height:1.6!important;font-weight:400!important}.mdx-content p{text-wrap:pretty}.mdx-content>p:first-of-type,.mdx-content>[data-as=\"p\"]:first-of-type{color:var(--text-body)!important;font-size:var(--font-size-body)!important;font-weight:400!important;line-height:1.6!important;margin-top:0!important;margin-bottom:20px!important}.mdx-content a,.mdx-content .link{color:var(--accent)!important;text-decoration:none;transition:color 80ms ease}.mdx-content a:hover,.mdx-content .link:hover{color:var(--accent-hover)!important;text-decoration:underline}.mdx-content a.link:has(>div){background:var(--page-bg)!important;border:1px solid var(--border)!important;border-radius:4px!important;box-shadow:none!important;padding:16px 18px!important;transition:border-color 80ms ease, background-color 80ms ease!important}.mdx-content a.link:has(>div):hover{border-color:var(--border-strong)!important;background:var(--page-bg)!important;box-shadow:none!important;transform:none!important;text-decoration:none!important}.mdx-content a.link:has(>div)>div:first-child{color:var(--accent)!important;font-size:var(--font-size-secondary)!important;font-weight:500!important;line-height:1.35!important;margin:0 0 4px 0!important;padding:0!important}.mdx-content a.link:has(>div)>div:last-child{color:var(--text-muted)!important;font-size:var(--font-size-small)!important;font-weight:400!important;line-height:1.4!important;margin:0!important;padding:0!important}.card-group,.columns{gap:12px!important}#topbar-cta-button{background:var(--accent)!important;border:1px solid var(--accent)!important;color:#fff!important;border-radius:4px!important;font-family:var(--font-sans)!important;font-size:var(--font-size-small)!important;font-weight:500!important;padding:6px 12px!important;box-shadow:none!important}#topbar-cta-button:hover{background:var(--accent-hover)!important;border-color:var(--accent-hover)!important}#page-context-menu button{border-radius:4px!important;border-color:var(--border)!important}#feedback-thumbs-up,#feedback-thumbs-down{border-radius:4px!important;border-color:var(--border)!important;background:var(--page-bg)!important}[data-assistant-bar] div[class*=\"rounded-2xl\"]{border-radius:4px!important;border-color:var(--border)!important}#search-input,#search-bar-entry{border:1px solid var(--border)!important;border-radius:4px!important;font-family:var(--font-sans)!important;font-size:var(--font-size-small)!important;background:var(--input-bg)!important;color:var(--text-body)!important}#search-input:focus{border-color:var(--border-strong)!important;box-shadow:0 0 0 3px var(--focus-ring)!important;outline:none!important}#search-input kbd,#search-bar-entry kbd{font-family:var(--font-mono)!important;font-size:var(--font-size-label)!important}#topbar-cta-button:focus-visible,#page-context-menu button:focus-visible,#navigation-items a:focus-visible,#navigation-items button:focus-visible,.toc-item a:focus-visible,#pagination a:focus-visible,#footer a:focus-visible{outline:2px solid var(--text-muted)!important;outline-offset:2px}.mdx-content table{border:1px solid var(--border)!important;border-collapse:collapse!important;font-variant-numeric:tabular-nums}.mdx-content th{background:var(--chrome-bg)!important;font-size:var(--font-size-small)!important;font-weight:600!important;color:var(--text-heading)!important;padding:8px 12px!important}.mdx-content td{border-color:var(--border)!important;font-size:var(--font-size-secondary)!important;padding:8px 12px!important}.mdx-content pre{border-radius:4px!important}code,pre,pre code,.code-block,[class*=\"language-\"]{font-family:var(--font-mono)!important}pre,.code-block{font-size:var(--font-size-code)!important;line-height:1.6!important}code{border-radius:4px!important;font-size:var(--font-size-code)!important;background:var(--chrome-bg)!important;color:var(--text-heading)!important;padding:1px 4px!important;border:1px solid var(--border)!important}pre code{background:transparent!important;border:0!important;padding:0!important;font-size:inherit!important}.mdx-content+.prose,[class*=\"text-lg\"][class*=\"prose\"]{font-size:var(--font-size-body)!important;line-height:1.6!important;color:var(--text-body)!important}.accordion{border:1px solid var(--border)!important;border-radius:4px!important;overflow:hidden}.accordion-group{border:1px solid var(--border)!important;border-radius:4px!important}.accordion-group>.accordion{border-radius:0!important;border-left:0!important;border-right:0!important;border-top:0!important}.accordion-group>.accordion:last-child{border-bottom:0!important}.mdx-content [data-component-part=\"accordion-title\"]{color:var(--text-heading)!important;font-size:var(--font-size-body)!important;font-weight:500!important}[data-component-part=\"accordion-content\"]{font-size:var(--font-size-body)!important;line-height:1.6!important;color:var(--text-body)!important}[data-component-part=\"accordion-content\"] p,[data-component-part=\"accordion-content\"] [data-as=\"p\"],[data-component-part=\"accordion-content\"] li{font-size:var(--font-size-body)!important;line-height:1.6!important;color:var(--text-body)!important;font-weight:400!important}.steps{margin-top:24px!important}.step{padding-bottom:24px!important}.mdx-content [data-component-part=\"step-title\"]{font-size:var(--font-size-h3)!important;font-weight:600!important;line-height:1.4!important;color:var(--text-heading)!important;margin-top:0!important;margin-bottom:8px!important}.mdx-content [data-component-part=\"step-title\"] a{color:inherit!important;text-decoration:none!important}.mdx-content [data-component-part=\"step-title\"]:hover a{color:var(--accent)!important}[data-component-part=\"step-number\"]{color:var(--text-muted)!important}[data-component-part=\"step-line\"]{background-color:var(--border)!important}[data-component-part=\"step-content\"]{font-size:var(--font-size-body)!important;line-height:1.6!important;color:var(--text-body)!important}[data-component-part=\"step-content\"] p,[data-component-part=\"step-content\"] [data-as=\"p\"],[data-component-part=\"step-content\"] li{font-size:var(--font-size-body)!important;line-height:1.6!important;color:var(--text-body)!important;font-weight:400!important}[data-component-part=\"step-content\"] a{color:var(--accent)!important;text-decoration:none!important;transition:color 80ms ease}[data-component-part=\"step-content\"] a:hover{color:var(--accent-hover)!important;text-decoration:underline!important}.callout{border-radius:4px!important}[data-component-part=\"callout-content\"]{font-size:var(--font-size-secondary)!important;line-height:1.6!important}[data-component-part=\"callout-content\"] p,[data-component-part=\"callout-content\"] [data-as=\"p\"]{font-size:var(--font-size-secondary)!important;line-height:1.6!important}.mdx-content strong,[data-component-part=\"accordion-content\"] strong{color:var(--text-heading)!important;font-weight:600!important}.mdx-content em,[data-component-part=\"accordion-content\"] em{font-style:italic}.mdx-content blockquote{border-left:3px solid var(--border)!important;padding-left:16px!important;color:var(--text-muted)!important}.toc{font-size:var(--font-size-small)!important}.toc-item a{color:var(--text-muted)!important;transition:color 80ms ease}.toc-item a:hover{color:var(--text-heading)!important}.toc-item[data-active]>a,.toc-item[data-active-deepest]>a{color:var(--accent)!important}#pagination{font-size:var(--font-size-small)!important;color:var(--text-body)!important;border-top:1px solid var(--border)!important;padding-top:16px!important;margin-top:32px!important}#pagination a{color:var(--text-body)!important;transition:color 80ms ease}#pagination a:hover{color:var(--accent)!important}hr{border-color:var(--border)!important}#footer,footer{background:transparent!important;border-top:1px solid var(--border)!important;color:var(--text-muted)!important;margin-top:48px!important;font-size:var(--font-size-small)!important}#footer:not(.advanced-footer),footer:not(.advanced-footer){padding-top:24px!important;padding-bottom:32px!important}#footer.advanced-footer{padding:0!important}#footer.advanced-footer>div{padding-top:32px!important;padding-bottom:32px!important}@media (min-width: 768px){#footer.advanced-footer>div{padding-top:40px!important;padding-bottom:40px!important}}#footer.advanced-footer p{color:var(--text-heading)!important;font-size:var(--font-size-small)!important;font-weight:600!important;margin-bottom:4px!important}#footer.advanced-footer a{color:var(--text-muted)!important;font-size:var(--font-size-small)!important;transition:color 80ms ease}#footer.advanced-footer a:hover{color:var(--text-heading)!important}#footer a{color:var(--text-muted)!important;transition:color 80ms ease}#footer a:hover{color:var(--text-heading)!important}#footer svg{background-color:var(--text-muted)!important;transition:background-color 80ms ease}#footer a:hover svg{background-color:var(--accent)!important}[data-testid=\"sales-agent-background\"]{background:var(--accent)!important}[data-testid=\"sales-agent-background\"]>div{background:transparent!important;opacity:0!important}.intercom-launcher-frame,.intercom-lightweight-app-launcher,.intercom-messenger-frame,[class^=\"intercom-\"][class*=\"frame\"]{border-radius:12px!important;box-shadow:0 8px 24px rgba(26, 31, 54, 0.12), 0 2px 6px rgba(26, 31, 54, 0.06)!important}.intercom-launcher-frame,.intercom-lightweight-app-launcher{background:var(--accent)!important}::selection{background:var(--accent)!important;color:#fff!important}*{scrollbar-color:var(--border-strong) transparent}*::-webkit-scrollbar{width:10px;height:10px}*::-webkit-scrollbar-track{background:transparent}*::-webkit-scrollbar-thumb{background:var(--border-strong);border-radius:5px;border:2px solid var(--page-bg)}*::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}@media (max-width: 1024px){#content-area,#content,#content-container{padding-left:16px!important;padding-right:16px!important}#table-of-contents,#table-of-contents-layout aside{display:none!important}.card-group,.columns{grid-template-columns:1fr!important;gap:10px!important}}@media (max-width: 768px){:root{--font-size-h1: 1.375rem;--font-size-h2: 1.125rem;--font-size-h3: 1rem;--font-size-body: 0.875rem;--font-size-code: 0.75rem}.mdx-content>h2,.mdx-content>div>h2{margin-top:24px!important}.mdx-content>h3,.mdx-content>div>h3{margin-top:16px!important}#content-area,#content,#content-container{padding-left:12px!important;padding-right:12px!important}.mdx-content a.link:has(>div){padding:12px 14px!important}.mdx-content a.link:has(>div)>div:first-child{font-size:var(--font-size-small)!important}.mdx-content a.link:has(>div)>div:last-child{font-size:var(--font-size-tiny)!important}.mdx-content table{display:block!important;overflow-x:auto!important;-webkit-overflow-scrolling:touch;max-width:100%!important}.mdx-content th,.mdx-content td{font-size:var(--font-size-tiny)!important;padding:6px 8px!important;white-space:nowrap}pre,.code-block{overflow-x:auto!important;-webkit-overflow-scrolling:touch;max-width:100%!important}[data-component-part=\"callout-content\"],[data-component-part=\"callout-content\"] p,[data-component-part=\"callout-content\"] [data-as=\"p\"]{font-size:var(--font-size-small)!important}#sidebar,#sidebar-content{width:280px!important}#navbar,#header{padding-left:12px!important;padding-right:12px!important}#topbar-cta-button{font-size:var(--font-size-tiny)!important;padding:5px 10px!important}#pagination{flex-direction:column!important;gap:8px!important}}@media (max-width: 480px){:root{--font-size-h1: 1.25rem;--font-size-h2: 1rem;--font-size-h3: 0.9375rem}#content-area,#content,#content-container{padding-left:12px!important;padding-right:12px!important}#search-input+kbd,#search-bar-entry kbd{display:none!important}}.catalog-page .card{border:1px solid var(--border)!important;border-radius:4px!important;box-shadow:none!important;margin:0 0 6px 0!important;transition:border-color 80ms ease}.catalog-page .card:hover{border-color:var(--border-strong)!important;background:var(--page-bg)!important}.catalog-page .card>div{display:flex!important;align-items:center!important;gap:12px!important;padding:9px 16px!important}.catalog-page .card [data-component-part=\"card-icon\"],.catalog-page .card [data-component-part=\"card-icon\"] svg{width:18px!important;height:18px!important;flex-shrink:0;color:var(--accent)!important;fill:var(--accent)!important}.catalog-page .card .w-full{flex:1!important;min-width:0}.catalog-page .card [data-component-part=\"card-title\"]{display:inline!important;font-size:14px!important;font-weight:500!important;color:var(--text-heading)!important;margin:0 10px 0 0!important;line-height:1.4!important}.catalog-page .card [data-component-part=\"card-content\"]{display:inline!important;font-size:13px!important;color:var(--text-muted)!important;line-height:1.45!important}.catalog-page h3{font-size:13px!important;font-weight:600!important;color:var(--text-muted)!important;text-transform:uppercase;letter-spacing:0.04em;margin:22px 0 10px!important}.catalog-page .card>div>a{display:flex!important;align-items:center!important;gap:12px!important;width:100%!important;border-bottom:none!important}.catalog-page .columns{max-width:100%!important}"},{"filePath":"custom.css","content":"@media (min-width: 1024px){nav#sidebar{height:calc(\n 100dvh - var(--mintlify-slot-header-height, calc(4rem + var(--topbar-tabs-height, 0rem)))\n )!important}}"}],"page":{"pagePath":"api-reference/analytics/run-a-cohort-analysis","slug":"/api-reference/analytics/run-a-cohort-analysis","pageMetadata":{"title":"Run a cohort analysis for customer LTV and retention","description":"Group customers by the week, month, or year of their first order and track cumulative revenue per customer, retention, AOV, and contribution margin over time.","deprecated":null,"version":null,"sidebarTitle":"Run a cohort analysis","keywords":["cohort analysis API","customer lifetime value","LTV","retention","Upstack Data API"],"openapi":"/api-reference/openapi.yaml post /db-mgmt/api/query-cohort-analysis","href":"/api-reference/analytics/run-a-cohort-analysis","autogeneratedByOpenApi":true},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Group customers by the week, month, or year of their first order and track cumulative revenue per customer, retention, AOV, and contribution margin over time.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,p:`p`,strong:`strong`,ul:`ul`,..._provideComponents(),...props.components},{Heading}=_components;if(!Heading)_missingMdxReference(`Heading`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[_jsx(_components.strong,{children:`Required scope:`}),` `,_jsx(_components.code,{children:`analytics:read`})]}),`\n`,_jsx(_components.p,{children:`Use this to compare customers by when you acquired them. For example, check whether\ncustomers acquired in January have spent more per head after three months than\ncustomers acquired in March, or watch how many of each month’s new customers order\nagain.`}),`\n`,_jsx(Heading,{level:`2`,id:`request-rules`,children:`Request rules`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Send `,_jsx(_components.code,{children:`timezone`}),`. The schema marks it optional, but a request without it fails with\n`,_jsx(_components.code,{children:`500`}),` and the message `,_jsx(_components.code,{children:`Timezone is required`}),`.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`measures`}),` is a list of plain measure id strings, limited to the cohort measures\nlisted below. `,_jsx(_components.a,{href:`/api-reference/analytics/run-an-analytics-query`,children:`Run an analytics query`}),`\ntakes objects instead.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`granularity`}),` is `,_jsx(_components.code,{children:`week`}),`, `,_jsx(_components.code,{children:`month`}),`, or `,_jsx(_components.code,{children:`year`}),`. Each period in `,_jsx(_components.code,{children:`dateRange`}),` becomes one\ncohort.`]}),`\n`,_jsxs(_components.li,{children:[`Only `,_jsx(_components.code,{children:`orders.*`}),` filter fields work here. A malformed `,_jsx(_components.code,{children:`filters`}),` tree returns `,_jsx(_components.code,{children:`400`}),`,\nbut a field that isn’t valid for cohort analysis returns `,_jsx(_components.code,{children:`500`}),` with the reason in\n`,_jsx(_components.code,{children:`message`}),`. Check fields with `,_jsx(_components.a,{href:`/api-reference/catalog/list-filter-fields`,children:`List filter fields`}),`\n(`,_jsx(_components.code,{children:`cohort_analysis`}),`).`]}),`\n`,_jsxs(_components.li,{children:[`Saved order settings aren’t applied for you. Pass the object from\n`,_jsx(_components.a,{href:`/api-reference/account/get-order-settings`,children:`Get order settings`}),` as `,_jsx(_components.code,{children:`orderSettings`}),`\nto match the web app.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`reading-the-response`,children:`Reading the response`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`results`}),` has one entry. Its `,_jsx(_components.code,{children:`data.primary`}),` holds one row per cohort and period\npair: `,_jsx(_components.code,{children:`cohort_month`}),` is the cohort’s first day and `,_jsx(_components.code,{children:`order_month`}),` is the period the\nvalues cover, both as `,_jsx(_components.code,{children:`YYYY-MM-DD`}),`. The keys keep the `,_jsx(_components.code,{children:`_month`}),` names for every\ngranularity. Only periods on or after the cohort’s start appear.`]}),`\n`,_jsx(_components.li,{children:`Each measure is keyed by its id. Revenue, CM1, and CM2 measures are cumulative per\ncustomer: the cohort’s total since its first period divided by its customer count.`}),`\n`,_jsx(_components.li,{children:`A period with no orders repeats that cohort’s previous values, so cumulative\nfigures never drop back to zero.`}),`\n`,_jsxs(_components.li,{children:[`Measure values can come back as numeric strings (for example `,_jsx(_components.code,{children:`\"84.37\"`}),`). Parse them\nbefore doing math.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`measureDetails`}),` is always empty, and there’s no comparison period.`]}),`\n`,_jsxs(_components.li,{children:[`The `,_jsx(_components.code,{children:`orders.lifetime_value_90`}),`, `,_jsx(_components.code,{children:`_180`}),`, and `,_jsx(_components.code,{children:`_365`}),` measures extend the periods\ncovered by 90, 180, or 365 days past `,_jsx(_components.code,{children:`dateRange.end`}),`.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`related`,children:`Related`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`/api-reference/analytics/run-an-analytics-query`,children:`Run an analytics query`}),` for non-cohort measures.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`/api-reference/account/get-order-settings`,children:`Get order settings`}),` for the `,_jsx(_components.code,{children:`orderSettings`}),` to pass.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`/cli/query-cohort`,children:_jsx(_components.code,{children:`upstack query cohort`})}),` runs the same analysis from the CLI.`]}),`\n`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Run a cohort analysis for customer LTV and retention","description":"Group customers by the week, month, or year of their first order and track cumulative revenue per customer, retention, AOV, and contribution margin over time.","deprecated":null,"version":null,"sidebarTitle":"Run a cohort analysis","keywords":["cohort analysis API","customer lifetime value","LTV","retention","Upstack Data API"],"openapi":"/api-reference/openapi.yaml post /db-mgmt/api/query-cohort-analysis","href":"/api-reference/analytics/run-a-cohort-analysis","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Request rules","slug":"request-rules","depth":2,"children":[]},{"title":"Reading the response","slug":"reading-the-response","depth":2,"children":[]},{"title":"Related","slug":"related","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":["/_mintlify/custom/upstackdata-afbed50d/b64b07ede631efed/intercom-customize.js","/_mintlify/custom/upstackdata-afbed50d/1cbfb793dc2ec470/upstack-pixel.js","/_mintlify/custom/upstackdata-afbed50d/e2ccc0353f9bb1f8/sidebar-footer-scroll-fix.js"],"openApiReferenceData":{"operation":{"tags":["Analytics"],"operationId":"queryCohortAnalysis","summary":"Run a cohort analysis","description":"Group customers by the week, month, or year of their first order and track cumulative revenue per customer, retention, AOV, and contribution margin over time.","x-mint":{"metadata":{"title":"Run a cohort analysis for customer LTV and retention","sidebarTitle":"Run a cohort analysis","keywords":["cohort analysis API","customer lifetime value","LTV","retention","Upstack Data API"]},"content":"**Required scope:** `analytics:read`\n\nUse this to compare customers by when you acquired them. For example, check whether\ncustomers acquired in January have spent more per head after three months than\ncustomers acquired in March, or watch how many of each month's new customers order\nagain.\n\n## Request rules\n\n- Send `timezone`. The schema marks it optional, but a request without it fails with\n `500` and the message `Timezone is required`.\n- `measures` is a list of plain measure id strings, limited to the cohort measures\n listed below. [Run an analytics query](/api-reference/analytics/run-an-analytics-query)\n takes objects instead.\n- `granularity` is `week`, `month`, or `year`. Each period in `dateRange` becomes one\n cohort.\n- Only `orders.*` filter fields work here. A malformed `filters` tree returns `400`,\n but a field that isn't valid for cohort analysis returns `500` with the reason in\n `message`. Check fields with [List filter fields](/api-reference/catalog/list-filter-fields)\n (`cohort_analysis`).\n- Saved order settings aren't applied for you. Pass the object from\n [Get order settings](/api-reference/account/get-order-settings) as `orderSettings`\n to match the web app.\n\n## Reading the response\n\n- `results` has one entry. Its `data.primary` holds one row per cohort and period\n pair: `cohort_month` is the cohort's first day and `order_month` is the period the\n values cover, both as `YYYY-MM-DD`. The keys keep the `_month` names for every\n granularity. Only periods on or after the cohort's start appear.\n- Each measure is keyed by its id. Revenue, CM1, and CM2 measures are cumulative per\n customer: the cohort's total since its first period divided by its customer count.\n- A period with no orders repeats that cohort's previous values, so cumulative\n figures never drop back to zero.\n- Measure values can come back as numeric strings (for example `\"84.37\"`). Parse them\n before doing math.\n- `measureDetails` is always empty, and there's no comparison period.\n- The `orders.lifetime_value_90`, `_180`, and `_365` measures extend the periods\n covered by 90, 180, or 365 days past `dateRange.end`.\n\n## Related\n\n- [Run an analytics query](/api-reference/analytics/run-an-analytics-query) for non-cohort measures.\n- [Get order settings](/api-reference/account/get-order-settings) for the `orderSettings` to pass.\n- [`upstack query cohort`](/cli/query-cohort) runs the same analysis from the CLI.\n"},"requestBody":"71e41627-8e8a-4cb9-9c5c-1927610d0cc3","responses":{"200":"08cc8cf7-2ab4-4cd5-a401-1856f17b9162","400":"f5130320-8e36-450f-9329-86de64f9302b","401":"965a3a3a-3edf-40f2-b685-e9f3e03e7971","403":"0711ba3f-3fa4-4c7a-ae26-18c0c651a314","500":"4792c888-8848-476e-9ee0-db65315f8cbd"},"method":"post","type":"path","servers":["2bbb3e85-633d-4371-b828-47a29d5899c5"],"security":["f19e0b22-afd0-4760-b88e-dce1773111cb"],"path":"/db-mgmt/api/query-cohort-analysis","baseUrlOptions":["https://api.upstackdata.com"],"title":"Run a cohort analysis","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["pixelId","granularity","measures","dateRange"],"properties":{"pixelId":{"type":"string","description":"Must match the `x-pixel-id` header.","isRequired":true,"uniqueKey":"pixelId","typeLabel":"string"},"granularity":{"type":"string","enum":["week","month","year"],"description":"Cohort period length. Each period in `dateRange` is one cohort.","isRequired":true,"uniqueKey":"granularity","typeLabel":"enum\u003cstring>"},"measures":{"type":"array","maxItems":30,"items":{"type":"string","enum":["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"],"uniqueKey":"measures.items.[INDEX]","typeLabel":"enum\u003cstring>"},"description":"Cohort-specific measure ids. Pass measure ids as strings (this\nendpoint differs from `/api/query`, which takes objects with\n`pacing`).\n","isRequired":true,"uniqueKey":"measures","typeLabel":"enum\u003cstring>[]"},"dateRange":{"type":"object","required":["start","end"],"description":"The cohorts to include. Customers are grouped by the period of their first order.","properties":{"start":{"type":"string","format":"date","description":"First day of the range, as an ISO 8601 date.","example":"2026-04-01","isRequired":true,"uniqueKey":"dateRange.start","typeLabel":"string\u003cdate>"},"end":{"type":"string","format":"date","description":"Last day of the range, as an ISO 8601 date. Included in the results.","example":"2026-04-30","isRequired":true,"uniqueKey":"dateRange.end","typeLabel":"string\u003cdate>"}},"isRequired":true,"uniqueKey":"dateRange","typeLabel":"object"},"timezone":{"type":"string","description":"IANA timezone (e.g. `America/New_York`) used to bucket orders into periods.\nRequired in practice: a request without it fails with `500`.\n","example":"America/New_York","uniqueKey":"timezone","typeLabel":"string"},"currency":{"type":"string","default":"USD","description":"ISO 4217 code to convert cohort money values to (revenue, AOV,\nCM1/CM2). Each amount converts at the rate for the day the\norder occurred.\n**Defaults to `USD` when omitted** — if your store sells in\nanother currency, pass this explicitly.\n","uniqueKey":"currency","typeLabel":"string"},"filters":{"oneOf":[{"type":"object","title":"All of (and)","description":"Filter applied to the orders in the cohort. Only `orders.*` fields are\nvalid here; any other field fails with `500`.\n","required":["and"],"properties":{"and":{"type":"array","minItems":1,"items":{"oneOf":[{"type":"object","title":"Condition","description":"Either a `FilterCondition` leaf or a nested `FilterGroup`.","required":["field","op","value"],"properties":{"field":{"type":"string","description":"Canonical filter field id (`\u003cscope>.\u003csnake_case_id>`). Each id is only\nvalid on certain endpoints. [List filter fields](/api-reference/catalog/list-filter-fields)\nreturns the full set and where each one applies.\n","enum":["orders.source_name","orders.customer_type","orders.order_type","orders.value","orders.payment_gateway","orders.tags","channel.resource_name","channel.resource_source","channel.resource_status","channel.resource_configured_status","channel.resource_effective_status","channel.account_id","channel.campaign_id","channel.adset_id","channel.ad_id","channel.account_name","channel.campaign_name","channel.adset_name","channel.ad_name","attribution.utm_source","attribution.utm_medium","attribution.utm_campaign","attribution.utm_adset","attribution.utm_term","attribution.utm_ad","attribution.utm_content","events.event_name","emq.dataset_id","emq.event_name","emq.diagnostic_name"],"isRequired":true,"uniqueKey":"filters.oneOf.0.and.items.[INDEX].oneOf.0.field","typeLabel":"enum\u003cstring>"},"op":{"type":"string","description":"Operator on a filter condition. Each field accepts its own subset, listed in\n`supportedOperators` by [List filter fields](/api-reference/catalog/list-filter-fields).\n","enum":["equals","not_equals","greater_than","less_than","greater_than_or_equals","less_than_or_equals","contains","not_contains","starts_with","ends_with","in","not_in","array_includes","array_includes_all","array_includes_any"],"isRequired":true,"uniqueKey":"filters.oneOf.0.and.items.[INDEX].oneOf.0.op","typeLabel":"enum\u003cstring>"},"value":{"oneOf":[{"type":"string","title":"String","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.0.and.items.[INDEX].oneOf.0.value.oneOf.0","typeLabel":"string"},{"type":"number","title":"Number","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.0.and.items.[INDEX].oneOf.0.value.oneOf.1","typeLabel":"number"},{"type":"boolean","title":"Boolean","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.0.and.items.[INDEX].oneOf.0.value.oneOf.2","typeLabel":"boolean"},{"type":"array","items":{"type":"string","uniqueKey":"filters.oneOf.0.and.items.[INDEX].oneOf.0.value.oneOf.3.items.[INDEX]","typeLabel":"string"},"title":"List of strings","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.0.and.items.[INDEX].oneOf.0.value.oneOf.3","typeLabel":"string[]"},{"type":"array","items":{"type":"number","uniqueKey":"filters.oneOf.0.and.items.[INDEX].oneOf.0.value.oneOf.4.items.[INDEX]","typeLabel":"number"},"title":"List of numbers","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.0.and.items.[INDEX].oneOf.0.value.oneOf.4","typeLabel":"number[]"},{"type":"array","items":{"type":"boolean","uniqueKey":"filters.oneOf.0.and.items.[INDEX].oneOf.0.value.oneOf.5.items.[INDEX]","typeLabel":"boolean"},"title":"List of booleans","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.0.and.items.[INDEX].oneOf.0.value.oneOf.5","typeLabel":"boolean[]"}],"isRequired":true,"uniqueKey":"filters.oneOf.0.and.items.[INDEX].oneOf.0.value","typeLabel":"string | number | boolean | string[] | number[] | boolean[]"}},"uniqueKey":"filters.oneOf.0.and.items.[INDEX].oneOf.0","typeLabel":"Condition · object"},{"title":"Nested group","description":"Either a `FilterCondition` leaf or a nested `FilterGroup`.","uniqueKey":"filters.oneOf.0.and.items.[INDEX].oneOf.1","typeLabel":"any"}],"uniqueKey":"filters.oneOf.0.and.items.[INDEX]","typeLabel":"Condition · object | any"},"isRequired":true,"uniqueKey":"filters.oneOf.0.and","typeLabel":"(Condition · object | any)[]"}},"uniqueKey":"filters.oneOf.0","typeLabel":"All of (and) · object"},{"type":"object","title":"Any of (or)","description":"Filter applied to the orders in the cohort. Only `orders.*` fields are\nvalid here; any other field fails with `500`.\n","required":["or"],"properties":{"or":{"type":"array","minItems":1,"items":{"oneOf":[{"type":"object","title":"Condition","description":"Either a `FilterCondition` leaf or a nested `FilterGroup`.","required":["field","op","value"],"properties":{"field":{"type":"string","description":"Canonical filter field id (`\u003cscope>.\u003csnake_case_id>`). Each id is only\nvalid on certain endpoints. [List filter fields](/api-reference/catalog/list-filter-fields)\nreturns the full set and where each one applies.\n","enum":["orders.source_name","orders.customer_type","orders.order_type","orders.value","orders.payment_gateway","orders.tags","channel.resource_name","channel.resource_source","channel.resource_status","channel.resource_configured_status","channel.resource_effective_status","channel.account_id","channel.campaign_id","channel.adset_id","channel.ad_id","channel.account_name","channel.campaign_name","channel.adset_name","channel.ad_name","attribution.utm_source","attribution.utm_medium","attribution.utm_campaign","attribution.utm_adset","attribution.utm_term","attribution.utm_ad","attribution.utm_content","events.event_name","emq.dataset_id","emq.event_name","emq.diagnostic_name"],"isRequired":true,"uniqueKey":"filters.oneOf.1.or.items.[INDEX].oneOf.0.field","typeLabel":"enum\u003cstring>"},"op":{"type":"string","description":"Operator on a filter condition. Each field accepts its own subset, listed in\n`supportedOperators` by [List filter fields](/api-reference/catalog/list-filter-fields).\n","enum":["equals","not_equals","greater_than","less_than","greater_than_or_equals","less_than_or_equals","contains","not_contains","starts_with","ends_with","in","not_in","array_includes","array_includes_all","array_includes_any"],"isRequired":true,"uniqueKey":"filters.oneOf.1.or.items.[INDEX].oneOf.0.op","typeLabel":"enum\u003cstring>"},"value":{"oneOf":[{"type":"string","title":"String","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.1.or.items.[INDEX].oneOf.0.value.oneOf.0","typeLabel":"string"},{"type":"number","title":"Number","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.1.or.items.[INDEX].oneOf.0.value.oneOf.1","typeLabel":"number"},{"type":"boolean","title":"Boolean","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.1.or.items.[INDEX].oneOf.0.value.oneOf.2","typeLabel":"boolean"},{"type":"array","items":{"type":"string","uniqueKey":"filters.oneOf.1.or.items.[INDEX].oneOf.0.value.oneOf.3.items.[INDEX]","typeLabel":"string"},"title":"List of strings","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.1.or.items.[INDEX].oneOf.0.value.oneOf.3","typeLabel":"string[]"},{"type":"array","items":{"type":"number","uniqueKey":"filters.oneOf.1.or.items.[INDEX].oneOf.0.value.oneOf.4.items.[INDEX]","typeLabel":"number"},"title":"List of numbers","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.1.or.items.[INDEX].oneOf.0.value.oneOf.4","typeLabel":"number[]"},{"type":"array","items":{"type":"boolean","uniqueKey":"filters.oneOf.1.or.items.[INDEX].oneOf.0.value.oneOf.5.items.[INDEX]","typeLabel":"boolean"},"title":"List of booleans","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.1.or.items.[INDEX].oneOf.0.value.oneOf.5","typeLabel":"boolean[]"}],"isRequired":true,"uniqueKey":"filters.oneOf.1.or.items.[INDEX].oneOf.0.value","typeLabel":"string | number | boolean | string[] | number[] | boolean[]"}},"uniqueKey":"filters.oneOf.1.or.items.[INDEX].oneOf.0","typeLabel":"Condition · object"},{"title":"Nested group","description":"Either a `FilterCondition` leaf or a nested `FilterGroup`.","uniqueKey":"filters.oneOf.1.or.items.[INDEX].oneOf.1","typeLabel":"any"}],"uniqueKey":"filters.oneOf.1.or.items.[INDEX]","typeLabel":"Condition · object | any"},"isRequired":true,"uniqueKey":"filters.oneOf.1.or","typeLabel":"(Condition · object | any)[]"}},"uniqueKey":"filters.oneOf.1","typeLabel":"Any of (or) · object"},{"type":"object","title":"Not","description":"Filter applied to the orders in the cohort. Only `orders.*` fields are\nvalid here; any other field fails with `500`.\n","required":["not"],"properties":{"not":{"oneOf":[{"type":"object","title":"Condition","description":"Either a `FilterCondition` leaf or a nested `FilterGroup`.","required":["field","op","value"],"properties":{"field":{"type":"string","description":"Canonical filter field id (`\u003cscope>.\u003csnake_case_id>`). Each id is only\nvalid on certain endpoints. [List filter fields](/api-reference/catalog/list-filter-fields)\nreturns the full set and where each one applies.\n","enum":["orders.source_name","orders.customer_type","orders.order_type","orders.value","orders.payment_gateway","orders.tags","channel.resource_name","channel.resource_source","channel.resource_status","channel.resource_configured_status","channel.resource_effective_status","channel.account_id","channel.campaign_id","channel.adset_id","channel.ad_id","channel.account_name","channel.campaign_name","channel.adset_name","channel.ad_name","attribution.utm_source","attribution.utm_medium","attribution.utm_campaign","attribution.utm_adset","attribution.utm_term","attribution.utm_ad","attribution.utm_content","events.event_name","emq.dataset_id","emq.event_name","emq.diagnostic_name"],"isRequired":true,"uniqueKey":"filters.oneOf.2.not.oneOf.0.field","typeLabel":"enum\u003cstring>"},"op":{"type":"string","description":"Operator on a filter condition. Each field accepts its own subset, listed in\n`supportedOperators` by [List filter fields](/api-reference/catalog/list-filter-fields).\n","enum":["equals","not_equals","greater_than","less_than","greater_than_or_equals","less_than_or_equals","contains","not_contains","starts_with","ends_with","in","not_in","array_includes","array_includes_all","array_includes_any"],"isRequired":true,"uniqueKey":"filters.oneOf.2.not.oneOf.0.op","typeLabel":"enum\u003cstring>"},"value":{"oneOf":[{"type":"string","title":"String","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.2.not.oneOf.0.value.oneOf.0","typeLabel":"string"},{"type":"number","title":"Number","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.2.not.oneOf.0.value.oneOf.1","typeLabel":"number"},{"type":"boolean","title":"Boolean","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.2.not.oneOf.0.value.oneOf.2","typeLabel":"boolean"},{"type":"array","items":{"type":"string","uniqueKey":"filters.oneOf.2.not.oneOf.0.value.oneOf.3.items.[INDEX]","typeLabel":"string"},"title":"List of strings","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.2.not.oneOf.0.value.oneOf.3","typeLabel":"string[]"},{"type":"array","items":{"type":"number","uniqueKey":"filters.oneOf.2.not.oneOf.0.value.oneOf.4.items.[INDEX]","typeLabel":"number"},"title":"List of numbers","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.2.not.oneOf.0.value.oneOf.4","typeLabel":"number[]"},{"type":"array","items":{"type":"boolean","uniqueKey":"filters.oneOf.2.not.oneOf.0.value.oneOf.5.items.[INDEX]","typeLabel":"boolean"},"title":"List of booleans","description":"Scalar (`string` / `number` / `boolean`) for equality / comparison /\n`contains` operators. Array of scalars for `in`, `not_in`, and\n`array_includes_*` operators.\n","isRequired":true,"uniqueKey":"filters.oneOf.2.not.oneOf.0.value.oneOf.5","typeLabel":"boolean[]"}],"isRequired":true,"uniqueKey":"filters.oneOf.2.not.oneOf.0.value","typeLabel":"string | number | boolean | string[] | number[] | boolean[]"}},"isRequired":true,"uniqueKey":"filters.oneOf.2.not.oneOf.0","typeLabel":"Condition · object"},{"title":"Nested group","description":"Either a `FilterCondition` leaf or a nested `FilterGroup`.","isRequired":true,"uniqueKey":"filters.oneOf.2.not.oneOf.1","typeLabel":"any"}],"isRequired":true,"uniqueKey":"filters.oneOf.2.not","typeLabel":"Condition · object | any"}},"uniqueKey":"filters.oneOf.2","typeLabel":"Not · object"}],"uniqueKey":"filters","typeLabel":"All of (and) · object | Any of (or) · object | Not · object"},"orderSettings":{"type":"object","description":"Order settings to apply to this query. The query endpoints don't read the account's\nsaved order settings, so pass them here to match the web app's numbers. The\n`orderSettings` object returned by [Get order settings](/api-reference/account/get-order-settings)\ncan be passed as-is.\n","properties":{"countPendingOrders":{"type":"boolean","description":"Include pending orders.","uniqueKey":"orderSettings.countPendingOrders","typeLabel":"boolean"},"countVoidedOrders":{"type":"boolean","description":"Include voided orders.","uniqueKey":"orderSettings.countVoidedOrders","typeLabel":"boolean"},"refundDateAttribution":{"type":"string","enum":["refund_date","order_date"],"description":"Which date a refund is counted on.\n- `refund_date`: the day the refund was processed, matching Shopify. The default.\n- `order_date`: the date of the original order.\n","uniqueKey":"orderSettings.refundDateAttribution","typeLabel":"enum\u003cstring>"},"exclusionFilters":{"type":"array","description":"Orders matching any enabled filter are left out of the query. On this path every\nfilter, condition group, and condition must carry its `id`, and every condition\nneeds a `value`, including `exists` and `not_exists`.\n","items":{"type":"object","required":["name","enabled","conditionGroups"],"description":"A single exclusion filter. An order that matches any enabled filter is\nleft out of reporting. The server assigns `id` and `createdAt` when you\nleave them out, and sets `updatedAt` on every save. Max 20 condition\ngroups per filter.\n","properties":{"name":{"type":"string","minLength":1,"maxLength":100,"example":"Exclude POS","description":"Display name. Control / zero-width / bidi characters rejected;\nunicode letters, marks, digits, punctuation, and emoji accepted.\n","isRequired":true,"uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].name","typeLabel":"string"},"enabled":{"type":"boolean","description":"Only enabled filters exclude orders. Must be a JSON boolean, not a string.","isRequired":true,"uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].enabled","typeLabel":"boolean"},"conditionGroups":{"type":"array","minItems":1,"maxItems":20,"description":"The order is excluded when any one group matches.","items":{"type":"object","required":["logic","conditions"],"description":"Group of conditions joined by `logic`. Within a filter, groups\nare OR'd; within a group, conditions are joined by the group's\n`logic`. Max 20 conditions per group.\n","properties":{"logic":{"type":"string","enum":["and","or"],"isRequired":true,"uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].conditionGroups.items.[INDEX].logic","typeLabel":"enum\u003cstring>"},"conditions":{"type":"array","minItems":1,"maxItems":20,"items":{"type":"object","required":["field","operator"],"description":"Single condition inside a group. The server assigns `id` (a UUID) when you\nleave it out; send it back on later updates to keep the condition's identity.\n`value` is required for every operator except `exists` and `not_exists`.\n","properties":{"field":{"type":"string","enum":["sourceName","tags","value","paymentGateway"],"description":"Order field a condition is evaluated against. Each field accepts only\nthe operators that suit its type, listed under `ConditionOperator`.\n","isRequired":true,"uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].conditionGroups.items.[INDEX].conditions.items.[INDEX].field","typeLabel":"enum\u003cstring>"},"operator":{"type":"string","enum":["equals","not_equals","in","not_in","contains","not_contains","starts_with","ends_with","greater_than","less_than","greater_than_or_equals","less_than_or_equals","exists","not_exists","array_includes","array_includes_all","array_includes_any"],"description":"Comparison operator. It has to suit the field's type\n(string / array / number) — a numeric operator on a string field, such as\n`greater_than` on `sourceName`, is rejected with 400.\n","isRequired":true,"uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].conditionGroups.items.[INDEX].conditions.items.[INDEX].operator","typeLabel":"enum\u003cstring>"},"id":{"type":"string","format":"uuid","description":"Condition id. Omit on new conditions.","uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].conditionGroups.items.[INDEX].conditions.items.[INDEX].id","typeLabel":"string\u003cuuid>"},"value":{"oneOf":[{"type":"string","title":"String","description":"The value to compare against. Use a list of strings with `in`, `not_in`, and the\n`array_includes*` operators; a number with `value`; a string otherwise.\n","uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].conditionGroups.items.[INDEX].conditions.items.[INDEX].value.oneOf.0","typeLabel":"string"},{"type":"number","title":"Number","description":"The value to compare against. Use a list of strings with `in`, `not_in`, and the\n`array_includes*` operators; a number with `value`; a string otherwise.\n","uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].conditionGroups.items.[INDEX].conditions.items.[INDEX].value.oneOf.1","typeLabel":"number"},{"type":"boolean","title":"Boolean","description":"The value to compare against. Use a list of strings with `in`, `not_in`, and the\n`array_includes*` operators; a number with `value`; a string otherwise.\n","uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].conditionGroups.items.[INDEX].conditions.items.[INDEX].value.oneOf.2","typeLabel":"boolean"},{"type":"array","items":{"type":"string","uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].conditionGroups.items.[INDEX].conditions.items.[INDEX].value.oneOf.3.items.[INDEX]","typeLabel":"string"},"title":"List of strings","description":"The value to compare against. Use a list of strings with `in`, `not_in`, and the\n`array_includes*` operators; a number with `value`; a string otherwise.\n","uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].conditionGroups.items.[INDEX].conditions.items.[INDEX].value.oneOf.3","typeLabel":"string[]"}],"uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].conditionGroups.items.[INDEX].conditions.items.[INDEX].value","typeLabel":"string | number | boolean | string[]"}},"uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].conditionGroups.items.[INDEX].conditions.items.[INDEX]","typeLabel":"object"},"isRequired":true,"uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].conditionGroups.items.[INDEX].conditions","typeLabel":"object[]"},"id":{"type":"string","format":"uuid","description":"Group id. Omit on new groups; the server assigns one.","uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].conditionGroups.items.[INDEX].id","typeLabel":"string\u003cuuid>"}},"uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].conditionGroups.items.[INDEX]","typeLabel":"object"},"isRequired":true,"uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].conditionGroups","typeLabel":"object[]"},"id":{"type":"string","format":"uuid","description":"Filter id. Omit on new filters; send it back to keep the filter's identity.","uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].id","typeLabel":"string\u003cuuid>"},"createdAt":{"type":"string","format":"date-time","description":"When the filter was created. Send it back unchanged to keep it; omit it and it resets to the time of the request.","uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].createdAt","typeLabel":"string\u003cdate-time>"},"updatedAt":{"type":"string","format":"date-time","description":"Set by the server to the time of the last save. Any value you send is overwritten.","uniqueKey":"orderSettings.exclusionFilters.items.[INDEX].updatedAt","typeLabel":"string\u003cdate-time>"}},"uniqueKey":"orderSettings.exclusionFilters.items.[INDEX]","typeLabel":"object"},"uniqueKey":"orderSettings.exclusionFilters","typeLabel":"object[]"}},"uniqueKey":"orderSettings","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"monthlyCohorts":{"title":"monthlyCohorts","value":{"pixelId":"5f1e6a4f-2b7c-4d1e-9a3f-8c6b2e0d4a71","granularity":"month","measures":["orders.customers_cohort","orders.ltv_cohort_net_revenue"],"dateRange":{"start":"2026-01-01","end":"2026-03-31"},"timezone":"America/New_York","currency":"USD"}},"webOnly":{"title":"webOnly","value":{"pixelId":"5f1e6a4f-2b7c-4d1e-9a3f-8c6b2e0d4a71","granularity":"week","measures":["orders.customers_cohort","orders.cohort_cm2"],"dateRange":{"start":"2026-03-02","end":"2026-03-29"},"timezone":"Europe/London","filters":{"and":[{"field":"orders.source_name","op":"equals","value":"web"}]}}}},"exampleType":"examples"}},"exampleType":"examples"},"responses":{"08cc8cf7-2ab4-4cd5-a401-1856f17b9162":{"description":"Cohort results.","content":{"application/json":{"schema":{"type":"object","required":["results"],"properties":{"results":{"type":"array","description":"Query results. A cohort analysis always returns exactly one entry.","items":{"type":"object","properties":{"granularity":{"type":"string","enum":["none","second","minute","hour","day","week","month","quarter","year"],"description":"Time bucket for result rows. `none` returns one row per dimension combination\ninstead of a time series.\n","uniqueKey":"results.items.[INDEX].granularity","typeLabel":"enum\u003cstring>"},"dimensions":{"type":"array","description":"The dimensions the rows are broken down by. Empty when none were requested.","items":{"type":"string","uniqueKey":"results.items.[INDEX].dimensions.items.[INDEX]","typeLabel":"string"},"uniqueKey":"results.items.[INDEX].dimensions","typeLabel":"string[]"},"dateRange":{"type":"object","required":["start","end"],"description":"The range queried. A date-only `end` comes back with its end-of-day time.","properties":{"start":{"type":"string","format":"date","description":"First day of the range, as an ISO 8601 date.","example":"2026-04-01","isRequired":true,"uniqueKey":"results.items.[INDEX].dateRange.start","typeLabel":"string\u003cdate>"},"end":{"type":"string","format":"date","description":"Last day of the range, as an ISO 8601 date. Included in the results.","example":"2026-04-30","isRequired":true,"uniqueKey":"results.items.[INDEX].dateRange.end","typeLabel":"string\u003cdate>"}},"uniqueKey":"results.items.[INDEX].dateRange","typeLabel":"object"},"compareDateRange":{"type":"object","required":["start","end"],"description":"The comparison range queried. Absent when the server picked the period itself.","properties":{"start":{"type":"string","format":"date","description":"First day of the range, as an ISO 8601 date.","example":"2026-04-01","isRequired":true,"uniqueKey":"results.items.[INDEX].compareDateRange.start","typeLabel":"string\u003cdate>"},"end":{"type":"string","format":"date","description":"Last day of the range, as an ISO 8601 date. Included in the results.","example":"2026-04-30","isRequired":true,"uniqueKey":"results.items.[INDEX].compareDateRange.end","typeLabel":"string\u003cdate>"}},"uniqueKey":"results.items.[INDEX].compareDateRange","typeLabel":"object"},"measureDetails":{"oneOf":[{"type":"array","description":"One entry per requested measure.","items":{"type":"object","description":"Totals and formatting hints for one requested measure.","properties":{"measure":{"type":"string","description":"The measure id this entry describes.","uniqueKey":"results.items.[INDEX].measureDetails.oneOf.0.items.[INDEX].measure","typeLabel":"string"},"isAverage":{"type":"boolean","description":"The measure is an average, so read `primaryAvg` rather than `primarySum` as its headline value.","uniqueKey":"results.items.[INDEX].measureDetails.oneOf.0.items.[INDEX].isAverage","typeLabel":"boolean"},"isPercentage":{"type":"boolean","description":"The value is a percentage.","uniqueKey":"results.items.[INDEX].measureDetails.oneOf.0.items.[INDEX].isPercentage","typeLabel":"boolean"},"calculatedAverage":{"type":"boolean","description":"The average is calculated from the period's totals rather than averaged across rows.","uniqueKey":"results.items.[INDEX].measureDetails.oneOf.0.items.[INDEX].calculatedAverage","typeLabel":"boolean"},"success":{"type":"boolean","description":"Whether this measure was computed. When `false`, the measure's query failed\nand its totals are all `0`, so check this before treating a zero as real. The\nrequest still returns `200` and the other measures still carry their data.\n","uniqueKey":"results.items.[INDEX].measureDetails.oneOf.0.items.[INDEX].success","typeLabel":"boolean"},"primaryAvg":{"type":"number","description":"Average value over `dateRange`.","uniqueKey":"results.items.[INDEX].measureDetails.oneOf.0.items.[INDEX].primaryAvg","typeLabel":"number"},"compareAvg":{"type":"number","description":"Average value over the comparison period.","uniqueKey":"results.items.[INDEX].measureDetails.oneOf.0.items.[INDEX].compareAvg","typeLabel":"number"},"primarySum":{"type":"number","description":"Total over `dateRange`.","uniqueKey":"results.items.[INDEX].measureDetails.oneOf.0.items.[INDEX].primarySum","typeLabel":"number"},"compareSum":{"type":"number","description":"Total over the comparison period.","uniqueKey":"results.items.[INDEX].measureDetails.oneOf.0.items.[INDEX].compareSum","typeLabel":"number"},"percentDiff":{"type":"number","description":"Percent change from the comparison period to `dateRange`.","uniqueKey":"results.items.[INDEX].measureDetails.oneOf.0.items.[INDEX].percentDiff","typeLabel":"number"},"hasPacing":{"type":"boolean","description":"Pacing data is included. `true` only when you asked for `pacing` and the measure supports it.","uniqueKey":"results.items.[INDEX].measureDetails.oneOf.0.items.[INDEX].hasPacing","typeLabel":"boolean"},"preferredTrendDirection":{"type":"string","enum":["up","down"],"description":"Whether higher (`up`) or lower (`down`) values are favorable.","uniqueKey":"results.items.[INDEX].measureDetails.oneOf.0.items.[INDEX].preferredTrendDirection","typeLabel":"enum\u003cstring>"}},"uniqueKey":"results.items.[INDEX].measureDetails.oneOf.0.items.[INDEX]","typeLabel":"object"},"uniqueKey":"results.items.[INDEX].measureDetails.oneOf.0","typeLabel":"object[]"},{"type":"null","description":"One entry per requested measure.","items":{"type":"object","description":"Totals and formatting hints for one requested measure.","properties":{"measure":{"type":"string","description":"The measure id this entry describes."},"isAverage":{"type":"boolean","description":"The measure is an average, so read `primaryAvg` rather than `primarySum` as its headline value."},"isPercentage":{"type":"boolean","description":"The value is a percentage."},"calculatedAverage":{"type":"boolean","description":"The average is calculated from the period's totals rather than averaged across rows."},"success":{"type":"boolean","description":"Whether this measure was computed. When `false`, the measure's query failed\nand its totals are all `0`, so check this before treating a zero as real. The\nrequest still returns `200` and the other measures still carry their data.\n"},"primaryAvg":{"type":"number","description":"Average value over `dateRange`."},"compareAvg":{"type":"number","description":"Average value over the comparison period."},"primarySum":{"type":"number","description":"Total over `dateRange`."},"compareSum":{"type":"number","description":"Total over the comparison period."},"percentDiff":{"type":"number","description":"Percent change from the comparison period to `dateRange`."},"hasPacing":{"type":"boolean","description":"Pacing data is included. `true` only when you asked for `pacing` and the measure supports it."},"preferredTrendDirection":{"type":"string","enum":["up","down"],"description":"Whether higher (`up`) or lower (`down`) values are favorable."}}},"uniqueKey":"results.items.[INDEX].measureDetails.oneOf.1","typeLabel":"null"}],"uniqueKey":"results.items.[INDEX].measureDetails","typeLabel":"object[] | null"},"data":{"oneOf":[{"type":"object","properties":{"primary":{"type":"array","description":"Rows for `dateRange`.","items":{"type":"object","description":"One row of query data. Carries the requested dimension values keyed by dimension\nid, and one numeric value per measure keyed by measure id. Time-series queries\n(`granularity` other than `none`) add a `dt` bucket.\n","additionalProperties":true,"properties":{"dt":{"type":"string","description":"Start of the time bucket, e.g. `2026-04-01T00:00:00.000`. Present when `granularity` isn't `none`.","uniqueKey":"results.items.[INDEX].data.oneOf.0.primary.items.[INDEX].dt","typeLabel":"string"},"start":{"type":"string","uniqueKey":"results.items.[INDEX].data.oneOf.0.primary.items.[INDEX].start","typeLabel":"string"},"end":{"type":"string","uniqueKey":"results.items.[INDEX].data.oneOf.0.primary.items.[INDEX].end","typeLabel":"string"}},"uniqueKey":"results.items.[INDEX].data.oneOf.0.primary.items.[INDEX]","typeLabel":"object"},"uniqueKey":"results.items.[INDEX].data.oneOf.0.primary","typeLabel":"object[]"},"compare":{"type":"array","description":"Rows for `compareDateRange`. Left out of time-series responses when you didn't\nsend a `compareDateRange`.\n","items":{"type":"object","description":"One row of query data. Carries the requested dimension values keyed by dimension\nid, and one numeric value per measure keyed by measure id. Time-series queries\n(`granularity` other than `none`) add a `dt` bucket.\n","additionalProperties":true,"properties":{"dt":{"type":"string","description":"Start of the time bucket, e.g. `2026-04-01T00:00:00.000`. Present when `granularity` isn't `none`.","uniqueKey":"results.items.[INDEX].data.oneOf.0.compare.items.[INDEX].dt","typeLabel":"string"},"start":{"type":"string","uniqueKey":"results.items.[INDEX].data.oneOf.0.compare.items.[INDEX].start","typeLabel":"string"},"end":{"type":"string","uniqueKey":"results.items.[INDEX].data.oneOf.0.compare.items.[INDEX].end","typeLabel":"string"}},"uniqueKey":"results.items.[INDEX].data.oneOf.0.compare.items.[INDEX]","typeLabel":"object"},"uniqueKey":"results.items.[INDEX].data.oneOf.0.compare","typeLabel":"object[]"}},"uniqueKey":"results.items.[INDEX].data.oneOf.0","typeLabel":"object"},{"type":"null","uniqueKey":"results.items.[INDEX].data.oneOf.1","typeLabel":"null"}],"uniqueKey":"results.items.[INDEX].data","typeLabel":"object | null"}},"uniqueKey":"results.items.[INDEX]","typeLabel":"object"},"isRequired":true,"uniqueKey":"results","typeLabel":"object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"monthlyCohorts":{"title":"monthlyCohorts","value":{"results":[{"granularity":"month","dimensions":[],"dateRange":{"start":"2026-01-01","end":"2026-03-31T23:59:59.999"},"measureDetails":[],"data":{"primary":[{"cohort_month":"2026-01-01","order_month":"2026-01-01","orders.customers_cohort":"412","orders.ltv_cohort_net_revenue":"68.40"},{"cohort_month":"2026-01-01","order_month":"2026-02-01","orders.customers_cohort":"412","orders.ltv_cohort_net_revenue":"79.15"},{"cohort_month":"2026-01-01","order_month":"2026-03-01","orders.customers_cohort":"412","orders.ltv_cohort_net_revenue":"86.02"},{"cohort_month":"2026-02-01","order_month":"2026-02-01","orders.customers_cohort":"377","orders.ltv_cohort_net_revenue":"71.90"},{"cohort_month":"2026-02-01","order_month":"2026-03-01","orders.customers_cohort":"377","orders.ltv_cohort_net_revenue":"80.33"},{"cohort_month":"2026-03-01","order_month":"2026-03-01","orders.customers_cohort":"455","orders.ltv_cohort_net_revenue":"66.75"}]}}]}}},"exampleType":"examples"}},"exampleType":"examples"},"f5130320-8e36-450f-9329-86de64f9302b":{"description":"Validation error. Includes an `errors` array with per-field detail.","content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","description":"Human-readable error message.","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"errors":{"type":"array","description":"Per-field validation errors (present on 400 responses).","items":{"type":"object","properties":{"message":{"type":"string","uniqueKey":"errors.items.[INDEX].message","typeLabel":"string"},"key":{"type":"string","uniqueKey":"errors.items.[INDEX].key","typeLabel":"string"},"path":{"type":"array","items":{"type":"string","uniqueKey":"errors.items.[INDEX].path.items.[INDEX]","typeLabel":"string"},"uniqueKey":"errors.items.[INDEX].path","typeLabel":"string[]"}},"uniqueKey":"errors.items.[INDEX]","typeLabel":"object"},"uniqueKey":"errors","typeLabel":"object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"message":"\u003cstring>","errors":[{"message":"\u003cstring>","key":"\u003cstring>","path":["\u003cstring>"]}]}}},"exampleType":"generated"}},"exampleType":"generated"},"965a3a3a-3edf-40f2-b685-e9f3e03e7971":{"description":"The `x-api-key` or `x-pixel-id` header is missing. The request is rejected\nbefore it reaches the API, and the body is `{\"message\": \"Unauthorized\"}`.\nA key that is present but not accepted returns `403`, not `401`.\n","content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","description":"Human-readable error message.","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"errors":{"type":"array","description":"Per-field validation errors (present on 400 responses).","items":{"type":"object","properties":{"message":{"type":"string","uniqueKey":"errors.items.[INDEX].message","typeLabel":"string"},"key":{"type":"string","uniqueKey":"errors.items.[INDEX].key","typeLabel":"string"},"path":{"type":"array","items":{"type":"string","uniqueKey":"errors.items.[INDEX].path.items.[INDEX]","typeLabel":"string"},"uniqueKey":"errors.items.[INDEX].path","typeLabel":"string[]"}},"uniqueKey":"errors.items.[INDEX]","typeLabel":"object"},"uniqueKey":"errors","typeLabel":"object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"message":"\u003cstring>","errors":[{"message":"\u003cstring>","key":"\u003cstring>","path":["\u003cstring>"]}]}}},"exampleType":"generated"}},"exampleType":"generated"},"0711ba3f-3fa4-4c7a-ae26-18c0c651a314":{"description":"The key was rejected, or it is valid but not allowed to do this. Either:\n\n- the key is unknown, revoked, or expired, or the pixel is inactive — the body is\n `{\"Message\": \"User is not authorized to access this resource with an explicit deny\n in an identity-based policy\"}` (note the capital `M`);\n- the key doesn't carry the scope this endpoint needs, or the body `pixelId` doesn't\n match the `x-pixel-id` header — the body is `{\"message\": \"…\"}` as described below.\n","content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","description":"Human-readable error message.","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"errors":{"type":"array","description":"Per-field validation errors (present on 400 responses).","items":{"type":"object","properties":{"message":{"type":"string","uniqueKey":"errors.items.[INDEX].message","typeLabel":"string"},"key":{"type":"string","uniqueKey":"errors.items.[INDEX].key","typeLabel":"string"},"path":{"type":"array","items":{"type":"string","uniqueKey":"errors.items.[INDEX].path.items.[INDEX]","typeLabel":"string"},"uniqueKey":"errors.items.[INDEX].path","typeLabel":"string[]"}},"uniqueKey":"errors.items.[INDEX]","typeLabel":"object"},"uniqueKey":"errors","typeLabel":"object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"message":"\u003cstring>","errors":[{"message":"\u003cstring>","key":"\u003cstring>","path":["\u003cstring>"]}]}}},"exampleType":"generated"}},"exampleType":"generated"},"4792c888-8848-476e-9ee0-db65315f8cbd":{"description":"The query failed. The body carries the underlying failure message.\n","content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","description":"Human-readable error message.","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"errors":{"type":"array","description":"Per-field validation errors (present on 400 responses).","items":{"type":"object","properties":{"message":{"type":"string","uniqueKey":"errors.items.[INDEX].message","typeLabel":"string"},"key":{"type":"string","uniqueKey":"errors.items.[INDEX].key","typeLabel":"string"},"path":{"type":"array","items":{"type":"string","uniqueKey":"errors.items.[INDEX].path.items.[INDEX]","typeLabel":"string"},"uniqueKey":"errors.items.[INDEX].path","typeLabel":"string[]"}},"uniqueKey":"errors.items.[INDEX]","typeLabel":"object"},"uniqueKey":"errors","typeLabel":"object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"message":"\u003cstring>","errors":[{"message":"\u003cstring>","key":"\u003cstring>","path":["\u003cstring>"]}]}}},"exampleType":"generated"}},"exampleType":"generated"}},"security":{"f19e0b22-afd0-4760-b88e-dce1773111cb":{"apiKey":{"type":"apiKey","in":"header","name":"x-api-key","description":"Your Upstack API key. Starts with `upstack_`.","scopes":[],"schemeName":"apiKey"},"pixelId":{"type":"apiKey","in":"header","name":"x-pixel-id","description":"The pixel id the request targets.","scopes":[],"schemeName":"pixelId"}}},"servers":{"2bbb3e85-633d-4371-b828-47a29d5899c5":{"url":"https://api.upstackdata.com","description":"Production"}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"apiKey","in":"header","name":"x-api-key","description":"Your Upstack API key. Starts with `upstack_`.","scopes":[],"schemeName":"apiKey"},"schema":{"title":"x-api-key","type":"string","description":"Your Upstack API key. Starts with `upstack_`.","isRequired":true,"typeLabel":"string","deprecated":false},"schemeName":"apiKey","name":"x-api-key"},{"scheme":{"type":"apiKey","in":"header","name":"x-pixel-id","description":"The pixel id the request targets.","scopes":[],"schemeName":"pixelId"},"schema":{"title":"x-pixel-id","type":"string","description":"The pixel id the request targets.","isRequired":true,"typeLabel":"string","deprecated":false},"schemeName":"pixelId","name":"x-pixel-id"}],"title":"apiKey \u0026 pixelId"}]},"originalFileLocation":"api-reference/openapi.yaml"},"subdomain":"upstackdata-afbed50d","siteName":"Upstack Data","title":"Run a cohort analysis for customer LTV and retention - Upstack Data","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-11-04T13:39:43.847Z","originalFileLocation":"api-reference/analytics/run-a-cohort-analysis.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=\"light\";if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"light\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Group customers by the week, month, or year of their first order and track cumulative revenue per customer, retention, AOV, and contribution margin over time.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Upstack Data\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/upstackdata-afbed50d/3BK6qL6Jr5lRaaY0/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/upstackdata-afbed50d/3BK6qL6Jr5lRaaY0/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/upstackdata-afbed50d/3BK6qL6Jr5lRaaY0/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/upstackdata-afbed50d/3BK6qL6Jr5lRaaY0/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/upstackdata-afbed50d/3BK6qL6Jr5lRaaY0/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/upstackdata-afbed50d/3BK6qL6Jr5lRaaY0/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/upstackdata-afbed50d/3BK6qL6Jr5lRaaY0/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/upstackdata-afbed50d/3BK6qL6Jr5lRaaY0/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/upstackdata-afbed50d/3BK6qL6Jr5lRaaY0/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Run a cohort analysis for customer LTV and retention - Upstack Data\">\u003cmeta data-mint-head property=\"og:description\" content=\"Group customers by the week, month, or year of their first order and track cumulative revenue per customer, retention, AOV, and contribution margin over time.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Upstack Data\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.upstackdata.com/api-reference/analytics/run-a-cohort-analysis\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://upstackdata-afbed50d.mintlify.site/_mintlify/api/og/v2?division=ANALYTICS\u0026amp;title=Run+a+cohort+analysis+for+customer+LTV+and+retention\u0026amp;description=Group+customers+by+the+week%2C+month%2C+or+year+of+their+first+order+and+track+cumulative+revenue+per+customer%2C+retention%2C+AOV%2C+and+contribution+margin+over+time.\u0026amp;theme=b279b8bf440b9d86f43d4b66\u0026amp;signature=cdf410595a7832195218d84347becaf8f2f0692a232b64020f6ec1035597a19b\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Run a cohort analysis for customer LTV and retention - Upstack Data\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Group customers by the week, month, or year of their first order and track cumulative revenue per customer, retention, AOV, and contribution margin over time.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://upstackdata-afbed50d.mintlify.site/_mintlify/api/og/v2?division=ANALYTICS\u0026amp;title=Run+a+cohort+analysis+for+customer+LTV+and+retention\u0026amp;description=Group+customers+by+the+week%2C+month%2C+or+year+of+their+first+order+and+track+cumulative+revenue+per+customer%2C+retention%2C+AOV%2C+and+contribution+margin+over+time.\u0026amp;theme=b279b8bf440b9d86f43d4b66\u0026amp;signature=cdf410595a7832195218d84347becaf8f2f0692a232b64020f6ec1035597a19b\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/upstackdata-afbed50d/3BK6qL6Jr5lRaaY0/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Upstack Data\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#4230b4\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.upstackdata.com/api-reference/analytics/run-a-cohort-analysis\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/analytics/run-a-cohort-analysis.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.upstackdata.com/#organization\",\"name\":\"Upstack Data\",\"url\":\"https://docs.upstackdata.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/upstackdata-afbed50d/40dgTTn1PLjePhJa/logo/light.svg?fit=max\u0026auto=format\u0026n=40dgTTn1PLjePhJa\u0026q=85\u0026s=598c05fb87860ddc1b6b7640b41e136c\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.upstackdata.com#website\",\"name\":\"Upstack Data\",\"url\":\"https://docs.upstackdata.com\",\"publisher\":{\"@id\":\"https://docs.upstackdata.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.upstackdata.com/api-reference/analytics/run-a-cohort-analysis#webpage\",\"url\":\"https://docs.upstackdata.com/api-reference/analytics/run-a-cohort-analysis\",\"name\":\"Run a cohort analysis for customer LTV and retention\",\"description\":\"Group customers by the week, month, or year of their first order and track cumulative revenue per customer, retention, AOV, and contribution margin over time.\",\"dateModified\":\"2026-11-04T13:39:43.847Z\",\"isPartOf\":{\"@id\":\"https://docs.upstackdata.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.upstackdata.com/api-reference/analytics/run-a-cohort-analysis#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.upstackdata.com/api-reference/analytics/run-a-cohort-analysis#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"ANALYTICS\",\"item\":\"https://docs.upstackdata.com/api-reference/analytics/run-an-analytics-query\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Run a cohort analysis for customer LTV and retention\",\"item\":\"https://docs.upstackdata.com/api-reference/analytics/run-a-cohort-analysis\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.upstackdata.com/api-reference/analytics/run-a-cohort-analysis#apireference\",\"headline\":\"Run a cohort analysis for customer LTV and retention\",\"name\":\"Run a cohort analysis for customer LTV and retention\",\"description\":\"Group customers by the week, month, or year of their first order and track cumulative revenue per customer, retention, AOV, and contribution margin over time.\",\"url\":\"https://docs.upstackdata.com/api-reference/analytics/run-a-cohort-analysis\",\"mainEntityOfPage\":{\"@id\":\"https://docs.upstackdata.com/api-reference/analytics/run-a-cohort-analysis#webpage\"},\"dateModified\":\"2026-11-04T13:39:43.847Z\",\"keywords\":\"cohort analysis API, customer lifetime value, LTV, retention, Upstack Data API\",\"publisher\":{\"@id\":\"https://docs.upstackdata.com/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.upstackdata.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Upstack Data\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"Upstack Data\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/api-reference/analytics/run-a-cohort-analysis.md","siteName":"Upstack Data","nav":{"global":null,"tabs":[{"tab":"Documentation","pages":[{"title":"Documentation","href":"/get-started/overview"}]},{"tab":"Pixel","pages":[{"title":"Pixel","href":"/pixel"}]},{"tab":"Event Tracking","pages":[{"title":"Event Tracking","href":"/event-tracking"}]},{"tab":"Metrics","pages":[{"title":"Metrics","href":"/reference/metrics"}]},{"tab":"API","groups":[{"group":"OVERVIEW","pages":[{"title":"Introduction","sidebarTitle":"Introduction","href":"/api-reference/introduction"},{"title":"Errors","sidebarTitle":"Errors","href":"/api-reference/errors"},{"title":"Rate limiting","sidebarTitle":"Rate limiting","href":"/api-reference/rate-limiting"}]},{"group":"ACCOUNT","pages":[{"title":"Get account details, owners, and subscription plan","deprecated":null,"version":null,"sidebarTitle":"Get the account","openapi":"/api-reference/openapi.yaml get /accounts/api/account","href":"/api-reference/account/get-the-account"},{"title":"Rename the account","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml patch /accounts/api/account","href":"/api-reference/account/rename-the-account"},{"title":"Get order settings and order exclusion filters","deprecated":null,"version":null,"sidebarTitle":"Get order settings","openapi":"/api-reference/openapi.yaml get /accounts/api/account/settings/order","href":"/api-reference/account/get-order-settings"},{"title":"Replace order settings and order exclusion filters","deprecated":null,"version":null,"sidebarTitle":"Replace order settings","openapi":"/api-reference/openapi.yaml put /accounts/api/account/settings/order","href":"/api-reference/account/replace-order-settings"}]},{"group":"CATALOG","pages":[{"title":"List available measures","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /db-mgmt/api/measures","href":"/api-reference/catalog/list-available-measures"},{"title":"List filter fields for analytics queries","deprecated":null,"version":null,"sidebarTitle":"List filter fields","openapi":"/api-reference/openapi.yaml get /db-mgmt/api/filters","href":"/api-reference/catalog/list-filter-fields"}]},{"group":"ANALYTICS","pages":[{"title":"Run an analytics query with measures and dimensions","deprecated":null,"version":null,"sidebarTitle":"Run an analytics query","openapi":"/api-reference/openapi.yaml post /db-mgmt/api/query","href":"/api-reference/analytics/run-an-analytics-query"},{"title":"Run an attribution query by UTM source, campaign, or ad","description":"See which UTM source, campaign, ad set, or ad gets credit for your orders or conversion events, with revenue, new customers, ad spend, and ROAS on every row.","deprecated":null,"version":null,"sidebarTitle":"Run an attribution query","openapi":"/api-reference/openapi.yaml post /db-mgmt/api/query-attribution","href":"/api-reference/analytics/run-an-attribution-query"},{"title":"Run a cohort analysis for customer LTV and retention","deprecated":null,"version":null,"sidebarTitle":"Run a cohort analysis","openapi":"/api-reference/openapi.yaml post /db-mgmt/api/query-cohort-analysis","href":"/api-reference/analytics/run-a-cohort-analysis"},{"title":"List channel entities with optional metrics","description":"List ad accounts, campaigns, ad sets, or ads from the ads-platform\nintegrations connected to your pixel, with optional metric aggregation\nover a date range.\n\n**Required scope:** `analytics:read`.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /db-mgmt/api/query-channel-details","href":"/api-reference/analytics/list-channel-entities-with-optional-metrics"},{"title":"List ads with daily spend and performance metrics","deprecated":null,"version":null,"sidebarTitle":"List ads with metrics","openapi":"/api-reference/openapi.yaml post /db-mgmt/api/query-ads","href":"/api-reference/analytics/list-ads-with-optional-daily-metrics"}]},{"group":"DASHBOARDS","pages":[{"title":"List dashboard views for a pixel","deprecated":null,"version":null,"sidebarTitle":"List dashboard views","openapi":"/api-reference/openapi.yaml get /accounts/api/dashboard/views","href":"/api-reference/dashboards/list-dashboard-views"},{"title":"Get a dashboard view and its widget configuration","deprecated":null,"version":null,"sidebarTitle":"Get a dashboard view","openapi":"/api-reference/openapi.yaml get /accounts/api/dashboard/views/{dashboardViewId}","href":"/api-reference/dashboards/get-a-dashboard-view"},{"title":"Create a dashboard view from a full configuration","deprecated":null,"version":null,"sidebarTitle":"Create a dashboard view","openapi":"/api-reference/openapi.yaml post /accounts/api/dashboard/views","href":"/api-reference/dashboards/create-a-dashboard-view"},{"title":"Build a dashboard from a list of measures","deprecated":null,"version":null,"sidebarTitle":"Build a dashboard from a measure list","openapi":"/api-reference/openapi.yaml post /accounts/api/dashboard/views/from-preset","href":"/api-reference/dashboards/build-a-dashboard-from-a-measure-list-preset"},{"title":"Duplicate a dashboard view","deprecated":null,"version":null,"sidebarTitle":"Duplicate a dashboard view","openapi":"/api-reference/openapi.yaml post /accounts/api/dashboard/views/{dashboardViewId}/copy","href":"/api-reference/dashboards/duplicate-a-dashboard-view"},{"title":"Update a dashboard view","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml patch /accounts/api/dashboard/views/{dashboardViewId}","href":"/api-reference/dashboards/update-a-dashboard-view"},{"title":"Delete a dashboard view","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml delete /accounts/api/dashboard/views/{dashboardViewId}","href":"/api-reference/dashboards/delete-a-dashboard-view"}]},{"group":"COSTS","pages":[{"title":"Get cost configuration for COGS, shipping, and fees","deprecated":null,"version":null,"sidebarTitle":"Get cost configuration","openapi":"/api-reference/openapi.yaml get /accounts/api/costs","href":"/api-reference/costs/get-cost-configuration"},{"title":"Update the global product override","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml put /accounts/api/costs/global-product-override","href":"/api-reference/costs/update-the-global-product-override"},{"title":"Update shipping cost settings","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml put /accounts/api/costs/shipping-settings","href":"/api-reference/costs/update-shipping-cost-settings"},{"title":"Add a cost line","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /accounts/api/costs/lines","href":"/api-reference/costs/add-a-cost-line"},{"title":"Update an order, payment, shipping, or recurring cost line","deprecated":null,"version":null,"sidebarTitle":"Update a cost line","openapi":"/api-reference/openapi.yaml put /accounts/api/costs/lines/{lineId}","href":"/api-reference/costs/update-a-cost-line"},{"title":"Delete a cost line","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml delete /accounts/api/costs/lines/{lineId}","href":"/api-reference/costs/delete-a-cost-line"}]},{"group":"PRODUCTS","pages":[{"title":"Search products","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /accounts/api/products/search","href":"/api-reference/products/search-products"},{"title":"Get a product variant","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /accounts/api/products/{productId}/{variantId}/cost","href":"/api-reference/products/get-a-product-variant"},{"title":"Set a variant's handling fee","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml put /accounts/api/products/{productId}/{variantId}/handling-fee","href":"/api-reference/products/set-a-variants-handling-fee"},{"title":"Add a COGS line to a product variant","deprecated":null,"version":null,"sidebarTitle":"Add a COG line","openapi":"/api-reference/openapi.yaml post /accounts/api/products/{productId}/{variantId}/cogs","href":"/api-reference/products/add-a-cog-line-to-a-variant"},{"title":"Update a COGS line on a product variant","deprecated":null,"version":null,"sidebarTitle":"Update a COG line","openapi":"/api-reference/openapi.yaml put /accounts/api/products/{productId}/{variantId}/cogs/{cogId}","href":"/api-reference/products/update-a-cog-line"},{"title":"Delete a COGS line from a product variant","deprecated":null,"version":null,"sidebarTitle":"Delete a COG line","openapi":"/api-reference/openapi.yaml delete /accounts/api/products/{productId}/{variantId}/cogs/{cogId}","href":"/api-reference/products/delete-a-cog-line"}]},{"group":"EVENTS","pages":[{"title":"Send events via Upstack Conversion API","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /tr/api/events","href":"/api-reference/events/send-events-via-upstack-conversion-api"}]}]},{"tab":"CLI","pages":[{"title":"CLI","href":"/cli/install"}]}]},"basePath":"","title":"Run a cohort analysis for customer LTV and retention - Upstack Data","buildId":"dpl_DqYu5MPb49gWBBbUGgpHQUmCHY3P","deploymentId":"dpl_DqYu5MPb49gWBBbUGgpHQUmCHY3P","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-CybtLBIt.js","utils-BMLj2fvV.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-B6In562Y.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-Dr8Mfhp9.js","snippetPresets-2rmQvMVl.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","conditional-requirements-CFM0id0Q.js","ApiExamples-WMqJYdZj.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-CJ-MlPHu.js","shallow-dY3TMRCk.js","getApiPlaygroundDisplay-v-1B2bKm.js","CodeSnippet-BDhiTB7U.js","CodeSnippets-D9hnzQcS.js","Page-C4GwDT3_.js","getPastedJson-Th2V45jI.js","icon-BQXch1W9.js","MethodPill-BCqUneP3.js","DuplicateIcon-Q_-bhurZ.js","createIcon-DUjLHRqp.js","DynamicMarkdown-B-f2cqXQ.js","SectionHeading-Da5NsV4v.js","axios-vUo_bRtp.js","Markdown-D13FWkIM.js","clsx-D3Isdib3.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-C-XZBk9h.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink--qIqmmVG.js"]}