\n\n```\n\n### 2. Identify the person once they sign in\nTies the anonymous session to a real identity. Use their **email** as the id — Banchurn merges\npre-signup page views into it.\n\n```js\nwindow.banchurn.identify('user@example.com', { name: 'Jane Doe', plan: 'pro' });\n```\n\n### 3. Track the moments that matter\n```js\nwindow.banchurn.track('upgraded_plan', { from: 'free', to: 'pro', mrr: 49 });\n```\n\n### Verify it landed\nOpen **Dashboard → Live / Events** (rows appear within a second or two), or hit the endpoint directly:\n\n```bash\ncurl -s -X POST \"https://api.banchurn.com/api/track\" \\\n -H \"content-type: application/json\" \\\n -H \"x-api-key: YOUR_INGESTION_KEY\" \\\n -d '{\"eventName\":\"Signed Up\",\"visitorId\":\"test@example.com\",\"properties\":{\"plan\":\"free\"}}'\n```\n\nNothing showing up? Check the key is an **ingestion** key, the `host` has no trailing slash,\nand that `banchurn-analytics.js` actually loaded (Network tab, not ad-blocked).\n\nNext: the [JavaScript SDK](#tag/javascript-sdk) in depth, or [Server-side events and identity](#tag/server-side-events-and-identity) for events you must be able to trust."
},
{
"name": "JavaScript SDK",
"description": "The drop-in auto-tracker (`banchurn-analytics.js`) is the fastest way to instrument any web app.\nConfigure it **before** it loads, and it handles the rest.\n\n### What it captures automatically\n- Page views and route changes\n- Clicks and form submissions\n- Session boundaries (and optional session recording)\n- Anonymous → known identity resolution\n\n### Configuration\n`window.BanchurnConfig` must be set on the page before the script tag runs.\n\n```html\n\n\n```\n\n### Identify\nCall as soon as you know who the visitor is. The id should be their **email** so anonymous\nsessions merge into the known person.\n\n```js\nwindow.banchurn.identify('user@example.com', { name: 'Jane Doe', plan: 'pro' });\n```\n\n### Track a custom event\n```js\nwindow.banchurn.track('upgraded_plan', { from: 'free', to: 'pro', mrr: 49 });\n```\n\n### React / Next.js\nPut the two script tags in your root shell (`app/layout.tsx` or `index.html`) using `next/script`,\nand set `BanchurnConfig` with `strategy=\"beforeInteractive\"`:\n\n```tsx\nimport Script from \"next/script\";\n\nexport default function RootLayout({ children }: { children: React.ReactNode }) {\n const key = process.env.NEXT_PUBLIC_BANCHURN_KEY;\n const host = process.env.NEXT_PUBLIC_BANCHURN_HOST ?? \"https://api.banchurn.com\";\n return (\n \n \n {children}\n \n \n \n \n );\n}\n```\n\nFor events that gate revenue or email (signup, subscription), also fire them server-side where\nthey are guaranteed — see [Server-side events and identity](#tag/server-side-events-and-identity)."
},
{
"name": "Server-side events and identity",
"description": "Client tracking is best-effort (ad-blockers, closed tabs). For events that gate revenue or\ntrigger email, fire them from your backend with the same ingestion key in the `x-api-key` header.\n\n### The visitor model\nEvery event belongs to a `visitorId` — any stable string you choose. **Email is ideal**: Banchurn\nmerges the anonymous web session into it, so pre-signup activity attaches to the right person.\nCall `/api/identify` with `previousVisitorId` to merge an anonymous id into a known one.\n\n### Identify — attach or refresh traits\n```http\nPOST https://api.banchurn.com/api/identify\nContent-Type: application/json\nx-api-key: YOUR_INGESTION_KEY\n\n{ \"visitorId\": \"user@example.com\",\n \"traits\": { \"email\": \"user@example.com\", \"name\": \"Jane\", \"plan\": \"pro\" } }\n```\n\n### Track — record an event\n```http\nPOST https://api.banchurn.com/api/track\nContent-Type: application/json\nx-api-key: YOUR_INGESTION_KEY\n\n{ \"eventName\": \"order_paid\",\n \"visitorId\": \"user@example.com\",\n \"properties\": { \"amount\": 149.0, \"currency\": \"USD\", \"orderId\": 1042 } }\n```\n\nEvents are auto-categorised server-side (e.g. `order_paid` → *Revenue*). Special property keys\n`revenue`/`amount`, `currency`, and `$utm_*` are captured for attribution.\n\n### A tiny Node helper\n```js\nconst HOST = process.env.BANCHURN_HOST ?? \"https://api.banchurn.com\";\nconst headers = { \"Content-Type\": \"application/json\", \"x-api-key\": process.env.BANCHURN_API_KEY };\n\nexport const banchurnIdentify = (visitorId, traits) =>\n fetch(`${HOST}/api/identify`, { method: \"POST\", headers, body: JSON.stringify({ visitorId, traits }) });\n\nexport const banchurnTrack = (eventName, visitorId, properties = {}) =>\n fetch(`${HOST}/api/track`, { method: \"POST\", headers, body: JSON.stringify({ eventName, visitorId, properties }) });\n```\n\n### The events worth firing\nA *variety* of well-named events is what lets the intelligence engine build meaningful feature\ngroups, flows, and anomalies. Keyed by email:\n\n| Moment | Call | Why it matters |\n|---|---|---|\n| Signup complete | `track(\"Signed Up\", …)` | Fires the **welcome** email (Triggered campaign) |\n| Onboarding step done | `track(\"onboarding_completed\", …)` | Activation signal |\n| First core action | `track(\"_used\", …)` | Sticky-feature / flow analysis |\n| Plan upgrade | `identify(email,{plan})` + `track(\"plan_upgraded\", …)` | Revenue + trait-change trigger |\n| Subscription cancel | `identify(email,{ status:\"cancelled\" })` | **Strongest churn signal** |\n\n> **Event names must match campaign triggers exactly.** A welcome campaign triggered on `Signed Up`\n> only fires for the literal string `\"Signed Up\"` — triggers are case- and spelling-sensitive.\n> (The intelligence engine is tolerant; triggers are exact.)"
},
{
"name": "Bulk import and Stripe",
"description": "Backfill history and sync revenue. These use **management auth** — a JWT plus `x-org-id` — so\nrun them server-side only, never from a browser.\n\n### Get a session token\n```http\nPOST https://api.banchurn.com/api/auth/login\nContent-Type: application/json\n\n{ \"email\": \"you@company.com\", \"password\": \"…\" }\n```\nReturns `{ \"token\": \"…\", \"organization\": { \"id\": \"…\", \"apiKey\": \"…\" } }`. Use `token` as the\nbearer and `organization.id` as `x-org-id`.\n\n### Bulk import users, then events\nUpsert up to 10,000 users per call (creates new, merges traits for existing). Import **users**\nbefore their **events** — events match to existing users by email.\n\n```http\nPOST https://api.banchurn.com/api/engage/import/users\nAuthorization: Bearer YOUR_JWT\nx-org-id: YOUR_ORG_ID\nContent-Type: application/json\n\n{ \"users\": [ { \"email\": \"john@example.com\", \"name\": \"John Doe\", \"plan\": \"pro\" } ] }\n```\n\nThen `POST /api/engage/import/events`, and poll `GET /api/engage/import/status`. Full schemas are\nin the **Bulk Import** section of this reference.\n\n### Stripe — revenue & subscription sync\nPoint a Stripe webhook at Banchurn using your org **secret** `apiKey` (Dashboard → Settings —\n*not* an ingestion key):\n\n```\nhttps://api.banchurn.com/api/engage/webhooks/stripe?key=YOUR_ORG_APIKEY\n```\n\nSubscribe to `customer.created/updated`, `customer.subscription.created/updated/deleted`,\n`invoice.paid`, `charge.refunded`, and `customer.subscription.trial_will_end`. Banchurn syncs\ncustomers, MRR, invoices, refunds, and trial endings into visitor profiles automatically."
},
{
"name": "Enrichment and data sources",
"description": "Segments, churn scores, and personalization are only as good as what Banchurn knows about a person.\n**Data sources** top that knowledge up from outside your event stream; **merge tags** spend it back\ninside your messages.\n\n### Two kinds of source\nCreate these under **Data Sources** (API: `/api/engage/data-sources`):\n- **Endpoint** (`type: endpoint`) — Banchurn `GET`s a JSON URL on a schedule and upserts visitors by\n email. A `mapping` object lines your source columns up with Banchurn fields, e.g.\n `{ \"email\": \"customer_email\", \"name\": \"full_name\" }`. Hit **Test** to preview rows and columns\n first, then **Sync now** or let the schedule (`hourly` / `every_6h` / `daily` / `weekly`) run it.\n- **Stripe** (`type: stripe`) — point it at your **own** Stripe secret key (`stripeApiKey`) and\n Banchurn polls subscriptions, matching each to a visitor by email.\n\n### What Stripe enrichment writes\nEvery matched visitor gets these traits — normalized across billing intervals and legacy / multi-item\nsubscriptions, so no custom integration is needed:\n\n| Trait | Meaning |\n|---|---|\n| `plan` | price nickname / id (or product) of the first subscription item |\n| `subscription_status` | Stripe status (`active`, `trialing`, `past_due`, `canceled`, …) |\n| `mrr` | monthly-normalized recurring revenue, summed across items |\n| `current_period_end` | when the subscription next renews (ISO) |\n| `trial_end` | when the trial ends, if any (ISO) |\n| `stripe_customer_id` | the Stripe customer id |\n\nThose traits immediately power `plan` / `mrr` / `status` **segments**, sharpen churn scoring, and\nfill the `{{subscription.*}}` merge tags below. Prefer webhooks to polling? Point Stripe at the org\nwebhook in [Bulk import and Stripe](#tag/bulk-import-and-stripe) instead.\n\n### Personalization merge tags\nTemplates and campaign subjects interpolate `{{dot.path}}` variables from a standard context. Every\nblock is optional and degrades to blank rather than breaking a send:\n\n| Namespace | Examples |\n|---|---|\n| `{{visitor.*}}` | `name`, `firstName`, `email`, `country`, `city`, `totalRevenue`, `traits.*` |\n| `{{account.*}}` | `name`, `plan`, `stage`, `tier`, `score`, `industry`, `size` |\n| `{{product.*}}` | `name` (your app / brand), `url` |\n| `{{stats.*}}` | `totalEvents`, `eventsLast7d`, `lastEventName`, `lastEventAt`, `daysSinceLastSeen` |\n| `{{event.*}}` | `name`, `properties.*` — the firing event (triggered sends only) |\n| `{{digest.*}}` | `rangeLabel`, `totalEvents`, `topEvents[]`, `summaryHtml` (pre-rendered) |\n| `{{org.name}}` | your organization name |\n| `{{subscription.*}}` | `plan`, `status`, `mrr`, `renews_at`, `trial_ends` — from Stripe enrichment |\n| `{{custom.}}` | any visitor trait by key (e.g. `{{custom.plan}}`) |\n\nSo a recurring digest can greet `{{visitor.firstName}}`, drop in `{{digest.summaryHtml}}`, and note\nthat their plan renews on `{{subscription.renews_at}}` — each filled per recipient at send time."
},
{
"name": "MCP and AI access",
"description": "Banchurn ships a **Model Context Protocol** server so AI agents (Claude, and any MCP client) can\nquery analytics, segments, campaigns, automations, and churn through the management API.\n\n### Install\n```bash\ncd mcp && npm install\nclaude mcp add banchurn-mcp -- node /path/to/banchurn/mcp/index.js\n```\n\n### Configure\nPoint it at your org with environment variables:\n\n```env\nBANCHURN_API_URL=https://api.banchurn.com\nBANCHURN_API_TOKEN=YOUR_JWT\nBANCHURN_ORG_ID=YOUR_ORG_ID\n```\n\nThe token and org id are the same management credentials described in\n[Bulk import and Stripe](#tag/bulk-import-and-stripe). Keep them server-side."
}
],
"x-tagGroups": [
{
"name": "Product guides",
"tags": [
"Getting started",
"Audience segments",
"Email campaigns",
"Automations",
"In-app messages",
"Lifecycle scoring",
"Product intelligence",
"Deliverability"
]
},
{
"name": "Developer guides",
"tags": [
"Quickstart",
"JavaScript SDK",
"Server-side events and identity",
"Bulk import and Stripe",
"Enrichment and data sources",
"MCP and AI access"
]
}
],
"paths": {}
}
},
{
"slug": "api",
"title": "API Reference",
"content": {
"openapi": "3.1.0",
"info": {
"title": "Banchurn API",
"version": "1.0.0",
"description": "The Banchurn API ingests product analytics, identifies users, records sessions,\nand powers the churn / engagement platform.\n\n## Authentication\n\nBanchurn uses **two** auth modes depending on the endpoint:\n\n### 1. Ingestion key (`x-api-key`)\nReal-time endpoints (`/api/track`, `/api/identify`, `/t/session-recording`) authenticate\nwith your **organization ingestion key**. Send it as the `x-api-key` header.\nThis key is safe to embed in browser/mobile clients — it can only *write* events.\n\n```\nx-api-key: bc_live_xxxxxxxxxxxxxxxxxxxxxxxx\n```\n\n### 2. Session token (`Authorization: Bearer`)\nManagement + bulk endpoints authenticate with a **JWT** obtained from `/api/auth/login`,\nplus an `x-org-id` header naming the organization you act on. These are server-side only —\nnever expose them in a browser.\n\n```\nAuthorization: Bearer \nx-org-id: \n```\n\n## Visitor model\nEvery event belongs to a `visitorId` — any stable string you choose (a UUID for anonymous\nbrowser visitors, or the user's email / your internal user id once known). Call `/api/identify`\nto attach traits and to merge an anonymous `visitorId` into a known one via `previousVisitorId`.",
"contact": {
"name": "Banchurn",
"url": "https://banchurn.com"
}
},
"servers": [
{
"url": "https://api.banchurn.com",
"description": "Production"
}
],
"tags": [
{
"name": "Ingestion",
"description": "Real-time event, identify and session data. Auth: `x-api-key`."
},
{
"name": "Bulk Import",
"description": "Server-side backfill of users and historical events. Auth: `Bearer` + `x-org-id`."
},
{
"name": "Authentication",
"description": "Obtain a session token and inspect the current user."
},
{
"name": "API Keys",
"description": "List, create and revoke keys. Auth: `Bearer` + `x-org-id`."
},
{
"name": "System",
"description": "Health and status."
},
{
"name": "Analytics",
"description": "Product-analytics reports: KPIs, retention cohorts, funnels, revenue, people/accounts, session flows and AI insights. Auth: `Bearer` + `x-org-id`."
},
{
"name": "Segments",
"description": "Define and evaluate audience segments from a nested rule tree. Auth: `Bearer` + `x-org-id`."
},
{
"name": "Campaigns",
"description": "One-off, scheduled and triggered messaging campaigns, plus their delivery stats. Auth: `Bearer` + `x-org-id`."
},
{
"name": "Templates",
"description": "Reusable email templates with `{{variable}}` interpolation. Auth: `Bearer` + `x-org-id`."
},
{
"name": "Automations",
"description": "Multi-step, trigger-driven journeys and their visitor enrollments. Auth: `Bearer` + `x-org-id`."
},
{
"name": "Churn",
"description": "Churn-risk scoring: org overview, at-risk lists, trends and per-visitor detail. Auth: `Bearer` + `x-org-id`."
},
{
"name": "Data Sources",
"description": "External endpoint / Stripe connectors that sync users and events into Banchurn. Auth: `Bearer` + `x-org-id`."
},
{
"name": "In-app Messages",
"description": "On-site banners, modals, slide-outs and tooltips. CRUD + activate/pause are management endpoints (`Bearer` + `x-org-id`); the `match` and `track` endpoints the SDK calls are **public** and authenticate with the org ingestion key in the request body."
}
],
"components": {
"securitySchemes": {
"ApiKeyAuth": {
"type": "apiKey",
"in": "header",
"name": "x-api-key",
"description": "Organization ingestion key."
},
"BearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT",
"description": "Session token from /api/auth/login."
},
"OrgId": {
"type": "apiKey",
"in": "header",
"name": "x-org-id",
"description": "Target organization id."
}
},
"schemas": {
"TrackRequest": {
"type": "object",
"required": [
"eventName",
"visitorId"
],
"properties": {
"eventName": {
"type": "string",
"example": "page_view",
"description": "Raw event type. Banchurn auto-categorizes it."
},
"visitorId": {
"type": "string",
"example": "v_8fc2a1",
"description": "Stable id for this visitor (uuid, email, or your user id)."
},
"url": {
"type": "string",
"example": "https://app.example.com/pricing"
},
"fingerprint": {
"type": "string",
"example": "fp_9a1b2c",
"description": "Optional device fingerprint for identity recovery."
},
"properties": {
"type": "object",
"additionalProperties": true,
"description": "Arbitrary context. Special keys: `revenue`, `currency`, `$utm_source`, `$utm_medium`, `$utm_campaign`, `$referrer`.",
"example": {
"text": "Upgrade",
"path": "/pricing",
"revenue": 49,
"currency": "USD",
"$utm_source": "google"
}
}
}
},
"IdentifyRequest": {
"type": "object",
"required": [
"visitorId"
],
"properties": {
"visitorId": {
"type": "string",
"example": "user@example.com",
"description": "The known identity for this visitor."
},
"previousVisitorId": {
"type": "string",
"example": "v_8fc2a1",
"description": "Anonymous id to merge into this identity."
},
"fingerprint": {
"type": "string",
"example": "fp_9a1b2c"
},
"traits": {
"type": "object",
"additionalProperties": true,
"example": {
"name": "Ada Lovelace",
"email": "user@example.com",
"plan": "pro",
"company": "Analytical Engines"
}
}
}
},
"SessionRecordingRequest": {
"type": "object",
"required": [
"visitorId",
"sessionId",
"events"
],
"properties": {
"visitorId": {
"type": "string",
"example": "v_8fc2a1"
},
"sessionId": {
"type": "string",
"example": "s_20260707_01"
},
"pageUrl": {
"type": "string",
"example": "https://app.example.com/dashboard"
},
"events": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
},
"description": "rrweb-style event chunks."
}
}
},
"ImportUsersRequest": {
"type": "object",
"required": [
"users"
],
"properties": {
"users": {
"type": "array",
"maxItems": 10000,
"items": {
"type": "object",
"required": [
"email"
],
"properties": {
"email": {
"type": "string",
"example": "user@example.com"
},
"name": {
"type": "string",
"example": "Ada Lovelace"
},
"plan": {
"type": "string",
"example": "pro"
}
},
"additionalProperties": true
}
}
}
},
"ImportEventsRequest": {
"type": "object",
"required": [
"events"
],
"properties": {
"events": {
"type": "array",
"items": {
"type": "object",
"required": [
"email",
"event"
],
"properties": {
"email": {
"type": "string",
"example": "user@example.com"
},
"event": {
"type": "string",
"example": "subscription_started"
},
"timestamp": {
"type": "string",
"format": "date-time",
"example": "2026-07-01T12:00:00Z"
},
"properties": {
"type": "object",
"additionalProperties": true,
"example": {
"plan": "pro",
"mrr": 49
}
}
}
}
}
}
},
"LoginRequest": {
"type": "object",
"required": [
"email",
"password"
],
"properties": {
"email": {
"type": "string",
"example": "you@company.com"
},
"password": {
"type": "string",
"example": "super-secret"
}
}
},
"SuccessResponse": {
"type": "object",
"properties": {
"success": {
"type": "boolean",
"example": true
}
}
},
"ImportUsersResponse": {
"type": "object",
"properties": {
"imported": {
"type": "integer",
"example": 120
},
"updated": {
"type": "integer",
"example": 5
},
"failed": {
"type": "integer",
"example": 0
},
"errors": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
}
}
},
"ImportEventsResponse": {
"type": "object",
"properties": {
"imported": {
"type": "integer",
"example": 340
},
"failed": {
"type": "integer",
"example": 2
},
"errors": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
}
}
},
"ImportStatusResponse": {
"type": "object",
"properties": {
"totalVisitors": {
"type": "integer",
"example": 1280
},
"totalWithEmail": {
"type": "integer",
"example": 640
},
"lastImport": {
"type": "string",
"format": "date-time",
"nullable": true
}
}
},
"LoginResponse": {
"type": "object",
"properties": {
"token": {
"type": "string",
"example": "eyJhbGciOi..."
},
"user": {
"type": "object",
"additionalProperties": true
},
"organization": {
"type": "object",
"properties": {
"id": {
"type": "string",
"example": "org_123"
},
"name": {
"type": "string",
"example": "Acme Inc"
},
"apiKey": {
"type": "string",
"example": "bc_live_xxxxxxxxxxxx",
"description": "Ingestion key for x-api-key."
}
}
}
}
},
"ApiKey": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"key": {
"type": "string"
},
"label": {
"type": "string"
},
"title": {
"type": "string"
},
"createdAt": {
"type": "string",
"format": "date-time"
}
}
},
"Error": {
"type": "object",
"properties": {
"error": {
"type": "string",
"example": "Invalid API Key"
}
}
},
"Paginated": {
"type": "object",
"description": "Envelope shared by the paginated list endpoints.",
"properties": {
"total": {
"type": "integer",
"example": 142
},
"page": {
"type": "integer",
"example": 1
},
"limit": {
"type": "integer",
"example": 50
},
"totalPages": {
"type": "integer",
"example": 3
}
}
},
"EventCount": {
"type": "object",
"properties": {
"eventName": {
"type": "string",
"example": "Page View"
},
"count": {
"type": "integer",
"example": 1820
}
}
},
"LiveEvent": {
"type": "object",
"description": "A single recent event with the visitor's name/email attached.",
"properties": {
"id": {
"type": "string",
"example": "evt_9a1b"
},
"orgId": {
"type": "string",
"example": "org_123"
},
"eventName": {
"type": "string",
"example": "Signup Completed"
},
"properties": {
"type": "object",
"additionalProperties": true,
"example": {
"plan": "pro",
"path": "/welcome"
}
},
"visitorId": {
"type": "string",
"example": "user@example.com"
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"revenue": {
"type": "number",
"nullable": true,
"example": 49
},
"visitor": {
"type": "object",
"properties": {
"name": {
"type": "string",
"nullable": true,
"example": "Ada Lovelace"
},
"email": {
"type": "string",
"nullable": true,
"example": "user@example.com"
}
}
}
}
},
"RetentionResponse": {
"type": "object",
"properties": {
"weeks": {
"type": "integer",
"example": 12
},
"cohorts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"label": {
"type": "string",
"example": "2026-05-04",
"description": "ISO date the cohort was first seen."
},
"week": {
"type": "integer",
"example": 0,
"description": "Cohort week offset from the range start."
},
"size": {
"type": "integer",
"example": 80,
"description": "Number of visitors in the cohort."
},
"retention": {
"type": "array",
"items": {
"type": "integer"
},
"example": [
100,
62,
48,
40
],
"description": "Retention % for each subsequent week."
}
}
}
}
}
},
"FunnelRequest": {
"type": "object",
"required": [
"steps"
],
"properties": {
"steps": {
"type": "array",
"items": {
"type": "string"
},
"example": [
"Page View",
"Signup Started",
"Signup Completed"
],
"description": "Ordered list of event names forming the funnel."
},
"days": {
"type": "integer",
"default": 30,
"example": 30,
"description": "Look-back window in days."
}
}
},
"FunnelResponse": {
"type": "object",
"properties": {
"totalDays": {
"type": "integer",
"example": 30
},
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"example": "Signup Completed"
},
"count": {
"type": "integer",
"example": 210,
"description": "Visitors who reached this step in order."
},
"rate": {
"type": "integer",
"example": 42,
"description": "Percentage of first-step visitors who reached this step."
},
"dropoff": {
"type": "integer",
"example": 90,
"description": "Visitors lost since the previous step."
}
}
}
}
}
},
"KpiResponse": {
"type": "object",
"description": "Headline KPIs for the selected range, with the previous equal-length range for comparison.",
"properties": {
"totalEvents": {
"type": "integer",
"example": 12500
},
"prevEvents": {
"type": "integer",
"example": 11800
},
"totalVisitors": {
"type": "integer",
"example": 940
},
"prevVisitors": {
"type": "integer",
"example": 880
},
"newVisitors": {
"type": "integer",
"example": 320
},
"prevNewVisitors": {
"type": "integer",
"example": 290
},
"eventsPerUser": {
"type": "number",
"example": 13.3
}
}
},
"EventsVolumePoint": {
"type": "object",
"properties": {
"date": {
"type": "string",
"example": "2026-07-01"
},
"events": {
"type": "integer",
"example": 420
},
"visitors": {
"type": "integer",
"example": 88
}
}
},
"LabeledCount": {
"type": "object",
"description": "A generic label/count pair (country, category, etc.).",
"properties": {
"count": {
"type": "integer",
"example": 42
}
},
"additionalProperties": true,
"example": {
"country": "US",
"count": 320
}
},
"RevenueKpiResponse": {
"type": "object",
"description": "Total Revenue is net (refunds subtracted). Paying customers / transactions count positive events only. Each metric is paired with its previous-period value for change calculation.",
"properties": {
"totalRevenue": {
"type": "number",
"example": 18400.5
},
"prevTotalRevenue": {
"type": "number",
"example": 15200
},
"payingCustomers": {
"type": "integer",
"example": 142
},
"prevPayingCustomers": {
"type": "integer",
"example": 128
},
"arpu": {
"type": "number",
"example": 129.58,
"description": "Average revenue per paying customer."
},
"prevArpu": {
"type": "number",
"example": 118.75
},
"conversionRate": {
"type": "number",
"example": 12.4,
"description": "Paying customers as a percentage of active visitors."
},
"prevConversionRate": {
"type": "number",
"example": 11.1
},
"transactions": {
"type": "integer",
"example": 260
},
"prevTransactions": {
"type": "integer",
"example": 220
}
}
},
"SessionDurationResponse": {
"type": "object",
"properties": {
"avgDuration": {
"type": "integer",
"example": 214,
"description": "Average session duration in seconds."
}
}
},
"RevenueBySource": {
"type": "object",
"properties": {
"source": {
"type": "string",
"example": "google"
},
"revenue": {
"type": "number",
"example": 4200.75
}
}
},
"RevenuePoint": {
"type": "object",
"properties": {
"date": {
"type": "string",
"example": "2026-07-01"
},
"revenue": {
"type": "number",
"example": 640
}
}
},
"EventsRecentResponse": {
"type": "object",
"properties": {
"total": {
"type": "integer",
"example": 5400
},
"totalPages": {
"type": "integer",
"example": 108
},
"events": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"example": "evt_9a1b"
},
"eventName": {
"type": "string",
"example": "CTA Clicked"
},
"visitorId": {
"type": "string",
"example": "user@example.com"
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"properties": {
"type": "object",
"additionalProperties": true
},
"revenue": {
"type": "number",
"nullable": true,
"example": 0
},
"url": {
"type": "string",
"nullable": true,
"example": "https://app.example.com/pricing"
},
"aiCategory": {
"type": "string",
"nullable": true,
"example": "Pricing Interest"
},
"name": {
"type": "string",
"nullable": true,
"example": "Ada Lovelace"
},
"email": {
"type": "string",
"nullable": true,
"example": "user@example.com"
},
"country": {
"type": "string",
"nullable": true,
"example": "US"
},
"city": {
"type": "string",
"nullable": true,
"example": "San Francisco"
},
"browser": {
"type": "string",
"nullable": true,
"example": "Chrome"
},
"os": {
"type": "string",
"nullable": true,
"example": "macOS"
},
"device": {
"type": "string",
"nullable": true,
"example": "desktop"
}
}
}
}
}
},
"VisitorEnriched": {
"type": "object",
"description": "A visitor row enriched with event counts, last activity and geo/account data.",
"properties": {
"id": {
"type": "string",
"example": "vst_1"
},
"visitorId": {
"type": "string",
"example": "user@example.com"
},
"traits": {
"type": "string",
"description": "JSON-stringified traits blob.",
"example": "{\"name\":\"Ada\",\"plan\":\"pro\"}"
},
"firstSeen": {
"type": "integer",
"example": 1719792000000,
"description": "Epoch milliseconds."
},
"lastSeen": {
"type": "integer",
"example": 1722384000000,
"description": "Epoch milliseconds."
},
"eventCount": {
"type": "integer",
"example": 84
},
"lastEvent": {
"type": "string",
"example": "Dashboard Viewed"
},
"lastEventUrl": {
"type": "string",
"example": "https://app.example.com/home"
},
"totalRevenue": {
"type": "number",
"example": 199
},
"revenueCount": {
"type": "integer",
"example": 3
},
"utmSource": {
"type": "string",
"nullable": true,
"example": "google"
},
"referrer": {
"type": "string",
"nullable": true,
"example": "https://news.ycombinator.com"
},
"country": {
"type": "string",
"nullable": true,
"example": "US"
},
"city": {
"type": "string",
"nullable": true,
"example": "San Francisco"
},
"countryEmoji": {
"type": "string",
"nullable": true,
"example": "🇺🇸"
},
"accountId": {
"type": "string",
"nullable": true,
"example": "acc_9"
},
"accountName": {
"type": "string",
"nullable": true,
"example": "Acme Inc"
}
}
},
"VisitorProfileResponse": {
"type": "object",
"properties": {
"visitor": {
"type": "object",
"additionalProperties": true,
"description": "The full visitor record (incl. linked account)."
},
"events": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
},
"description": "Up to 200 most recent events."
},
"eventCount": {
"type": "integer",
"example": 84
}
}
},
"VisitorSession": {
"type": "object",
"properties": {
"sessionId": {
"type": "string",
"example": "s_20260707_01"
},
"startTime": {
"type": "integer",
"example": 1722380000000
},
"endTime": {
"type": "integer",
"example": 1722381200000
},
"duration": {
"type": "integer",
"example": 1200,
"description": "Seconds."
},
"pageCount": {
"type": "integer",
"example": 6
},
"referrer": {
"type": "string",
"example": ""
},
"isDay": {
"type": "boolean",
"example": false,
"description": "True when events were grouped by day (no sessionId)."
},
"events": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
}
}
},
"VisitorActivityResponse": {
"type": "object",
"properties": {
"totalEvents": {
"type": "integer",
"example": 84
},
"firstSeen": {
"type": "string",
"format": "date-time",
"nullable": true
},
"lastSeen": {
"type": "string",
"format": "date-time",
"nullable": true
},
"dailyCounts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string",
"example": "2026-07-01"
},
"count": {
"type": "integer",
"example": 4
}
}
},
"description": "Daily event counts for the last 30 days."
},
"topEvents": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"count": {
"type": "integer"
},
"pct": {
"type": "integer"
}
}
}
},
"topPages": {
"type": "array",
"items": {
"type": "object",
"properties": {
"url": {
"type": "string"
},
"title": {
"type": "string"
},
"path": {
"type": "string"
},
"count": {
"type": "integer"
}
}
}
}
}
},
"Account": {
"type": "object",
"properties": {
"id": {
"type": "string",
"example": "acc_9"
},
"name": {
"type": "string",
"example": "Acme Inc"
},
"domain": {
"type": "string",
"nullable": true,
"example": "acme.com"
},
"plan": {
"type": "string",
"nullable": true,
"example": "enterprise"
},
"platform": {
"type": "string",
"nullable": true,
"example": "web"
},
"externalId": {
"type": "string",
"nullable": true,
"example": "cus_123"
},
"traits": {
"type": "string",
"description": "JSON-stringified traits blob.",
"example": "{}"
},
"firstSeen": {
"type": "integer",
"example": 1719792000000
},
"lastSeen": {
"type": "integer",
"example": 1722384000000
},
"totalRevenue": {
"type": "number",
"example": 4200
},
"visitorCount": {
"type": "integer",
"example": 12
}
}
},
"TopCustomer": {
"type": "object",
"properties": {
"visitorId": {
"type": "string",
"example": "user@example.com"
},
"name": {
"type": "string",
"nullable": true,
"example": "Ada Lovelace"
},
"email": {
"type": "string",
"nullable": true,
"example": "user@example.com"
},
"totalRevenue": {
"type": "number",
"example": 1990
},
"revenueCount": {
"type": "integer",
"example": 11
},
"country": {
"type": "string",
"nullable": true,
"example": "US"
},
"lastSeen": {
"type": "string",
"format": "date-time"
}
}
},
"SegmentationRequest": {
"type": "object",
"required": [
"eventName"
],
"properties": {
"eventName": {
"type": "string",
"example": "Signup Completed"
},
"groupBy": {
"type": "string",
"nullable": true,
"example": "plan",
"description": "Optional property key to break the series down by."
},
"startDate": {
"type": "integer",
"example": 1719792000000,
"description": "Epoch milliseconds."
},
"endDate": {
"type": "integer",
"example": 1722384000000,
"description": "Epoch milliseconds."
}
}
},
"SegmentationResponse": {
"type": "object",
"properties": {
"series": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"example": "pro"
},
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string"
},
"count": {
"type": "integer"
}
}
}
}
}
}
}
}
},
"AiInsightsResponse": {
"type": "object",
"description": "Rule-derived insights plus suggested segments and campaigns for the period.",
"properties": {
"insights": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"success",
"warning",
"info",
"opportunity"
],
"example": "warning"
},
"title": {
"type": "string",
"example": "42 visitors at risk of churning"
},
"description": {
"type": "string",
"example": "15% of active users haven't returned in 14+ days."
},
"metric": {
"type": "string",
"example": "15% churn risk"
}
}
}
},
"suggestedSegments": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true,
"description": "A ready-to-create segment (name, description, rules)."
}
},
"suggestedCampaigns": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true,
"description": "A suggested campaign (name, type, description, trigger)."
}
},
"summary": {
"type": "object",
"additionalProperties": true,
"description": "Aggregate totals for the period (events, visitors, revenue, top categories/pages/sources)."
}
}
},
"Flow": {
"type": "object",
"description": "A reconstructed user journey for one session.",
"properties": {
"sessionId": {
"type": "string",
"example": "s_20260707_01"
},
"visitorId": {
"type": "string",
"example": "user@example.com"
},
"visitorName": {
"type": "string",
"nullable": true,
"example": "Ada Lovelace"
},
"flowName": {
"type": "string",
"example": "Submitted Signup (from Pricing)"
},
"flowType": {
"type": "string",
"example": "form_completion"
},
"description": {
"type": "string",
"example": "Started on Pricing, submitted the signup form, spent 3m"
},
"summary": {
"type": "string",
"example": "Viewed Pricing → Clicked CTA → Submitted Signup"
},
"steps": {
"type": "array",
"items": {
"type": "string"
}
},
"outcome": {
"type": "string",
"nullable": true,
"example": "Submitted Signup"
},
"stepCount": {
"type": "integer",
"example": 12
},
"uniqueSteps": {
"type": "integer",
"example": 7
},
"pages": {
"type": "array",
"items": {
"type": "string"
}
},
"durationSec": {
"type": "integer",
"example": 184
},
"startedAt": {
"type": "string",
"format": "date-time"
},
"endedAt": {
"type": "string",
"format": "date-time"
},
"events": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
}
}
},
"FlowsResponse": {
"type": "object",
"properties": {
"total": {
"type": "integer",
"example": 50
},
"flows": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Flow"
}
}
}
},
"FlowPatternsResponse": {
"type": "object",
"properties": {
"totalSessions": {
"type": "integer",
"example": 480
},
"period": {
"type": "string",
"example": "7d"
},
"patterns": {
"type": "array",
"items": {
"type": "object",
"properties": {
"pattern": {
"type": "string",
"example": "Viewed Pricing → Clicked CTA"
},
"count": {
"type": "integer",
"example": 34
},
"steps": {
"type": "array",
"items": {
"type": "string"
}
},
"pctSessions": {
"type": "integer",
"example": 7
}
}
}
},
"discoveredFlows": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"example": "Explored Dashboard"
},
"count": {
"type": "integer",
"example": 60
},
"pctSessions": {
"type": "integer",
"example": 12
}
}
}
}
}
},
"Dashboard": {
"type": "object",
"description": "A saved analytics dashboard (stored in the org settings blob).",
"properties": {
"id": {
"type": "string",
"example": "a1b2c3d4"
},
"name": {
"type": "string",
"example": "Growth Overview"
},
"widgets": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
},
"pinned": {
"type": "boolean",
"example": false
},
"createdAt": {
"type": "integer",
"example": 1719792000000
},
"updatedAt": {
"type": "integer",
"example": 1722384000000
}
}
},
"DashboardCreate": {
"type": "object",
"properties": {
"name": {
"type": "string",
"example": "Growth Overview"
},
"widgets": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
}
}
},
"SegmentRules": {
"type": "object",
"description": "A nested rule tree. A `group` has an `operator` (`AND` / `OR`) and a list of `conditions`; a\ncondition may itself be a nested `group` (up to 4 levels deep). The root `group` also accepts an\noptional `limit` (integer) + `orderBy` (`recent` | `revenue` | `oldest`) to cap the audience to the\ntop-N people. Each leaf condition has a `type`:\n- `trait` — `{ field, operator, value }` on visitor traits. Operators: `eq`, `neq`, `contains`, `not_contains`, `starts_with`, `ends_with`, `exists`, `not_exists`, `gt`, `lt`, `gte`, `lte`, `in`, `not_in`. Add `compareTo: \"\"` to compare against another person field instead of `value` (property-vs-property).\n- `event` — `{ event, operator, value?, aggProperty?, timeWindow?, propertyFilters? }`. Operators: `has_done`, `has_not_done`, `count_gt`, `count_lt`, `count_gte`, `count_lte`, and the aggregations `sum_gt` / `sum_lt` / `avg_gt` / `avg_lt` over `aggProperty` (a numeric event property; defaults to `revenue`). `timeWindow` is `{ value, unit }` (e.g. `{ value: 30, unit: \"days\" }`).\n- `account` — `{ field, operator, value }` on the linked account. Operators: `eq`, `neq`, `gt`, `lt`, `gte`, `lte`, `in`, `not_in`, `contains`. Also supports `compareTo` (account-field vs account-field).\n- `behavior` — `{ metric, operator, value }` where `metric` is `lastSeen` | `firstSeen` | `totalRevenue` | `revenueCount`. Operators: `within_days`, `not_within_days`, `gt`, `lt`, `gte`, `lte`.\n- `campaign` — `{ campaignId, operator }`. Operators: `received`, `opened`, `clicked`, `not_received`.\n- `source` — `{ operator, value }` on acquisition platform. Operators: `used`, `not_used`, `is`, `is_not`, `first_is`. `value` is a platform (`web` | `wordpress` | `shopify` | `ios` | `android` | `server`).\n- `sequence` — `{ first: { event }, then: { event }, withinDays?, operator? }`. Matches people who did `first` then `then` (in order); `withinDays` bounds the gap; `operator: \"not_done\"` negates.\n- `audience` — `{ segmentId, operator }` where `operator` is `in` | `not_in`. Matches people who are (or are not) in another saved segment. Cycle-guarded.",
"additionalProperties": true,
"example": {
"type": "group",
"operator": "AND",
"conditions": [
{
"type": "trait",
"field": "plan",
"operator": "eq",
"value": "pro"
},
{
"type": "event",
"event": "purchase",
"operator": "sum_gt",
"aggProperty": "amount",
"value": 500,
"timeWindow": {
"value": 90,
"unit": "days"
}
},
{
"type": "sequence",
"first": {
"event": "signup"
},
"then": {
"event": "purchase"
},
"withinDays": 7
},
{
"type": "audience",
"segmentId": "seg_admins",
"operator": "in"
}
],
"limit": 1000,
"orderBy": "revenue"
}
},
"Segment": {
"type": "object",
"properties": {
"id": {
"type": "string",
"example": "seg_1f2c"
},
"orgId": {
"type": "string",
"example": "org_123"
},
"name": {
"type": "string",
"example": "Power Users"
},
"description": {
"type": "string",
"example": "Visitors with 20+ events in the last 30 days."
},
"rules": {
"$ref": "#/components/schemas/SegmentRules"
},
"matchCount": {
"type": "integer",
"nullable": true,
"example": 142,
"description": "Cached size from the last evaluation."
},
"lastEvaluated": {
"type": "string",
"format": "date-time",
"nullable": true
},
"createdBy": {
"type": "string",
"example": "usr_1"
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"updatedAt": {
"type": "string",
"format": "date-time"
}
}
},
"SegmentCreate": {
"type": "object",
"required": [
"name",
"rules"
],
"properties": {
"name": {
"type": "string",
"example": "Power Users"
},
"description": {
"type": "string",
"example": "Visitors with 20+ events in the last 30 days."
},
"rules": {
"$ref": "#/components/schemas/SegmentRules"
}
}
},
"SegmentUpdate": {
"type": "object",
"description": "All fields optional — only supplied fields are changed.",
"properties": {
"name": {
"type": "string",
"example": "Power Users"
},
"description": {
"type": "string"
},
"rules": {
"$ref": "#/components/schemas/SegmentRules"
}
}
},
"VisitorSample": {
"type": "object",
"properties": {
"id": {
"type": "string",
"example": "vst_1"
},
"visitorId": {
"type": "string",
"example": "user@example.com"
},
"traits": {
"type": "object",
"additionalProperties": true,
"example": {
"name": "Ada Lovelace",
"plan": "pro"
}
},
"lastSeen": {
"type": "string",
"format": "date-time"
},
"country": {
"type": "string",
"nullable": true,
"example": "US"
},
"totalRevenue": {
"type": "number",
"example": 199
}
}
},
"SegmentEvaluateResponse": {
"type": "object",
"properties": {
"count": {
"type": "integer",
"example": 142,
"description": "Total matching visitors."
},
"sample": {
"type": "array",
"items": {
"$ref": "#/components/schemas/VisitorSample"
},
"description": "Up to 10 matching visitors."
}
}
},
"SegmentVisitorsResponse": {
"allOf": [
{
"$ref": "#/components/schemas/Paginated"
},
{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/VisitorSample"
}
}
}
}
]
},
"SegmentPreviewRequest": {
"type": "object",
"required": [
"rules"
],
"properties": {
"rules": {
"$ref": "#/components/schemas/SegmentRules"
}
}
},
"CountResponse": {
"type": "object",
"properties": {
"count": {
"type": "integer",
"example": 142
}
}
},
"SegmentSchemaResponse": {
"type": "object",
"description": "Everything the builder needs to offer real, typeahead-able choices for this org.",
"properties": {
"traits": {
"type": "object",
"description": "Person fields. `direct` are first-class columns; `custom` are trait keys discovered from recent visitors (with observed counts).",
"properties": {
"direct": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"label": {
"type": "string"
},
"type": {
"type": "string"
}
}
}
},
"custom": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"count": {
"type": "integer"
}
}
}
}
}
},
"account": {
"type": "object",
"description": "Account fields, same shape as `traits`.",
"properties": {
"direct": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"label": {
"type": "string"
},
"type": {
"type": "string"
}
}
}
},
"custom": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"count": {
"type": "integer"
}
}
}
}
}
},
"events": {
"type": "array",
"description": "Event names seen for this org, each with its discovered property keys.",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"example": "purchase"
},
"count": {
"type": "integer",
"example": 1240
},
"properties": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"count": {
"type": "integer"
}
}
}
}
}
}
},
"propertyKeys": {
"type": "array",
"description": "Union of all event property keys (for aggregation/filter pickers).",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"count": {
"type": "integer"
}
}
}
},
"segments": {
"type": "array",
"description": "Other saved segments — reference them in `audience` conditions.",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
}
},
"campaigns": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
}
},
"platforms": {
"type": "array",
"description": "Platforms observed in this org’s data.",
"items": {
"type": "string",
"example": "shopify"
}
}
}
},
"Campaign": {
"type": "object",
"properties": {
"id": {
"type": "string",
"example": "cmp_7a"
},
"orgId": {
"type": "string",
"example": "org_123"
},
"name": {
"type": "string",
"example": "July Win-back"
},
"type": {
"type": "string",
"example": "email",
"description": "Message channel, e.g. `email`."
},
"status": {
"type": "string",
"example": "draft",
"description": "One of `draft`, `scheduled`, `sending`, `sent`, `paused`, `cancelled`, `active`."
},
"campaignMode": {
"type": "string",
"example": "bulk",
"description": "`bulk` (send to a segment) or `triggered`."
},
"segmentId": {
"type": "string",
"nullable": true,
"example": "seg_1f2c"
},
"templateId": {
"type": "string",
"nullable": true,
"example": "tpl_9d"
},
"subject": {
"type": "string",
"example": "We miss you 👋"
},
"fromName": {
"type": "string",
"example": "Acme Team"
},
"fromEmail": {
"type": "string",
"example": "hello@acme.com"
},
"replyTo": {
"type": "string",
"example": "support@acme.com"
},
"triggerType": {
"type": "string",
"nullable": true,
"example": "event"
},
"triggerConfig": {
"type": "object",
"additionalProperties": true,
"nullable": true
},
"recurring": {
"type": "boolean",
"example": false
},
"recurringSchedule": {
"type": "string",
"nullable": true,
"example": "weekly",
"description": "`daily`, `weekly`, `biweekly` or `monthly`."
},
"sendOncePerVisitor": {
"type": "boolean",
"example": true
},
"cooldownHours": {
"type": "integer",
"example": 0
},
"isActive": {
"type": "boolean",
"example": false
},
"scheduledAt": {
"type": "string",
"format": "date-time",
"nullable": true
},
"sentAt": {
"type": "string",
"format": "date-time",
"nullable": true
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"updatedAt": {
"type": "string",
"format": "date-time"
}
}
},
"CampaignCreate": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"example": "July Win-back"
},
"type": {
"type": "string",
"example": "email",
"default": "email"
},
"segmentId": {
"type": "string",
"nullable": true,
"example": "seg_1f2c"
},
"templateId": {
"type": "string",
"nullable": true,
"example": "tpl_9d"
},
"subject": {
"type": "string",
"example": "We miss you 👋"
},
"fromName": {
"type": "string",
"example": "Acme Team"
},
"fromEmail": {
"type": "string",
"example": "hello@acme.com"
},
"replyTo": {
"type": "string",
"example": "support@acme.com"
},
"campaignMode": {
"type": "string",
"example": "bulk",
"default": "bulk",
"description": "`bulk` or `triggered`."
},
"triggerType": {
"type": "string",
"nullable": true,
"example": "event"
},
"triggerConfig": {
"type": "object",
"additionalProperties": true,
"nullable": true
},
"recurring": {
"type": "boolean",
"example": false
},
"recurringSchedule": {
"type": "string",
"nullable": true,
"example": "weekly"
},
"sendOncePerVisitor": {
"type": "boolean",
"example": true
},
"cooldownHours": {
"type": "integer",
"example": 0
}
}
},
"CampaignScheduleRequest": {
"type": "object",
"required": [
"scheduledAt"
],
"properties": {
"scheduledAt": {
"type": "string",
"format": "date-time",
"example": "2026-07-10T09:00:00Z"
}
}
},
"CampaignSendTestRequest": {
"type": "object",
"required": [
"email"
],
"properties": {
"email": {
"type": "string",
"example": "you@company.com",
"description": "Address to receive the test email."
}
}
},
"CampaignSendResult": {
"type": "object",
"properties": {
"success": {
"type": "boolean",
"example": true
},
"message": {
"type": "string",
"example": "Campaign send initiated"
},
"messageId": {
"type": "string",
"example": "msg_abc",
"description": "Present on the test-send response."
}
}
},
"EmailSend": {
"type": "object",
"properties": {
"id": {
"type": "string",
"example": "snd_1"
},
"campaignId": {
"type": "string",
"example": "cmp_7a"
},
"visitorId": {
"type": "string",
"example": "user@example.com"
},
"status": {
"type": "string",
"example": "delivered",
"description": "`queued`, `sent`, `delivered`, `opened`, `clicked`, `bounced`, `failed`."
},
"createdAt": {
"type": "string",
"format": "date-time"
}
}
},
"CampaignSendsResponse": {
"allOf": [
{
"$ref": "#/components/schemas/Paginated"
},
{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/EmailSend"
}
}
}
}
]
},
"CampaignAnalyticsResponse": {
"type": "object",
"properties": {
"timeline": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string"
},
"sent": {
"type": "integer"
},
"opened": {
"type": "integer"
},
"clicked": {
"type": "integer"
}
}
}
},
"topLinks": {
"type": "array",
"items": {
"type": "object",
"properties": {
"url": {
"type": "string"
},
"clicks": {
"type": "integer"
}
}
}
},
"geoBreakdown": {
"type": "array",
"items": {
"type": "object",
"properties": {
"country": {
"type": "string"
},
"count": {
"type": "integer"
}
}
}
}
}
},
"Template": {
"type": "object",
"properties": {
"id": {
"type": "string",
"example": "tpl_9d"
},
"orgId": {
"type": "string",
"example": "org_123"
},
"name": {
"type": "string",
"example": "Welcome Email"
},
"subject": {
"type": "string",
"example": "Welcome to {{company}}, {{name}}!"
},
"html": {
"type": "string",
"example": "Hi {{name}}
"
},
"text": {
"type": "string",
"example": "Hi {{name}}"
},
"category": {
"type": "string",
"example": "marketing",
"description": "Defaults to `marketing`."
},
"variables": {
"type": "array",
"items": {
"type": "string"
},
"example": [
"name",
"company"
],
"description": "Auto-extracted `{{variable}}` names."
},
"isArchived": {
"type": "boolean",
"example": false
},
"createdBy": {
"type": "string",
"example": "usr_1"
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"updatedAt": {
"type": "string",
"format": "date-time"
}
}
},
"TemplateCreate": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"example": "Welcome Email"
},
"subject": {
"type": "string",
"example": "Welcome to {{company}}, {{name}}!"
},
"html": {
"type": "string",
"example": "Hi {{name}}
"
},
"text": {
"type": "string",
"example": "Hi {{name}}"
},
"category": {
"type": "string",
"example": "marketing"
}
}
},
"TemplateRenderRequest": {
"type": "object",
"description": "Provide either `templateId` (to render a stored template) or raw `html`.",
"properties": {
"templateId": {
"type": "string",
"nullable": true,
"example": "tpl_9d"
},
"html": {
"type": "string",
"nullable": true,
"example": "Hi {{name}}
"
},
"context": {
"type": "object",
"additionalProperties": true,
"example": {
"name": "Ada",
"company": "Acme"
},
"description": "Variable values to interpolate."
}
}
},
"TemplateRenderResponse": {
"type": "object",
"properties": {
"html": {
"type": "string",
"example": "Hi Ada
"
}
}
},
"AutomationStep": {
"type": "object",
"description": "One node in the journey. Each step has a stable `id`, a `type`, and a `config` object whose\nshape depends on the type:\n- `send_email` — `{ templateId }`: deliver a template.\n- `wait` — `{ duration, unit }`: pause a fixed time (`unit`: `minutes` | `hours` | `days`).\n- `wait_for_event` — `{ eventName, timeout }`: pause until the visitor does the event, or the timeout elapses.\n- `branch` — split the path on a condition (trait / event / segment).\n- `update_trait` — `{ key, value }`: write a visitor trait.\n- `webhook` — `{ url }`: POST the visitor/event context to an external URL.\n- `add_to_segment` — `{ listId }`: add the visitor to a static list.",
"properties": {
"id": {
"type": "string",
"example": "step_1",
"description": "Stable id for this step within the journey."
},
"type": {
"type": "string",
"enum": [
"send_email",
"wait",
"wait_for_event",
"branch",
"update_trait",
"webhook",
"add_to_segment"
],
"example": "send_email"
},
"config": {
"type": "object",
"additionalProperties": true,
"description": "Type-specific configuration — see the per-type shapes in this schema's description.",
"example": {
"templateId": "tpl_9d"
}
}
},
"additionalProperties": true,
"example": {
"id": "step_1",
"type": "send_email",
"config": {
"templateId": "tpl_9d"
}
}
},
"Automation": {
"type": "object",
"properties": {
"id": {
"type": "string",
"example": "aut_3"
},
"orgId": {
"type": "string",
"example": "org_123"
},
"name": {
"type": "string",
"example": "Onboarding Journey"
},
"description": {
"type": "string",
"example": "5-step welcome sequence for new signups."
},
"status": {
"type": "string",
"example": "draft",
"description": "`draft`, `active`, `paused` or `archived`."
},
"triggerType": {
"type": "string",
"enum": [
"event",
"segment_enter",
"segment_exit",
"manual"
],
"example": "event",
"description": "What enrolls a visitor: `event` (visitor does `triggerConfig.eventName`), `segment_enter` / `segment_exit` (visitor enters / leaves `entrySegmentId`), or `manual` (enrolled only via the enroll endpoint)."
},
"triggerConfig": {
"type": "object",
"additionalProperties": true,
"description": "Trigger parameters. For `event` triggers: `{ eventName }`.",
"example": {
"eventName": "Signup Completed"
}
},
"entrySegmentId": {
"type": "string",
"nullable": true,
"example": "seg_1f2c",
"description": "The segment whose entry/exit drives `segment_enter` / `segment_exit` triggers."
},
"reentryAllowed": {
"type": "boolean",
"example": false,
"description": "When false, a visitor who already has an enrollment is not re-enrolled."
},
"steps": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AutomationStep"
}
},
"totalEnrolled": {
"type": "integer",
"example": 320
},
"createdBy": {
"type": "string",
"example": "usr_1"
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"updatedAt": {
"type": "string",
"format": "date-time"
}
}
},
"AutomationDetail": {
"allOf": [
{
"$ref": "#/components/schemas/Automation"
},
{
"type": "object",
"properties": {
"enrollmentStats": {
"type": "array",
"items": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "active"
},
"_count": {
"type": "integer",
"example": 120
}
}
},
"description": "Enrollment counts grouped by status."
}
}
}
]
},
"AutomationCreate": {
"type": "object",
"required": [
"name",
"triggerType",
"steps"
],
"properties": {
"name": {
"type": "string",
"example": "Onboarding Journey"
},
"description": {
"type": "string",
"example": "5-step welcome sequence for new signups."
},
"triggerType": {
"type": "string",
"enum": [
"event",
"segment_enter",
"segment_exit",
"manual"
],
"example": "event",
"description": "What enrolls a visitor. `event` reads `triggerConfig.eventName`; `segment_enter` / `segment_exit` use `entrySegmentId`; `manual` enrolls only via the enroll endpoint."
},
"triggerConfig": {
"type": "object",
"additionalProperties": true,
"description": "For `event` triggers: `{ eventName }`. The UI shorthand `triggerEvent` is also accepted and normalized into this.",
"example": {
"eventName": "Signup Completed"
}
},
"entrySegmentId": {
"type": "string",
"nullable": true,
"example": "seg_1f2c"
},
"reentryAllowed": {
"type": "boolean",
"example": false
},
"steps": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AutomationStep"
}
}
}
},
"AutomationEnrollRequest": {
"type": "object",
"required": [
"visitorId"
],
"properties": {
"visitorId": {
"type": "string",
"example": "user@example.com"
}
}
},
"Enrollment": {
"type": "object",
"properties": {
"id": {
"type": "string",
"example": "enr_1"
},
"automationId": {
"type": "string",
"example": "aut_3"
},
"orgId": {
"type": "string",
"example": "org_123"
},
"visitorId": {
"type": "string",
"example": "user@example.com"
},
"currentStep": {
"type": "integer",
"example": 0
},
"status": {
"type": "string",
"example": "active",
"description": "`active`, `completed`, `exited`."
},
"enteredAt": {
"type": "string",
"format": "date-time"
}
}
},
"EnrollmentsResponse": {
"allOf": [
{
"$ref": "#/components/schemas/Paginated"
},
{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Enrollment"
}
}
}
}
]
},
"ChurnDistribution": {
"type": "object",
"properties": {
"low": {
"type": "integer",
"example": 400
},
"medium": {
"type": "integer",
"example": 120
},
"high": {
"type": "integer",
"example": 60
},
"critical": {
"type": "integer",
"example": 20
}
}
},
"ChurnOverview": {
"type": "object",
"properties": {
"totalVisitors": {
"type": "integer",
"example": 940
},
"totalScored": {
"type": "integer",
"example": 600
},
"avgChurnScore": {
"type": "integer",
"example": 34,
"description": "Average risk score (0–100) across scored visitors."
},
"atRiskCount": {
"type": "integer",
"example": 200,
"description": "Visitors at medium risk or above."
},
"revenueAtRisk": {
"type": "number",
"example": 12400.5,
"description": "Revenue tied to high/critical visitors."
},
"distribution": {
"$ref": "#/components/schemas/ChurnDistribution"
}
}
},
"AtRiskVisitor": {
"type": "object",
"properties": {
"visitorId": {
"type": "string",
"example": "user@example.com"
},
"name": {
"type": "string",
"example": "Ada Lovelace"
},
"email": {
"type": "string",
"nullable": true,
"example": "user@example.com"
},
"churnScore": {
"type": "integer",
"example": 78
},
"riskLevel": {
"type": "string",
"example": "critical",
"description": "`low`, `medium`, `high` or `critical`."
},
"signals": {
"type": "array",
"items": {
"type": "string"
},
"example": [
"inactivity_14d",
"declining_sessions"
]
},
"lastSeen": {
"type": "string",
"format": "date-time"
},
"totalRevenue": {
"type": "number",
"example": 199
},
"accountId": {
"type": "string",
"nullable": true,
"example": "acc_9"
},
"engagementScore": {
"type": "integer",
"nullable": true,
"example": 22
},
"lifecycleStage": {
"type": "string",
"nullable": true,
"example": "at_risk"
},
"scoredAt": {
"type": "string",
"format": "date-time",
"nullable": true
}
}
},
"ChurnAtRiskResponse": {
"type": "object",
"properties": {
"visitors": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AtRiskVisitor"
}
},
"total": {
"type": "integer",
"example": 200
},
"page": {
"type": "integer",
"example": 1
},
"limit": {
"type": "integer",
"example": 50
}
}
},
"ChurnTrendResponse": {
"type": "object",
"properties": {
"days": {
"type": "integer",
"example": 30
},
"trend": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true,
"description": "Daily risk distribution point."
}
}
}
},
"ChurnScoreAllResponse": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "scoring_started"
}
}
},
"ChurnVisitorDetail": {
"type": "object",
"properties": {
"visitorId": {
"type": "string",
"example": "user@example.com"
},
"name": {
"type": "string",
"example": "Ada Lovelace"
},
"email": {
"type": "string",
"nullable": true,
"example": "user@example.com"
},
"totalRevenue": {
"type": "number",
"example": 199
},
"lastSeen": {
"type": "string",
"format": "date-time"
},
"accountId": {
"type": "string",
"nullable": true,
"example": "acc_9"
},
"engagementScore": {
"type": "integer",
"nullable": true,
"example": 22
},
"lifecycleStage": {
"type": "string",
"nullable": true,
"example": "at_risk"
},
"churn": {
"type": "object",
"additionalProperties": true,
"description": "Freshly-computed churn scoring result (score, level, signals, factors)."
},
"recentActivity": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
},
"description": "Up to 30 most recent events."
}
}
},
"ChurnAccount": {
"type": "object",
"properties": {
"accountId": {
"type": "string",
"example": "acc_9"
},
"name": {
"type": "string",
"example": "Acme Inc"
},
"domain": {
"type": "string",
"nullable": true,
"example": "acme.com"
},
"stage": {
"type": "string",
"nullable": true,
"example": "customer"
},
"tier": {
"type": "string",
"nullable": true,
"example": "enterprise"
},
"totalRevenue": {
"type": "number",
"example": 42000
},
"visitorCount": {
"type": "integer",
"example": 12
},
"lastSeen": {
"type": "string",
"format": "date-time"
},
"avgChurnScore": {
"type": "integer",
"example": 58
},
"maxChurnScore": {
"type": "integer",
"example": 91
},
"riskLevel": {
"type": "string",
"example": "high"
},
"revenueAtRisk": {
"type": "number",
"example": 8200
},
"scoredVisitors": {
"type": "integer",
"example": 10
},
"riskDistribution": {
"$ref": "#/components/schemas/ChurnDistribution"
}
}
},
"ChurnAccountsResponse": {
"type": "object",
"properties": {
"accounts": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ChurnAccount"
}
},
"total": {
"type": "integer",
"example": 40
},
"page": {
"type": "integer",
"example": 1
},
"limit": {
"type": "integer",
"example": 50
}
}
},
"DataSource": {
"type": "object",
"properties": {
"id": {
"type": "string",
"example": "ds_2"
},
"orgId": {
"type": "string",
"example": "org_123"
},
"name": {
"type": "string",
"example": "Stripe customers"
},
"type": {
"type": "string",
"enum": [
"endpoint",
"stripe"
],
"example": "endpoint",
"description": "`endpoint` (HTTP `url` + field `mapping`) or `stripe` (polls the customer's own Stripe with `stripeApiKey`). A Stripe sync writes these visitor traits: `plan`, `subscription_status`, `mrr`, `current_period_end`, `trial_end`, `stripe_customer_id`. Defaults to `endpoint`."
},
"url": {
"type": "string",
"nullable": true,
"example": "https://api.acme.com/customers",
"description": "Source URL for `endpoint` sources."
},
"method": {
"type": "string",
"example": "GET",
"default": "GET"
},
"headers": {
"type": "object",
"additionalProperties": true,
"example": {
"Authorization": "Bearer ..."
}
},
"stripeApiKey": {
"type": "string",
"nullable": true,
"example": "sk_live_..."
},
"syncFrequency": {
"type": "string",
"example": "daily",
"description": "`hourly`, `daily`, `weekly`. Defaults to `daily`."
},
"mapping": {
"type": "object",
"additionalProperties": true,
"description": "Maps source columns to Banchurn fields.",
"example": {
"email": "customer_email",
"name": "full_name"
}
},
"enabled": {
"type": "boolean",
"example": true
},
"createdBy": {
"type": "string",
"example": "usr_1"
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"updatedAt": {
"type": "string",
"format": "date-time"
}
}
},
"DataSourceCreate": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"example": "Stripe customers"
},
"type": {
"type": "string",
"enum": [
"endpoint",
"stripe"
],
"example": "endpoint",
"description": "`endpoint` (HTTP `url` + `mapping`) or `stripe` (uses `stripeApiKey`)."
},
"url": {
"type": "string",
"nullable": true,
"example": "https://api.acme.com/customers"
},
"method": {
"type": "string",
"example": "GET"
},
"headers": {
"type": "object",
"additionalProperties": true,
"example": {
"Authorization": "Bearer ..."
}
},
"syncFrequency": {
"type": "string",
"example": "daily",
"description": "`hourly`, `every_6h`, `daily` or `weekly`."
},
"mapping": {
"type": "object",
"additionalProperties": true,
"example": {
"email": "customer_email"
},
"description": "Maps Banchurn fields to source columns (`endpoint` sources)."
},
"stripeApiKey": {
"type": "string",
"nullable": true,
"example": "sk_live_...",
"description": "Secret key for `stripe` sources."
}
}
},
"DataSourceUpdate": {
"type": "object",
"description": "All fields optional — only supplied fields are changed.",
"properties": {
"name": {
"type": "string",
"example": "Stripe customers"
},
"type": {
"type": "string",
"example": "endpoint"
},
"url": {
"type": "string",
"nullable": true
},
"method": {
"type": "string",
"example": "GET"
},
"headers": {
"type": "object",
"additionalProperties": true
},
"syncFrequency": {
"type": "string",
"example": "daily"
},
"mapping": {
"type": "object",
"additionalProperties": true
},
"stripeApiKey": {
"type": "string",
"nullable": true
},
"enabled": {
"type": "boolean",
"example": true
}
}
},
"DataSourceTestResponse": {
"type": "object",
"properties": {
"success": {
"type": "boolean",
"example": true
},
"sampleData": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
},
"description": "Up to 3 sample rows from the source."
},
"columns": {
"type": "array",
"items": {
"type": "string"
},
"example": [
"id",
"email",
"name"
]
},
"totalRows": {
"type": "integer",
"example": 3
},
"error": {
"type": "string",
"nullable": true,
"example": "HTTP 401: Unauthorized",
"description": "Present when `success` is false."
}
}
},
"DataSourceSyncResponse": {
"type": "object",
"additionalProperties": true,
"description": "Sync summary from the connector (imported/updated/failed counts).",
"example": {
"imported": 120,
"updated": 5,
"failed": 0
}
},
"InAppContent": {
"type": "object",
"description": "The rendered content of an in-app message.",
"properties": {
"title": {
"type": "string",
"example": "Your trial ends soon"
},
"body": {
"type": "string",
"example": "Upgrade now to keep your workflows running."
},
"ctaText": {
"type": "string",
"example": "Upgrade"
},
"ctaUrl": {
"type": "string",
"example": "https://app.example.com/billing"
},
"bgColor": {
"type": "string",
"example": "#111827"
},
"textColor": {
"type": "string",
"example": "#ffffff"
},
"image": {
"type": "string",
"nullable": true,
"example": "https://cdn.example.com/promo.png"
},
"dismissible": {
"type": "boolean",
"example": true
},
"targetSelector": {
"type": "string",
"nullable": true,
"example": "#upgrade-button",
"description": "CSS selector to anchor a `tooltip` to (tooltip type only)."
}
}
},
"InAppPageRule": {
"type": "object",
"description": "A URL condition — the message only shows on pages that match. Multiple rules are OR-ed.",
"properties": {
"type": {
"type": "string",
"enum": [
"url_contains",
"url_equals",
"url_starts_with"
],
"example": "url_contains"
},
"value": {
"type": "string",
"example": "/pricing"
}
}
},
"InAppMessage": {
"type": "object",
"properties": {
"id": {
"type": "string",
"example": "iam_5c"
},
"orgId": {
"type": "string",
"example": "org_123"
},
"name": {
"type": "string",
"example": "Trial upgrade nudge"
},
"status": {
"type": "string",
"enum": [
"draft",
"active",
"paused"
],
"example": "draft",
"description": "Only `active` messages are returned by the public match endpoint. Defaults to `draft`."
},
"type": {
"type": "string",
"enum": [
"banner",
"modal",
"slideout",
"tooltip"
],
"example": "banner",
"description": "Presentation style. Defaults to `banner`."
},
"position": {
"type": "string",
"example": "top",
"description": "Placement, e.g. `top`, `bottom`, `bottom-right`. Defaults to `top`."
},
"content": {
"$ref": "#/components/schemas/InAppContent"
},
"segmentId": {
"type": "string",
"nullable": true,
"example": "seg_1f2c",
"description": "When set, only visitors matching this segment see the message."
},
"pageRules": {
"type": "array",
"items": {
"$ref": "#/components/schemas/InAppPageRule"
},
"description": "URL conditions; empty means every page."
},
"startAt": {
"type": "string",
"format": "date-time",
"nullable": true
},
"endAt": {
"type": "string",
"format": "date-time",
"nullable": true
},
"frequency": {
"type": "string",
"example": "once",
"description": "`once` shows a visitor the message a single time. Defaults to `once`."
},
"maxImpressions": {
"type": "integer",
"example": 1,
"description": "Per-visitor impression cap (0 = unlimited). Defaults to 1."
},
"priority": {
"type": "integer",
"example": 0,
"description": "Higher priority wins when several messages match. Defaults to 0."
},
"totalImpressions": {
"type": "integer",
"example": 1200
},
"totalClicks": {
"type": "integer",
"example": 84
},
"totalDismissals": {
"type": "integer",
"example": 300
},
"createdBy": {
"type": "string",
"example": "usr_1"
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"updatedAt": {
"type": "string",
"format": "date-time"
}
}
},
"InAppMessageCreate": {
"type": "object",
"required": [
"name",
"content"
],
"properties": {
"name": {
"type": "string",
"example": "Trial upgrade nudge"
},
"type": {
"type": "string",
"enum": [
"banner",
"modal",
"slideout",
"tooltip"
],
"example": "banner"
},
"position": {
"type": "string",
"example": "top"
},
"content": {
"$ref": "#/components/schemas/InAppContent"
},
"segmentId": {
"type": "string",
"nullable": true,
"example": "seg_1f2c"
},
"pageRules": {
"type": "array",
"items": {
"$ref": "#/components/schemas/InAppPageRule"
}
},
"startAt": {
"type": "string",
"format": "date-time",
"nullable": true
},
"endAt": {
"type": "string",
"format": "date-time",
"nullable": true
},
"frequency": {
"type": "string",
"example": "once"
},
"maxImpressions": {
"type": "integer",
"example": 1
},
"priority": {
"type": "integer",
"example": 0
}
}
},
"InAppMatchRequest": {
"type": "object",
"required": [
"apiKey",
"visitorId"
],
"properties": {
"apiKey": {
"type": "string",
"example": "bc_live_xxxxxxxxxxxx",
"description": "Organization ingestion key (sent in the body, not a header)."
},
"visitorId": {
"type": "string",
"example": "user@example.com",
"description": "The current visitor."
},
"url": {
"type": "string",
"example": "https://app.example.com/pricing",
"description": "Current page URL, evaluated against each message's page rules."
}
}
},
"InAppMatchMessage": {
"type": "object",
"description": "A message that should be shown to the visitor right now.",
"properties": {
"id": {
"type": "string",
"example": "iam_5c"
},
"type": {
"type": "string",
"example": "banner"
},
"position": {
"type": "string",
"example": "top"
},
"content": {
"$ref": "#/components/schemas/InAppContent"
},
"priority": {
"type": "integer",
"example": 10
}
}
},
"InAppMatchResponse": {
"type": "object",
"properties": {
"messages": {
"type": "array",
"items": {
"$ref": "#/components/schemas/InAppMatchMessage"
},
"description": "Messages to render, highest priority first. Empty when nothing matches."
}
}
},
"InAppTrackRequest": {
"type": "object",
"required": [
"apiKey",
"messageId",
"visitorId",
"action"
],
"properties": {
"apiKey": {
"type": "string",
"example": "bc_live_xxxxxxxxxxxx",
"description": "Organization ingestion key (sent in the body)."
},
"messageId": {
"type": "string",
"example": "iam_5c"
},
"visitorId": {
"type": "string",
"example": "user@example.com"
},
"action": {
"type": "string",
"enum": [
"impression",
"click",
"dismiss"
],
"example": "impression"
}
}
}
},
"responses": {
"Unauthorized": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"BadRequest": {
"description": "Malformed request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"paths": {
"/api/track": {
"post": {
"tags": [
"Ingestion"
],
"summary": "Track an event",
"description": "Record a single product event for a visitor. Creates the visitor on first sight. Auto-categorizes the event and captures revenue/UTM attribution when present. The event is also evaluated in real time against event-triggered **automations** and **triggered campaigns**, so a matching enrollment or send fires the moment the event lands.",
"security": [
{
"ApiKeyAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TrackRequest"
}
}
}
},
"responses": {
"200": {
"description": "Accepted",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SuccessResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/identify": {
"post": {
"tags": [
"Ingestion"
],
"summary": "Identify a visitor",
"description": "Attach traits to a visitor and optionally merge an anonymous visitor (`previousVisitorId`) into a known identity, carrying over events and revenue.",
"security": [
{
"ApiKeyAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IdentifyRequest"
}
}
}
},
"responses": {
"200": {
"description": "Accepted",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SuccessResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/t/session-recording": {
"post": {
"tags": [
"Ingestion"
],
"summary": "Upload session recording chunks",
"description": "Store a batch of rrweb-style DOM events for later replay in the dashboard.",
"security": [
{
"ApiKeyAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SessionRecordingRequest"
}
}
}
},
"responses": {
"200": {
"description": "Accepted",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SuccessResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/revenue": {
"post": {
"tags": [
"Ingestion"
],
"summary": "Record a revenue transaction",
"description": "Record one payment (or refund, with a negative `amount`) from your own backend. Writes a revenue event AND updates the person's lifetime totals. Pass a stable `externalId` to make retries idempotent. Attribute with `visitorId` or `email`. See docs/REVENUE-INTEGRATIONS.md.",
"security": [
{
"ApiKeyAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"amount"
],
"properties": {
"amount": {
"type": "number",
"example": 149,
"description": "Negative = refund. `revenue` accepted as an alias."
},
"currency": {
"type": "string",
"default": "USD",
"example": "USD"
},
"visitorId": {
"type": "string",
"description": "Internal id or public visitor id (provide this or email)."
},
"email": {
"type": "string",
"description": "Resolves/creates the person (provide this or visitorId)."
},
"externalId": {
"type": "string",
"example": "invoice_5567",
"description": "Idempotency key within (org, provider)."
},
"eventName": {
"type": "string",
"example": "payment_received"
},
"occurredAt": {
"type": "string",
"example": "2026-07-10T12:00:00Z",
"description": "ISO or epoch ms; backdates imports."
},
"properties": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
},
"responses": {
"200": {
"description": "Duplicate externalId — ignored",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"recorded": {
"type": "boolean",
"example": false
},
"duplicate": {
"type": "boolean",
"example": true
},
"eventId": {
"type": "string"
}
}
}
}
}
},
"201": {
"description": "Recorded",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"recorded": {
"type": "boolean"
},
"eventId": {
"type": "string"
},
"visitorId": {
"type": "string"
}
}
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/revenue/bulk": {
"post": {
"tags": [
"Ingestion"
],
"summary": "Record many revenue transactions",
"description": "Record up to 1000 transactions in one call (CSV import, backfills). Each row is independent and idempotent by `externalId`.",
"security": [
{
"ApiKeyAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"transactions"
],
"properties": {
"transactions": {
"type": "array",
"maxItems": 1000,
"items": {
"type": "object",
"required": [
"amount"
],
"properties": {
"amount": {
"type": "number"
},
"currency": {
"type": "string",
"default": "USD"
},
"visitorId": {
"type": "string"
},
"email": {
"type": "string"
},
"externalId": {
"type": "string"
},
"eventName": {
"type": "string"
},
"occurredAt": {
"type": "string"
},
"properties": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
},
"responses": {
"200": {
"description": "Batch summary",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"total": {
"type": "integer"
},
"recorded": {
"type": "integer"
},
"duplicates": {
"type": "integer"
},
"skipped": {
"type": "integer"
},
"errors": {
"type": "array",
"items": {
"type": "object",
"properties": {
"row": {
"type": "integer"
},
"reason": {
"type": "string"
}
}
}
}
}
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/import/users": {
"post": {
"tags": [
"Bulk Import"
],
"summary": "Bulk import / upsert users",
"description": "Upsert up to 10,000 users by email in one call. Existing users are updated with change detection.",
"security": [
{
"BearerAuth": [],
"OrgId": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ImportUsersRequest"
}
}
}
},
"responses": {
"200": {
"description": "Import summary",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ImportUsersResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/import/events": {
"post": {
"tags": [
"Bulk Import"
],
"summary": "Bulk import historical events",
"description": "Attach historical events to existing users (matched by email). Users must already exist — import them first.",
"security": [
{
"BearerAuth": [],
"OrgId": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ImportEventsRequest"
}
}
}
},
"responses": {
"200": {
"description": "Import summary",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ImportEventsResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/import/status": {
"get": {
"tags": [
"Bulk Import"
],
"summary": "Import status",
"description": "Counts of visitors, identified users, and the last import time.",
"security": [
{
"BearerAuth": [],
"OrgId": []
}
],
"responses": {
"200": {
"description": "Status",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ImportStatusResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/auth/login": {
"post": {
"tags": [
"Authentication"
],
"summary": "Log in",
"description": "Exchange email + password for a session token and your organization's ingestion key.",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginRequest"
}
}
}
},
"responses": {
"200": {
"description": "Session",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/auth/me": {
"get": {
"tags": [
"Authentication"
],
"summary": "Current user + organizations",
"security": [
{
"BearerAuth": []
}
],
"responses": {
"200": {
"description": "User + memberships",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/keys": {
"get": {
"tags": [
"API Keys"
],
"summary": "List API keys",
"security": [
{
"BearerAuth": [],
"OrgId": []
}
],
"responses": {
"200": {
"description": "Keys",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ApiKey"
}
}
}
}
}
}
},
"post": {
"tags": [
"API Keys"
],
"summary": "Create an API key",
"security": [
{
"BearerAuth": [],
"OrgId": []
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"label": {
"type": "string",
"example": "Shopify app"
}
}
}
}
}
},
"responses": {
"200": {
"description": "Created key",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ApiKey"
}
}
}
}
}
}
},
"/api/keys/{id}": {
"delete": {
"tags": [
"API Keys"
],
"summary": "Revoke an API key",
"security": [
{
"BearerAuth": [],
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Revoked",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SuccessResponse"
}
}
}
}
}
}
},
"/health": {
"get": {
"tags": [
"System"
],
"summary": "Health check",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
},
"/api/analytics/live": {
"get": {
"tags": [
"Analytics"
],
"summary": "Live event feed",
"description": "The most recent events for the org, newest first, each enriched with the visitor's name and email. Poll with `since` to stream new events.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 50,
"maximum": 200
},
"description": "Max events to return (capped at 200)."
},
{
"name": "since",
"in": "query",
"required": false,
"schema": {
"type": "string",
"format": "date-time"
},
"description": "Only return events created after this ISO timestamp."
},
{
"name": "source",
"in": "query",
"required": false,
"schema": {
"type": "string",
"example": "shopify"
},
"description": "Filter events by their `properties.source` value."
}
],
"responses": {
"200": {
"description": "Recent events",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/LiveEvent"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/retention": {
"get": {
"tags": [
"Analytics"
],
"summary": "Weekly retention cohorts",
"description": "Cohorts of visitors grouped by their first-seen week, with the percentage still active in each subsequent week.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "weeks",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 12,
"maximum": 24
},
"description": "Number of weeks to analyze (capped at 24)."
}
],
"responses": {
"200": {
"description": "Retention cohorts",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RetentionResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/funnel": {
"post": {
"tags": [
"Analytics"
],
"summary": "Compute a conversion funnel",
"description": "Given an ordered list of event names, computes how many visitors completed each step in sequence, plus the conversion rate and drop-off at each stage.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FunnelRequest"
}
}
}
},
"responses": {
"200": {
"description": "Funnel result",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FunnelResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/kpi": {
"get": {
"tags": [
"Analytics"
],
"summary": "Headline KPIs",
"description": "Total events, active visitors, new visitors and events-per-user for the range, each with the previous equal-length period for comparison.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "startDate",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"example": 1719792000000
},
"description": "Range start as epoch milliseconds. Defaults to 30 days ago."
},
{
"name": "endDate",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"example": 1722384000000
},
"description": "Range end as epoch milliseconds. Defaults to now."
},
{
"name": "source",
"in": "query",
"required": false,
"schema": {
"type": "string",
"example": "shopify"
},
"description": "Filter events by their `properties.source` value."
}
],
"responses": {
"200": {
"description": "KPI summary",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/KpiResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/events-volume-range": {
"get": {
"tags": [
"Analytics"
],
"summary": "Daily event & visitor volume",
"description": "Per-day event and unique-visitor counts across the range, with gaps filled as zero.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "startDate",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"example": 1719792000000
},
"description": "Range start as epoch milliseconds. Defaults to 30 days ago."
},
{
"name": "endDate",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"example": 1722384000000
},
"description": "Range end as epoch milliseconds. Defaults to now."
},
{
"name": "source",
"in": "query",
"required": false,
"schema": {
"type": "string",
"example": "shopify"
},
"description": "Filter events by their `properties.source` value."
}
],
"responses": {
"200": {
"description": "Daily volume series",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/EventsVolumePoint"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/events-top": {
"get": {
"tags": [
"Analytics"
],
"summary": "Top events by volume",
"description": "The 20 most frequent event names for the org.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "source",
"in": "query",
"required": false,
"schema": {
"type": "string",
"example": "shopify"
},
"description": "Filter events by their `properties.source` value."
}
],
"responses": {
"200": {
"description": "Top events",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/EventCount"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/event-names": {
"get": {
"tags": [
"Analytics"
],
"summary": "Distinct event names",
"description": "Up to 200 distinct event names with counts — useful for populating filter dropdowns.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "source",
"in": "query",
"required": false,
"schema": {
"type": "string",
"example": "shopify"
},
"description": "Filter events by their `properties.source` value."
}
],
"responses": {
"200": {
"description": "Event names",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/EventCount"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/locations": {
"get": {
"tags": [
"Analytics"
],
"summary": "Visitors by country",
"description": "The top 20 countries by visitor count.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "source",
"in": "query",
"required": false,
"schema": {
"type": "string",
"example": "shopify"
},
"description": "Filter events by their `properties.source` value."
}
],
"responses": {
"200": {
"description": "Country breakdown",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/LabeledCount"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/event-categories": {
"get": {
"tags": [
"Analytics"
],
"summary": "Events by category",
"description": "Events bucketed into coarse categories (Navigation, Interaction, Authentication, Revenue, Error, Other).",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "source",
"in": "query",
"required": false,
"schema": {
"type": "string",
"example": "shopify"
},
"description": "Filter events by their `properties.source` value."
}
],
"responses": {
"200": {
"description": "Category breakdown",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/LabeledCount"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/revenue-kpi": {
"get": {
"tags": [
"Analytics"
],
"summary": "Revenue KPIs",
"description": "Net revenue, paying customers, ARPU, and conversion rate for the range vs. the previous equal-length period. See docs/REVENUE-INTEGRATIONS.md for how revenue is ingested.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "startDate",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"example": 1719792000000
},
"description": "Range start as epoch milliseconds. Defaults to 30 days ago."
},
{
"name": "endDate",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"example": 1722384000000
},
"description": "Range end as epoch milliseconds. Defaults to now."
}
],
"responses": {
"200": {
"description": "Revenue KPIs",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RevenueKpiResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/revenue": {
"get": {
"tags": [
"Analytics"
],
"summary": "Daily revenue series",
"description": "Daily revenue totals over the look-back window.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "days",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 90
},
"description": "Look-back window in days (used when startDate is omitted)."
},
{
"name": "startDate",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"example": 1719792000000
},
"description": "Range start as epoch milliseconds. Defaults to 30 days ago."
},
{
"name": "endDate",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"example": 1722384000000
},
"description": "Range end as epoch milliseconds. Defaults to now."
}
],
"responses": {
"200": {
"description": "Daily revenue",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/RevenuePoint"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/revenue-by-source": {
"get": {
"tags": [
"Analytics"
],
"summary": "Revenue by source",
"description": "Revenue attributed to each traffic source (from `properties.source` / `utm_source`).",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "startDate",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"example": 1719792000000
},
"description": "Range start as epoch milliseconds. Defaults to 30 days ago."
},
{
"name": "endDate",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"example": 1722384000000
},
"description": "Range end as epoch milliseconds. Defaults to now."
}
],
"responses": {
"200": {
"description": "Revenue by source",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/RevenueBySource"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/session-duration": {
"get": {
"tags": [
"Analytics"
],
"summary": "Average session duration",
"description": "Mean session length in seconds across recent sessions.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"responses": {
"200": {
"description": "Average duration",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SessionDurationResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/top-customers": {
"get": {
"tags": [
"Analytics"
],
"summary": "Top customers by revenue",
"description": "The highest-revenue visitors for the org.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 10,
"maximum": 50
},
"description": "Number of customers to return (capped at 50)."
}
],
"responses": {
"200": {
"description": "Top customers",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/TopCustomer"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/events-recent-filtered": {
"get": {
"tags": [
"Analytics"
],
"summary": "Paginated event stream",
"description": "Paginated, filterable recent events enriched with visitor and device context — powers the Live Stream view.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "page",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 1,
"minimum": 1
},
"description": "1-based page number."
},
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 50,
"maximum": 100
},
"description": "Items per page (capped at 100)."
},
{
"name": "eventFilter",
"in": "query",
"required": false,
"schema": {
"type": "string"
},
"description": "Restrict to a single event name."
},
{
"name": "source",
"in": "query",
"required": false,
"schema": {
"type": "string",
"example": "shopify"
},
"description": "Filter events by their `properties.source` value."
}
],
"responses": {
"200": {
"description": "Event page",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/EventsRecentResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/visitors-enriched": {
"get": {
"tags": [
"Analytics"
],
"summary": "Enriched visitor list",
"description": "Up to 500 visitors (newest activity first) with event counts, last event, revenue, geo and linked account.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"responses": {
"200": {
"description": "Visitors",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/VisitorEnriched"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/visitor-profile": {
"get": {
"tags": [
"Analytics"
],
"summary": "Visitor profile",
"description": "Full visitor record plus their 200 most recent events and total event count.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "visitorId",
"in": "query",
"required": true,
"schema": {
"type": "string",
"example": "user@example.com"
},
"description": "The visitor to fetch."
}
],
"responses": {
"200": {
"description": "Visitor profile",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/VisitorProfileResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"404": {
"description": "Visitor not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api/analytics/visitor-sessions": {
"get": {
"tags": [
"Analytics"
],
"summary": "Visitor sessions",
"description": "A visitor's events grouped into sessions (by session id, or by day when no session id is present).",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "visitorId",
"in": "query",
"required": true,
"schema": {
"type": "string",
"example": "user@example.com"
}
}
],
"responses": {
"200": {
"description": "Sessions",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/VisitorSession"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/visitor-activity": {
"get": {
"tags": [
"Analytics"
],
"summary": "Visitor activity summary",
"description": "Daily event counts (last 30 days), top events and top pages for a single visitor.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "visitorId",
"in": "query",
"required": true,
"schema": {
"type": "string",
"example": "user@example.com"
}
}
],
"responses": {
"200": {
"description": "Activity summary",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/VisitorActivityResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"404": {
"description": "Visitor not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api/analytics/accounts": {
"get": {
"tags": [
"Analytics"
],
"summary": "List accounts",
"description": "Up to 200 accounts (companies) with visitor counts and revenue, newest activity first.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"responses": {
"200": {
"description": "Accounts",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Account"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/accounts/{id}": {
"get": {
"tags": [
"Analytics"
],
"summary": "Account detail",
"description": "A single account with up to 100 of its visitors.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "acc_9"
},
"description": "Account id."
}
],
"responses": {
"200": {
"description": "Account",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"404": {
"description": "Account not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api/analytics/event-property-keys": {
"get": {
"tags": [
"Analytics"
],
"summary": "Property keys for an event",
"description": "Distinct `properties` keys seen on a given event name — used to populate group-by/breakdown selectors.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "eventName",
"in": "query",
"required": true,
"schema": {
"type": "string",
"example": "Signup Completed"
}
}
],
"responses": {
"200": {
"description": "Property keys",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"type": "string"
},
"example": [
"plan",
"source",
"mrr"
]
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/segmentation": {
"post": {
"tags": [
"Analytics"
],
"summary": "Time-series segmentation",
"description": "Daily counts for an event over a range, optionally broken down into series by a property key.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SegmentationRequest"
}
}
}
},
"responses": {
"200": {
"description": "Series",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SegmentationResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/ai-insights": {
"get": {
"tags": [
"Analytics"
],
"summary": "AI insights & recommendations",
"description": "Analyzes recent activity and returns narrative insights plus ready-to-create suggested segments and campaigns, with a summary of key totals.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "days",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 30
},
"description": "Analysis window in days."
}
],
"responses": {
"200": {
"description": "Insights",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AiInsightsResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/flows": {
"get": {
"tags": [
"Analytics"
],
"summary": "Session flows",
"description": "Reconstructs recent user journeys from events, naming and classifying each session (form completion, creation, exploration, etc.).",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "visitorId",
"in": "query",
"required": false,
"schema": {
"type": "string"
},
"description": "Restrict to one visitor."
},
{
"name": "sessionId",
"in": "query",
"required": false,
"schema": {
"type": "string"
},
"description": "Restrict to one session."
},
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 500,
"maximum": 2000
},
"description": "Max events to scan (capped at 2000)."
},
{
"name": "source",
"in": "query",
"required": false,
"schema": {
"type": "string",
"example": "shopify"
},
"description": "Filter events by their `properties.source` value."
}
],
"responses": {
"200": {
"description": "Flows",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FlowsResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/flow-patterns": {
"get": {
"tags": [
"Analytics"
],
"summary": "Common flow patterns",
"description": "Discovers recurring n-gram step sequences and named flows across sessions — no hardcoded funnels.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "days",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 7,
"maximum": 90
},
"description": "Look-back window in days (capped at 90)."
}
],
"responses": {
"200": {
"description": "Flow patterns",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FlowPatternsResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/dashboards": {
"get": {
"tags": [
"Analytics"
],
"summary": "List saved dashboards",
"description": "All custom dashboards saved for the org.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"responses": {
"200": {
"description": "Dashboards",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Dashboard"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
},
"post": {
"tags": [
"Analytics"
],
"summary": "Create a dashboard",
"description": "Create a new custom dashboard with an optional set of widgets.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DashboardCreate"
}
}
}
},
"responses": {
"200": {
"description": "Created dashboard",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Dashboard"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/dashboards/{id}": {
"get": {
"tags": [
"Analytics"
],
"summary": "Get a dashboard",
"description": "Fetch a single saved dashboard by id.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "a1b2c3d4"
},
"description": "Dashboard id."
}
],
"responses": {
"200": {
"description": "Dashboard",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Dashboard"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"404": {
"description": "Dashboard not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"put": {
"tags": [
"Analytics"
],
"summary": "Update a dashboard",
"description": "Replace a dashboard's name and/or widgets.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "a1b2c3d4"
},
"description": "Dashboard id."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DashboardCreate"
}
}
}
},
"responses": {
"200": {
"description": "Updated dashboard",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Dashboard"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
},
"delete": {
"tags": [
"Analytics"
],
"summary": "Delete a dashboard",
"description": "Permanently remove a saved dashboard.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "a1b2c3d4"
},
"description": "Dashboard id."
}
],
"responses": {
"200": {
"description": "Deleted",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"ok": {
"type": "boolean",
"example": true
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/analytics/dashboards/{id}/pin": {
"put": {
"tags": [
"Analytics"
],
"summary": "Toggle dashboard pin",
"description": "Pin or unpin a dashboard (toggles the `pinned` flag).",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "a1b2c3d4"
},
"description": "Dashboard id."
}
],
"responses": {
"200": {
"description": "Updated dashboard",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Dashboard"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/segments": {
"get": {
"tags": [
"Segments"
],
"summary": "List segments",
"description": "All segments for the org, newest first.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"responses": {
"200": {
"description": "Segments",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Segment"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
},
"post": {
"tags": [
"Segments"
],
"summary": "Create a segment",
"description": "Create a segment from a nested rule tree. `name` and `rules` are required.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SegmentCreate"
}
}
}
},
"responses": {
"201": {
"description": "Created segment",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Segment"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/segments/preview": {
"post": {
"tags": [
"Segments"
],
"summary": "Preview a rule set",
"description": "Evaluate an arbitrary rule tree without saving a segment and return how many visitors would match.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SegmentPreviewRequest"
}
}
}
},
"responses": {
"200": {
"description": "Match count",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CountResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/segments/schema": {
"get": {
"tags": [
"Segments"
],
"summary": "Discover segmentable fields",
"description": "Live schema for the segment builder: person + account fields (built-in and discovered from data), event names with their property keys, sibling segments (for `audience` conditions), campaigns, and observed platforms. Sampled/bounded so it stays cheap at scale.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"responses": {
"200": {
"description": "Discovered schema",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SegmentSchemaResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/segments/{id}": {
"get": {
"tags": [
"Segments"
],
"summary": "Get a segment",
"description": "Fetch a single segment by id, including its rule tree and cached match count.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "seg_1f2c"
},
"description": "Segment id."
}
],
"responses": {
"200": {
"description": "Segment",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Segment"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"404": {
"description": "Segment not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"put": {
"tags": [
"Segments"
],
"summary": "Update a segment",
"description": "Update a segment's name, description and/or rules.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "seg_1f2c"
},
"description": "Segment id."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SegmentUpdate"
}
}
}
},
"responses": {
"200": {
"description": "Updated segment",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Segment"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
},
"delete": {
"tags": [
"Segments"
],
"summary": "Delete a segment",
"description": "Permanently remove a segment.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "seg_1f2c"
},
"description": "Segment id."
}
],
"responses": {
"200": {
"description": "Deleted",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SuccessResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/segments/{id}/evaluate": {
"post": {
"tags": [
"Segments"
],
"summary": "Evaluate a segment",
"description": "Recompute the segment's membership, cache the match count / timestamp, and return the count plus a sample of matching visitors.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "seg_1f2c"
},
"description": "Segment id."
}
],
"responses": {
"200": {
"description": "Evaluation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SegmentEvaluateResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/segments/{id}/visitors": {
"get": {
"tags": [
"Segments"
],
"summary": "List segment members",
"description": "Paginated list of visitors currently matching the segment.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "seg_1f2c"
},
"description": "Segment id."
},
{
"name": "page",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 1,
"minimum": 1
},
"description": "1-based page number."
},
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 50,
"maximum": 100
},
"description": "Items per page (capped at 100)."
}
],
"responses": {
"200": {
"description": "Members",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SegmentVisitorsResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/campaigns": {
"get": {
"tags": [
"Campaigns"
],
"summary": "List campaigns",
"description": "All campaigns for the org (newest updated first), with linked segment and template names.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "status",
"in": "query",
"required": false,
"schema": {
"type": "string",
"example": "draft"
},
"description": "Filter by status."
},
{
"name": "mode",
"in": "query",
"required": false,
"schema": {
"type": "string",
"example": "bulk"
},
"description": "Filter by campaign mode (`bulk` / `triggered`)."
}
],
"responses": {
"200": {
"description": "Campaigns",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Campaign"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
},
"post": {
"tags": [
"Campaigns"
],
"summary": "Create a campaign",
"description": "Create a draft campaign. Only `name` is required; everything else has sensible defaults.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignCreate"
}
}
}
},
"responses": {
"201": {
"description": "Created campaign",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Campaign"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/campaigns/{id}": {
"get": {
"tags": [
"Campaigns"
],
"summary": "Get a campaign",
"description": "Fetch a single campaign by id, with its full segment and template included.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "cmp_7a"
},
"description": "Campaign id."
}
],
"responses": {
"200": {
"description": "Campaign",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Campaign"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"404": {
"description": "Campaign not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"put": {
"tags": [
"Campaigns"
],
"summary": "Update a campaign",
"description": "Update a **draft** campaign. Non-draft campaigns cannot be edited.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "cmp_7a"
},
"description": "Campaign id."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignCreate"
}
}
}
},
"responses": {
"200": {
"description": "Updated campaign",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Campaign"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
},
"delete": {
"tags": [
"Campaigns"
],
"summary": "Delete a campaign",
"description": "Delete a **draft** or **cancelled** campaign and its send/event records.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "cmp_7a"
},
"description": "Campaign id."
}
],
"responses": {
"200": {
"description": "Deleted",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SuccessResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/campaigns/{id}/schedule": {
"post": {
"tags": [
"Campaigns"
],
"summary": "Schedule a campaign",
"description": "Move a draft campaign to `scheduled` for a future send time.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "cmp_7a"
},
"description": "Campaign id."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignScheduleRequest"
}
}
}
},
"responses": {
"200": {
"description": "Scheduled campaign",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Campaign"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/campaigns/{id}/send-now": {
"post": {
"tags": [
"Campaigns"
],
"summary": "Send a campaign now",
"description": "Immediately begin sending a draft or scheduled campaign to its segment. Sending runs asynchronously.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "cmp_7a"
},
"description": "Campaign id."
}
],
"responses": {
"200": {
"description": "Send initiated",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignSendResult"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/campaigns/{id}/send-test": {
"post": {
"tags": [
"Campaigns"
],
"summary": "Send a test email",
"description": "Send a one-off rendered test of the campaign to a single address.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "cmp_7a"
},
"description": "Campaign id."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignSendTestRequest"
}
}
}
},
"responses": {
"200": {
"description": "Test sent",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignSendResult"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/campaigns/{id}/pause": {
"post": {
"tags": [
"Campaigns"
],
"summary": "Pause a campaign",
"description": "Set the campaign status to `paused`.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "cmp_7a"
},
"description": "Campaign id."
}
],
"responses": {
"200": {
"description": "Paused campaign",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Campaign"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/campaigns/{id}/cancel": {
"post": {
"tags": [
"Campaigns"
],
"summary": "Cancel a campaign",
"description": "Set the campaign status to `cancelled`.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "cmp_7a"
},
"description": "Campaign id."
}
],
"responses": {
"200": {
"description": "Cancelled campaign",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Campaign"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/campaigns/{id}/duplicate": {
"post": {
"tags": [
"Campaigns"
],
"summary": "Duplicate a campaign",
"description": "Create a new draft copy of the campaign (named \"… (copy)\").",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "cmp_7a"
},
"description": "Campaign id."
}
],
"responses": {
"201": {
"description": "Cloned campaign",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Campaign"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/campaigns/{id}/activate": {
"post": {
"tags": [
"Campaigns"
],
"summary": "Activate a campaign",
"description": "Mark the campaign active (for triggered/recurring campaigns), scheduling the next recurring run when configured.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "cmp_7a"
},
"description": "Campaign id."
}
],
"responses": {
"200": {
"description": "Activated campaign",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Campaign"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/campaigns/{id}/deactivate": {
"post": {
"tags": [
"Campaigns"
],
"summary": "Deactivate a campaign",
"description": "Clear the campaign's `isActive` flag.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "cmp_7a"
},
"description": "Campaign id."
}
],
"responses": {
"200": {
"description": "Deactivated campaign",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Campaign"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/campaigns/{id}/sends": {
"get": {
"tags": [
"Campaigns"
],
"summary": "List campaign sends",
"description": "Paginated per-recipient send records for the campaign.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "cmp_7a"
},
"description": "Campaign id."
},
{
"name": "page",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 1,
"minimum": 1
},
"description": "1-based page number."
},
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 50,
"maximum": 100
},
"description": "Items per page (capped at 100)."
},
{
"name": "status",
"in": "query",
"required": false,
"schema": {
"type": "string",
"example": "delivered"
},
"description": "Filter sends by delivery status."
}
],
"responses": {
"200": {
"description": "Sends",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignSendsResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/campaigns/{id}/analytics": {
"get": {
"tags": [
"Campaigns"
],
"summary": "Campaign analytics",
"description": "Delivery timeline (sent/opened/clicked per day), top clicked links, and a geographic breakdown.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "cmp_7a"
},
"description": "Campaign id."
}
],
"responses": {
"200": {
"description": "Analytics",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignAnalyticsResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/templates": {
"get": {
"tags": [
"Templates"
],
"summary": "List templates",
"description": "All non-archived templates for the org.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "category",
"in": "query",
"required": false,
"schema": {
"type": "string",
"example": "marketing"
},
"description": "Filter by category."
}
],
"responses": {
"200": {
"description": "Templates",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Template"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
},
"post": {
"tags": [
"Templates"
],
"summary": "Create a template",
"description": "Create an email template. `{{variable}}` names in the subject/HTML are auto-extracted into `variables`.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TemplateCreate"
}
}
}
},
"responses": {
"201": {
"description": "Created template",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Template"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/templates/render-preview": {
"post": {
"tags": [
"Templates"
],
"summary": "Render a template preview",
"description": "Interpolate a template (by `templateId` or raw `html`) against a `context` object and return the rendered HTML.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TemplateRenderRequest"
}
}
}
},
"responses": {
"200": {
"description": "Rendered HTML",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TemplateRenderResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/templates/{id}": {
"get": {
"tags": [
"Templates"
],
"summary": "Get a template",
"description": "Fetch a single template by id, including its extracted variables.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "tpl_9d"
},
"description": "Template id."
}
],
"responses": {
"200": {
"description": "Template",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Template"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"404": {
"description": "Template not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"put": {
"tags": [
"Templates"
],
"summary": "Update a template",
"description": "Update a template. Variables are re-extracted from the resulting subject/HTML.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "tpl_9d"
},
"description": "Template id."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TemplateCreate"
}
}
}
},
"responses": {
"200": {
"description": "Updated template",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Template"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
},
"delete": {
"tags": [
"Templates"
],
"summary": "Archive a template",
"description": "Soft-delete a template by marking it archived; it no longer appears in listings.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "tpl_9d"
},
"description": "Template id."
}
],
"responses": {
"200": {
"description": "Archived",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SuccessResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/templates/{id}/duplicate": {
"post": {
"tags": [
"Templates"
],
"summary": "Duplicate a template",
"description": "Create a copy of the template (named \"… (copy)\").",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "tpl_9d"
},
"description": "Template id."
}
],
"responses": {
"201": {
"description": "Cloned template",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Template"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/automations": {
"get": {
"tags": [
"Automations"
],
"summary": "List automations",
"description": "All automations for the org with their entry segment, newest first.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"responses": {
"200": {
"description": "Automations",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Automation"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
},
"post": {
"tags": [
"Automations"
],
"summary": "Create an automation",
"description": "Create a draft automation. `name`, `triggerType` and `steps` are required.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AutomationCreate"
}
}
}
},
"responses": {
"201": {
"description": "Created automation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Automation"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/automations/{id}": {
"get": {
"tags": [
"Automations"
],
"summary": "Get an automation",
"description": "Fetch an automation with its entry segment and enrollment counts grouped by status.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "aut_3"
},
"description": "Automation id."
}
],
"responses": {
"200": {
"description": "Automation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AutomationDetail"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"404": {
"description": "Automation not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"put": {
"tags": [
"Automations"
],
"summary": "Update an automation",
"description": "Update a **draft** or **paused** automation.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "aut_3"
},
"description": "Automation id."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AutomationCreate"
}
}
}
},
"responses": {
"200": {
"description": "Updated automation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Automation"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
},
"delete": {
"tags": [
"Automations"
],
"summary": "Delete an automation",
"description": "Delete an automation and all of its enrollments.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "aut_3"
},
"description": "Automation id."
}
],
"responses": {
"200": {
"description": "Deleted",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SuccessResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/automations/{id}/activate": {
"post": {
"tags": [
"Automations"
],
"summary": "Activate an automation",
"description": "Set the automation status to `active` so visitors can be enrolled.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "aut_3"
},
"description": "Automation id."
}
],
"responses": {
"200": {
"description": "Activated automation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Automation"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/automations/{id}/pause": {
"post": {
"tags": [
"Automations"
],
"summary": "Pause an automation",
"description": "Set the automation status to `paused`.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "aut_3"
},
"description": "Automation id."
}
],
"responses": {
"200": {
"description": "Paused automation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Automation"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/automations/{id}/archive": {
"post": {
"tags": [
"Automations"
],
"summary": "Archive an automation",
"description": "Set the automation status to `archived`.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "aut_3"
},
"description": "Automation id."
}
],
"responses": {
"200": {
"description": "Archived automation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Automation"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/automations/{id}/enrollments": {
"get": {
"tags": [
"Automations"
],
"summary": "List enrollments",
"description": "Paginated visitor enrollments for the automation.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "aut_3"
},
"description": "Automation id."
},
{
"name": "page",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 1,
"minimum": 1
},
"description": "1-based page number."
},
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 50,
"maximum": 100
},
"description": "Items per page (capped at 100)."
},
{
"name": "status",
"in": "query",
"required": false,
"schema": {
"type": "string",
"example": "active"
},
"description": "Filter enrollments by status."
}
],
"responses": {
"200": {
"description": "Enrollments",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/EnrollmentsResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/automations/{id}/enroll": {
"post": {
"tags": [
"Automations"
],
"summary": "Enroll a visitor",
"description": "Manually enroll a visitor into an **active** automation. Returns 409 if the visitor is already enrolled and re-entry is disallowed.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "aut_3"
},
"description": "Automation id."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AutomationEnrollRequest"
}
}
}
},
"responses": {
"201": {
"description": "Enrollment",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Enrollment"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"409": {
"description": "Visitor already enrolled and re-entry is not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api/churn/overview": {
"get": {
"tags": [
"Churn"
],
"summary": "Churn overview",
"description": "Org-wide churn summary: scored visitors, average score, at-risk count, revenue at risk and the risk-level distribution.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"responses": {
"200": {
"description": "Overview",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChurnOverview"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/churn/at-risk": {
"get": {
"tags": [
"Churn"
],
"summary": "At-risk visitors",
"description": "Paginated list of visitors at or above a minimum risk level, highest score first.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "page",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 1,
"minimum": 1
},
"description": "1-based page number."
},
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 50,
"maximum": 100
},
"description": "Items per page (capped at 100)."
},
{
"name": "minLevel",
"in": "query",
"required": false,
"schema": {
"type": "string",
"enum": [
"low",
"medium",
"high",
"critical"
],
"default": "medium"
},
"description": "Minimum risk level to include."
}
],
"responses": {
"200": {
"description": "At-risk visitors",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChurnAtRiskResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/churn/trend": {
"get": {
"tags": [
"Churn"
],
"summary": "Churn risk trend",
"description": "Daily churn-risk distribution over the window, for charting.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "days",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 30,
"maximum": 90
},
"description": "Window in days (capped at 90)."
}
],
"responses": {
"200": {
"description": "Trend",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChurnTrendResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/churn/score-all": {
"post": {
"tags": [
"Churn"
],
"summary": "Rescore the whole org",
"description": "Kick off batch churn scoring for every visitor. Returns immediately; scoring runs in the background. **Requires an admin role.**",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"responses": {
"200": {
"description": "Scoring started",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChurnScoreAllResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/churn/visitor/{visitorId}": {
"get": {
"tags": [
"Churn"
],
"summary": "Visitor churn detail",
"description": "Freshly compute a single visitor's churn score and return it with their recent activity timeline.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "visitorId",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "user@example.com"
},
"description": "Visitor id."
}
],
"responses": {
"200": {
"description": "Churn detail",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChurnVisitorDetail"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"404": {
"description": "Visitor not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api/churn/accounts": {
"get": {
"tags": [
"Churn"
],
"summary": "Account-level churn",
"description": "Paginated accounts ranked by aggregate churn risk across their visitors, with per-account revenue at risk.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "page",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 1,
"minimum": 1
},
"description": "1-based page number."
},
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 50,
"maximum": 100
},
"description": "Items per page (capped at 100)."
}
],
"responses": {
"200": {
"description": "Account risk",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChurnAccountsResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/data-sources": {
"get": {
"tags": [
"Data Sources"
],
"summary": "List data sources",
"description": "All configured data-source connectors for the org.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"responses": {
"200": {
"description": "Data sources",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/DataSource"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
},
"post": {
"tags": [
"Data Sources"
],
"summary": "Create a data source",
"description": "Register a new HTTP endpoint or Stripe connector. `name` is required.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DataSourceCreate"
}
}
}
},
"responses": {
"201": {
"description": "Created data source",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DataSource"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/data-sources/{id}": {
"put": {
"tags": [
"Data Sources"
],
"summary": "Update a data source",
"description": "Update connector configuration (URL, headers, mapping, schedule, enabled flag, etc.).",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "ds_2"
},
"description": "Data source id."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DataSourceUpdate"
}
}
}
},
"responses": {
"200": {
"description": "Updated data source",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DataSource"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"404": {
"description": "Data source not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"tags": [
"Data Sources"
],
"summary": "Delete a data source",
"description": "Permanently remove a data-source connector.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "ds_2"
},
"description": "Data source id."
}
],
"responses": {
"200": {
"description": "Deleted",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SuccessResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"404": {
"description": "Data source not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api/engage/data-sources/{id}/test": {
"post": {
"tags": [
"Data Sources"
],
"summary": "Test a data source",
"description": "Fetch the source and return a few sample rows plus the detected columns, without importing anything.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "ds_2"
},
"description": "Data source id."
}
],
"responses": {
"200": {
"description": "Test result",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DataSourceTestResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/data-sources/{id}/sync-now": {
"post": {
"tags": [
"Data Sources"
],
"summary": "Sync a data source now",
"description": "Run an immediate sync of the connector, importing/updating users and events per its mapping.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "ds_2"
},
"description": "Data source id."
}
],
"responses": {
"200": {
"description": "Sync summary",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DataSourceSyncResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"404": {
"description": "Data source not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api/engage/in-app/messages": {
"get": {
"tags": [
"In-app Messages"
],
"summary": "List in-app messages",
"description": "All in-app messages for the org, newest first.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"responses": {
"200": {
"description": "Messages",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/InAppMessage"
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
},
"post": {
"tags": [
"In-app Messages"
],
"summary": "Create an in-app message",
"description": "Create a message. `name` and `content` are required; new messages start in `draft` — activate them to make them eligible for matching.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InAppMessageCreate"
}
}
}
},
"responses": {
"201": {
"description": "Created message",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InAppMessage"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/in-app/messages/{id}": {
"get": {
"tags": [
"In-app Messages"
],
"summary": "Get an in-app message",
"description": "Fetch a single in-app message by id.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "iam_5c"
},
"description": "Message id."
}
],
"responses": {
"200": {
"description": "Message",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InAppMessage"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"404": {
"description": "Message not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"put": {
"tags": [
"In-app Messages"
],
"summary": "Update an in-app message",
"description": "Update a message. Only supplied fields are changed.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "iam_5c"
},
"description": "Message id."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InAppMessageCreate"
}
}
}
},
"responses": {
"200": {
"description": "Updated message",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InAppMessage"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"404": {
"description": "Message not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"tags": [
"In-app Messages"
],
"summary": "Delete an in-app message",
"description": "Permanently remove a message and its impression records.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "iam_5c"
},
"description": "Message id."
}
],
"responses": {
"200": {
"description": "Deleted",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SuccessResponse"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
},
"404": {
"description": "Message not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api/engage/in-app/messages/{id}/activate": {
"post": {
"tags": [
"In-app Messages"
],
"summary": "Activate an in-app message",
"description": "Set the message status to `active` so it can be returned by the public match endpoint.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "iam_5c"
},
"description": "Message id."
}
],
"responses": {
"200": {
"description": "Activated message",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InAppMessage"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/in-app/messages/{id}/pause": {
"post": {
"tags": [
"In-app Messages"
],
"summary": "Pause an in-app message",
"description": "Set the message status to `paused` so it stops matching.",
"security": [
{
"BearerAuth": []
},
{
"OrgId": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"example": "iam_5c"
},
"description": "Message id."
}
],
"responses": {
"200": {
"description": "Paused message",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InAppMessage"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthorized"
}
}
}
},
"/api/engage/in-app/match": {
"post": {
"tags": [
"In-app Messages"
],
"summary": "Match in-app messages (public)",
"description": "Called by the web SDK on each page. Returns the active messages a visitor should see right now, after applying segment targeting, page-URL rules, scheduling windows and per-visitor frequency / impression caps — highest priority first. **Public**: authenticate with the org ingestion key in the request body (no Bearer token).",
"security": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InAppMatchRequest"
}
}
}
},
"responses": {
"200": {
"description": "Messages to show",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InAppMatchResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"description": "Invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api/engage/in-app/track": {
"post": {
"tags": [
"In-app Messages"
],
"summary": "Track an in-app interaction (public)",
"description": "Record an `impression`, `click` or `dismiss` for a message, updating its aggregate counters and the visitor's frequency history. **Public**: authenticate with the org ingestion key in the request body.",
"security": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/InAppTrackRequest"
}
}
}
},
"responses": {
"200": {
"description": "Recorded",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SuccessResponse"
}
}
}
},
"400": {
"$ref": "#/components/responses/BadRequest"
},
"401": {
"description": "Invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Message not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
}
},
"x-tagGroups": [
{
"name": "Core API",
"tags": [
"Ingestion",
"Bulk Import",
"Authentication",
"API Keys",
"System"
]
},
{
"name": "Management API",
"tags": [
"Analytics",
"Segments",
"Campaigns",
"Templates",
"Automations",
"Churn",
"Data Sources",
"In-app Messages"
]
}
]
}
}
],
"layout": "modern",
"hideDownloadButton": false,
"defaultHttpClient": {
"targetKey": "shell",
"clientKey": "curl"
},
"metaData": {
"title": "Banchurn Docs",
"description": "Product guides and the full REST API — ingest analytics and manage segments, campaigns, automations, and churn."
},
"theme": "default"
})