openapi: 3.1.0 tags: - name: Abandonment description: Cart abandonments - name: Account description: Accounts - name: Cart description: Carts - name: Discount description: Discounts - name: Event description: Events - name: Flow description: Flows - name: List description: List - name: Message description: Messages - name: OptinTool description: Opt-in tools - name: Order description: Orders - name: Segment description: Segments - name: Subscriber description: Subscribers - name: Subscription description: Subscriptions - name: Webhook description: Webhooks servers: - url: 'https://api.recart.com/app-integrations/2023-12' description: Production info: title: Recart API description: Open API description of the Recart API version: 2023-12 contact: name: Recart url: https://recart.com paths: /accounts: get: summary: Retrieve the accounts of the API key tags: - Account operationId: listAccounts security: - ApiKeyAuth: [] description: | List the accounts the API key gives access to. An API key belongs to one account, so the list carries a single entry: the account's id, name, domain, currency and time zone. Use the account's `id` wherever an integration needs to identify the account. responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Account' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /flows: get: summary: Retrieve list of flows tags: - Flow operationId: listFlows security: - ApiKeyAuth: [] description: | List flows. responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Flow' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/flows/{id}': get: summary: Receive a single flow tags: - Flow operationId: getFlow security: - ApiKeyAuth: [] description: | Get flow by ID parameters: - name: id in: path required: true description: ID of the flow schema: type: string responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/Flow' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/flows/views/{name}': get: summary: Statistics view of the site's flows and campaigns tags: - Flow operationId: getFlowsView security: - ApiKeyAuth: [] description: | Account-level SMS statistics — the numbers behind the Automated Flows overview and the Campaigns list. `name` picks the view. When the date range is omitted it defaults to the last 7 days. `sms-summary` returns one statistics object for the SMS channel; `tags` narrows it — `automated` for the Automated Flows header, `blast` for the Campaigns header, or omit `tags` for the whole channel. It carries no `recipients` and no `revenuePerRecipient`: the channel total has no first-message cohort — RPM (`revenuePerMessage`) is the per-message figure here, as on the dashboard header. For the Campaigns header's Recipients and RPR read the `blast` entry of `flow-groups-summary`. `flow-groups-summary` returns one entry per flow group — the dashboard's categories (e.g. `default-welcome`, `abandonment`, `receipt`, `fulfillment`, `back-in-stock`), each integration tag the site uses, and `blast` for campaigns. `automated-flows-summary` returns one entry per automated flow of the site — its `flowId`, `name` and statistics; a flow without sends in the range is still present, with zeros. `tags` narrows it to a category. `campaign-flows-summary` returns one entry per campaign with activity in the range — the campaign's `flowId`, `name` and statistics. Because every entry names its own flow, no separate list call is needed to label the rows. Every view is a range total. parameters: - name: name in: path required: true description: The view to return schema: type: string enum: - sms-summary - flow-groups-summary - automated-flows-summary - campaign-flows-summary - name: dateFrom in: query description: | First day of the range, inclusive (YYYY-MM-DD, UTC). Defaults to 7 days before `dateTo`. Must not be older than 18 months — the API does not serve older data, and an older `dateFrom` returns 400. schema: type: string format: date example: '2026-08-25' - name: dateTo in: query description: | Last day of the range, inclusive — `dateTo=2026-08-31` includes the whole of 2026-08-31 (UTC). Defaults to today. schema: type: string format: date example: '2026-08-31' - name: tags in: query description: | sms-summary and automated-flows-summary only — flow tags; a flow must carry all of them. `sms` is always applied. schema: type: array items: type: string responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: description: | Always one resource of type flow-views; attributes holds the requested view under its name. $ref: '#/components/schemas/FlowViews' examples: sms-summary: summary: name=sms-summary value: data: type: flow-views attributes: sms-summary: sent: 68700 clicked: 4040 clickRate: 0.0588 converted: 604 sales: USD: 48423 EUR: 44680.5 spent: USD: 2061 roi: 23.5 optOutRate: 0.0048 spamRate: 0.0001 revenuePerMessage: 0.7 flow-groups-summary: summary: name=flow-groups-summary — one entry per group value: data: type: flow-views attributes: flow-groups-summary: - group: abandonment sent: 18400 recipients: 17900 clicked: 1210 clickRate: 0.0658 converted: 204 sales: USD: 16210 spent: USD: 552 roi: 29.37 optOutRate: 0.0031 spamRate: 0 revenuePerRecipient: 0.91 revenuePerMessage: 0.88 - group: default-welcome sent: 9100 recipients: 9100 clicked: 690 clickRate: 0.0758 converted: 88 sales: USD: 7402.5 spent: USD: 273 roi: 27.12 optOutRate: 0.0092 spamRate: 0.0001 revenuePerRecipient: 0.81 revenuePerMessage: 0.81 - group: blast sent: 41200 recipients: 41200 clicked: 2140 clickRate: 0.0519 converted: 312 sales: USD: 24810.5 spent: USD: 1236 roi: 20.07 optOutRate: 0.0041 spamRate: 0.0002 revenuePerRecipient: 0.6 revenuePerMessage: 0.6 automated-flows-summary: summary: name=automated-flows-summary — one entry per automated flow value: data: type: flow-views attributes: automated-flows-summary: - flowId: 6138d0ac2d79e00001210035 name: Abandoned Cart sent: 9100 recipients: 9100 clicked: 690 clickRate: 0.0758 converted: 88 sales: USD: 7402.5 spent: USD: 273 roi: 27.12 optOutRate: 0.0092 spamRate: 0.0001 revenuePerRecipient: 0.81 revenuePerMessage: 0.81 - flowId: 6138d0ac2d79e00001210036 name: Welcome flow sent: 6200 recipients: 6100 clicked: 410 clickRate: 0.0661 converted: 61 sales: USD: 5104 spent: USD: 186 roi: 27.44 optOutRate: 0.0026 spamRate: 0 revenuePerRecipient: 0.84 revenuePerMessage: 0.82 campaign-flows-summary: summary: name=campaign-flows-summary — one entry per campaign, keyed by flowId value: data: type: flow-views attributes: campaign-flows-summary: - flowId: 68a0f1c7e8c9d2b001234abc name: Labor Day 20% off sent: 24700 recipients: 24700 clicked: 1310 clickRate: 0.053 converted: 189 sales: USD: 15020.5 spent: USD: 741 roi: 20.27 optOutRate: 0.0038 spamRate: 0.0001 revenuePerRecipient: 0.61 revenuePerMessage: 0.61 - flowId: 68a0f1c7e8c9d2b001234abd name: Back to school — 15% off sent: 16500 recipients: 16500 clicked: 830 clickRate: 0.0503 converted: 123 sales: USD: 9790 spent: USD: 495 roi: 19.78 optOutRate: 0.0044 spamRate: 0.0003 revenuePerRecipient: 0.59 revenuePerMessage: 0.59 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /automated-flows: get: summary: Retrieve list of automated flows tags: - Flow operationId: listAutomatedFlows security: - ApiKeyAuth: [] description: | The site's automated flows — configuration only, no statistics. Default page size 100. parameters: - name: limit in: query description: Maximum number of automated flows to return schema: type: integer minimum: 1 maximum: 100 default: 100 - name: offset in: query description: Number of automated flows to skip, for pagination schema: type: integer minimum: 0 default: 0 - name: tags in: query description: | Filter to flows carrying ALL given tags. Dashboard groups map to umbrella tags: default-welcome, joined-a-segment, abandonment, receipt, fulfillment, back-in-stock, integration (plus the specific integration's own tag), subscriber-support. schema: type: array items: type: string responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/AutomatedFlow' examples: automated: summary: An automated flow value: data: - type: automated-flows attributes: id: 655637c97825e6ae655fe1b5 name: Welcome flow status: active tags: - default-welcome - automated isQuietHoursEnabled: true isSmartSendingEnabled: false createdAt: '2026-01-10T09:00:00.000Z' updatedAt: '2026-08-20T09:00:00.000Z' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/automated-flows/{id}': get: summary: Receive a single automated flow tags: - Flow operationId: getAutomatedFlow security: - ApiKeyAuth: [] description: | One automated flow with its full structure: every item with its content and outbound edges resolved to item ids — `entryFlowItemId` is the first item; `nextItemId: null` means end of branch. The id of a campaign-backed flow returns 404 — use `/campaign-flows/{id}` instead. parameters: - name: id in: path required: true description: ID of the automated flow schema: type: string responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/AutomatedFlowDetail' examples: automated: summary: Welcome message, delay, conditional split, follow-up message value: data: type: automated-flows attributes: id: 655637c97825e6ae655fe1b5 name: Welcome flow status: active tags: - default-welcome - automated isQuietHoursEnabled: true isSmartSendingEnabled: false createdAt: '2026-01-10T09:00:00.000Z' updatedAt: '2026-08-20T09:00:00.000Z' entryFlowItemId: 655637c97825e6ae655fe401 items: - type: flow-item attributes: type: sms id: 655637c97825e6ae655fe401 name: Welcome message messages: - text: 'Welcome to our SMS list! Reply STOP to opt out.' imageUrl: null nextItemId: 655637c97825e6ae655fe402 - type: flow-item attributes: type: delay id: 655637c97825e6ae655fe402 delayType: delay durationInSeconds: 86400 nextItemId: 655637c97825e6ae655fe403 - type: flow-item attributes: type: conditional-split id: 655637c97825e6ae655fe403 branches: - expression: any: - fact: hasPurchased operator: equal value: true nextItemId: 655637c97825e6ae655fe404 defaultNextItemId: null - type: flow-item attributes: type: sms id: 655637c97825e6ae655fe404 name: Follow-up message messages: - text: 'Thanks for joining! Here is 10% off your first order.' imageUrl: null nextItemId: null 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/automated-flows/{id}/views/{name}': get: summary: Statistics view of an automated flow tags: - Flow operationId: getAutomatedFlowView security: - ApiKeyAuth: [] description: | One statistics view of an automated flow. `name` picks the view. When the date range is omitted it defaults to the last 7 days. The id of a campaign-backed flow returns 404 — use `/campaign-flows/{id}/views/{name}` instead. `flow-summary` returns the flow's totals for the range. `flow-items-summary` returns an object keyed by `flowItemId` — the same id as `items[]` on `/automated-flows/{id}` — with one key per message item that recorded activity in the range; a missing key means no activity. parameters: - name: id in: path required: true description: ID of the automated flow schema: type: string - name: name in: path required: true description: The view to return schema: type: string enum: - flow-summary - flow-items-summary - name: dateFrom in: query description: | First day of the range, inclusive (YYYY-MM-DD, UTC). Defaults to 7 days before `dateTo`. Must not be older than 18 months — the API does not serve older data, and an older `dateFrom` returns 400. schema: type: string format: date example: '2026-08-25' - name: dateTo in: query description: | Last day of the range, inclusive — `dateTo=2026-08-31` includes the whole of 2026-08-31 (UTC). Defaults to today. schema: type: string format: date example: '2026-08-31' responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: description: | Always one resource of type automated-flow-views; attributes holds the requested view under its name. $ref: '#/components/schemas/AutomatedFlowViews' examples: flow-summary: summary: name=flow-summary value: data: type: automated-flow-views attributes: flow-summary: sent: 12900 recipients: 9100 clicked: 900 clickRate: 0.0698 converted: 110 sales: USD: 9252.5 spent: USD: 387 roi: 23.91 optOutRate: 0.0095 spamRate: 0.0001 revenuePerRecipient: 1.02 revenuePerMessage: 0.72 flow-items-summary: summary: name=flow-items-summary — keyed by flowItemId, one key per message item value: data: type: automated-flow-views attributes: flow-items-summary: 6138d0ac2d79e00001210041: sent: 9100 recipients: 9100 clicked: 690 clickRate: 0.0758 converted: 88 sales: USD: 7402.5 spent: USD: 273 roi: 27.12 optOutRate: 0.0092 spamRate: 0.0001 revenuePerRecipient: 0.81 revenuePerMessage: 0.81 6138d0ac2d79e00001210042: sent: 3800 recipients: 3800 clicked: 210 clickRate: 0.0553 converted: 22 sales: USD: 1850 spent: USD: 114 roi: 16.23 optOutRate: 0.0008 spamRate: 0 revenuePerRecipient: 0.49 revenuePerMessage: 0.49 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /campaign-flows: get: summary: Retrieve list of campaigns tags: - Flow operationId: listCampaigns security: - ApiKeyAuth: [] description: | The site's campaigns — configuration only, no statistics. Default page size 100. parameters: - name: limit in: query description: Maximum number of campaigns to return schema: type: integer minimum: 1 maximum: 100 default: 100 - name: offset in: query description: Number of campaigns to skip, for pagination schema: type: integer minimum: 0 default: 0 - name: status in: query description: Filter by the dashboard's send status schema: type: array items: type: string enum: - draft - scheduled - processing - sending - sent - failed - cancelled - evaluating - noWinner - name: campaignType in: query description: Filter by campaign type schema: type: array items: type: string enum: - standard - adaptive - name: segmentId in: query description: Filter to campaigns whose audience includes or excludes this segment ID schema: type: string - name: scheduledFrom in: query description: Filter to campaigns scheduled at or after this time (inclusive) schema: type: string format: date-time - name: scheduledTo in: query description: Filter to campaigns scheduled at or before this time (inclusive) schema: type: string format: date-time responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Campaign' examples: sent-adaptive: summary: A sent adaptive campaign value: data: - type: campaigns attributes: id: 66aa11b7825e6ae655fe200 name: Labor Day Sale status: sent campaignType: adaptive scheduledFor: '2026-09-01T14:00:00.000Z' scheduleType: siteTimezone sentAt: '2026-09-01T14:03:00.000Z' deliveredSubscriberCount: 11840 includeSegments: - id: 655637c97825e6ae655fe300 name: VIP customers excludeSegments: [] isQuietHoursEnabled: true adaptiveTest: adaptiveTestStatus: complete_with_winner adaptiveTestResult: winnerFlowItemId: 655637c97825e6ae655fe411 wasTiebroken: false completedAt: '2026-09-01T18:03:00.000Z' testVariantsDispatchedAt: '2026-09-01T14:03:00.000Z' discountUsage: - id: 655637c97825e6ae655fe310 referenceCount: 2 discountCodePoolUsage: - id: 655637c97825e6ae655fe320 referenceCount: 1 createdAt: '2026-08-01T09:00:00.000Z' updatedAt: '2026-09-01T18:03:00.000Z' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/campaign-flows/{id}': get: summary: Receive a single campaign tags: - Flow operationId: getCampaign security: - ApiKeyAuth: [] description: | One campaign with its full message structure — the same item graph as the automated flow detail. The id of an automated flow returns 404 — use `/automated-flows/{id}` instead. parameters: - name: id in: path required: true description: ID of the campaign schema: type: string responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/CampaignDetail' examples: sent-adaptive: summary: Adaptive test with two SMS variants value: data: type: campaigns attributes: id: 66aa11b7825e6ae655fe200 name: Labor Day Sale status: sent campaignType: adaptive scheduledFor: '2026-09-01T14:00:00.000Z' scheduleType: siteTimezone sentAt: '2026-09-01T14:03:00.000Z' deliveredSubscriberCount: 11840 includeSegments: - id: 655637c97825e6ae655fe300 name: VIP customers excludeSegments: [] isQuietHoursEnabled: true adaptiveTest: adaptiveTestStatus: complete_with_winner adaptiveTestResult: winnerFlowItemId: 655637c97825e6ae655fe411 wasTiebroken: false completedAt: '2026-09-01T18:03:00.000Z' testVariantsDispatchedAt: '2026-09-01T14:03:00.000Z' discountUsage: - id: 655637c97825e6ae655fe310 referenceCount: 2 discountCodePoolUsage: - id: 655637c97825e6ae655fe320 referenceCount: 1 createdAt: '2026-08-01T09:00:00.000Z' updatedAt: '2026-09-01T18:03:00.000Z' entryFlowItemId: 655637c97825e6ae655fe410 items: - type: flow-item attributes: type: adaptive-test id: 655637c97825e6ae655fe410 adaptiveTest: variants: - flowItemId: 655637c97825e6ae655fe411 - flowItemId: 655637c97825e6ae655fe412 evaluation: metric: clickRate evaluateAfterHours: 4 audienceSplitPercentage: 20 - type: flow-item attributes: type: sms id: 655637c97825e6ae655fe411 name: Variant A messages: - text: 'Labor Day is here — 20% off everything.' imageUrl: null nextItemId: null - type: flow-item attributes: type: sms id: 655637c97825e6ae655fe412 name: Variant B messages: - text: 'Save big this Labor Day. Shop now.' imageUrl: null nextItemId: null 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/campaign-flows/{id}/views/{name}': get: summary: Statistics view of a campaign tags: - Flow operationId: getCampaignFlowView security: - ApiKeyAuth: [] description: | One statistics view of a campaign, addressed by campaign id — the same two views as `/automated-flows/{id}/views/{name}`. When the date range is omitted it covers the campaign's lifetime — a campaign's revenue keeps arriving for days after the send. The id of an automated flow returns 404 — use `/automated-flows/{id}/views/{name}` instead. `flow-summary` returns the campaign's totals for the range. `flow-items-summary` returns an object keyed by `flowItemId` — the same id as `items[]` on `/campaign-flows/{id}` — with one key per message item that recorded activity in the range; adaptive-test variants are message items, so each variant gets its own key. `adaptive-flow-summary` is for adaptive campaigns only (404 for a standard one): the campaign's id and name, its adaptive test state and result, and one entry per variant with the `evaluationStats` the winner was picked on next to the variant's lifetime totals. It ignores `dateFrom` and `dateTo`. parameters: - name: id in: path required: true description: ID of the campaign schema: type: string - name: name in: path required: true description: The view to return schema: type: string enum: - flow-summary - flow-items-summary - adaptive-flow-summary - name: dateFrom in: query description: | First day of the range, inclusive (YYYY-MM-DD, UTC). Defaults to the campaign's send day (`sentAt`, or `scheduledFor` / `createdAt` while it has not been sent), clamped to 18 months ago. A caller-supplied `dateFrom` must not be older than 18 months — the API does not serve older data, and an older `dateFrom` returns 400. schema: type: string format: date example: '2026-08-25' - name: dateTo in: query description: | Last day of the range, inclusive — `dateTo=2026-08-31` includes the whole of 2026-08-31 (UTC). Defaults to today. schema: type: string format: date example: '2026-08-31' responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: description: | Always one resource of type campaign-flow-views; attributes holds the requested view under its name. $ref: '#/components/schemas/CampaignFlowViews' examples: flow-summary: summary: name=flow-summary value: data: type: campaign-flow-views attributes: flow-summary: sent: 24700 recipients: 24700 clicked: 1310 clickRate: 0.053 converted: 189 sales: USD: 15020.5 spent: USD: 741 roi: 20.27 optOutRate: 0.0038 spamRate: 0.0001 revenuePerRecipient: 0.61 revenuePerMessage: 0.61 flow-items-summary: summary: name=flow-items-summary — keyed by flowItemId, one key per adaptive-test variant value: data: type: campaign-flow-views attributes: flow-items-summary: 655637c97825e6ae655fe411: sent: 14800 recipients: 14800 clicked: 850 clickRate: 0.0574 converted: 125 sales: USD: 10500.75 spent: USD: 444 roi: 23.65 optOutRate: 0.0035 spamRate: 0.0001 revenuePerRecipient: 0.71 revenuePerMessage: 0.71 655637c97825e6ae655fe412: sent: 9900 recipients: 9900 clicked: 460 clickRate: 0.0465 converted: 64 sales: USD: 4519.75 spent: USD: 297 roi: 15.22 optOutRate: 0.0042 spamRate: 0 revenuePerRecipient: 0.46 revenuePerMessage: 0.46 adaptive-flow-summary: summary: name=adaptive-flow-summary — the test as evaluated next to lifetime totals value: data: type: campaign-flow-views attributes: adaptive-flow-summary: id: 66aa11b7825e6ae655fe200 name: Labor Day Sale adaptiveTest: adaptiveTestStatus: complete_with_winner adaptiveTestResult: winnerFlowItemId: 655637c97825e6ae655fe411 wasTiebroken: false completedAt: '2026-09-01T18:03:00.000Z' testVariantsDispatchedAt: '2026-09-01T14:03:00.000Z' variants: - flowItemId: 655637c97825e6ae655fe411 evaluationStats: sent: 1184 clickRate: 0.0621 sales: USD: 1420.5 spent: USD: 35.52 roi: 39.99 optOutRate: 0.0034 allTimeStats: sent: 14800 recipients: 14800 clicked: 850 clickRate: 0.0574 converted: 125 sales: USD: 10500.75 spent: USD: 444 roi: 23.65 optOutRate: 0.0035 spamRate: 0.0001 revenuePerRecipient: 0.71 revenuePerMessage: 0.71 - flowItemId: 655637c97825e6ae655fe412 evaluationStats: sent: 1184 clickRate: 0.0447 sales: USD: 902 spent: USD: 35.52 roi: 25.39 optOutRate: 0.0042 allTimeStats: sent: 1184 recipients: 1184 clicked: 58 clickRate: 0.049 converted: 9 sales: USD: 1130.25 spent: USD: 35.52 roi: 31.82 optOutRate: 0.0042 spamRate: 0 revenuePerRecipient: 0.95 revenuePerMessage: 0.95 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /discounts: get: summary: Retrieve list of discounts tags: - Discount operationId: listDiscounts security: - ApiKeyAuth: [] description: | The site's discounts — configuration and pool state, no statistics. status is computed from the activation and expiration dates: active, scheduled (starts later), expired (ended or deactivated). Default page size 100. All filters combine with AND. parameters: - name: code in: query description: | The static code of a general discount, exact match, case-insensitive. Only general discounts have a code. schema: type: string minLength: 1 maxLength: 200 - name: name in: query description: Discount name contains this text, case-insensitive schema: type: string minLength: 1 maxLength: 200 - name: pattern in: query description: | The code prefix of a unique discount (discountCodePattern), exact match, case-insensitive. Only unique discounts have one. schema: type: string minLength: 1 maxLength: 200 - name: limit in: query description: Maximum number of discounts to return schema: type: integer minimum: 1 maximum: 100 default: 100 - name: offset in: query description: Number of discounts to skip, for pagination schema: type: integer minimum: 0 default: 0 - name: mode in: query description: Code pools only — refilling pools serve flows and popups, non-refilling pools serve campaigns schema: type: string enum: - refilling - non-refilling - name: available in: query description: | true = discounts a flow or campaign could pick — every general discount plus the unique discounts not yet assigned to a campaign; with flowId, also the ones that flow already uses. Status and dates are not checked. schema: type: boolean - name: flowId in: query description: Discounts configured in this flow schema: type: string responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Discount' examples: discounts: summary: A refilling code pool and an expiring discount value: data: - type: discounts attributes: id: 66aa0f1c7e8c9d2b00123abc name: Welcome 10% status: active customizationType: unique expiryType: fixed type: basic discountClasses: - order amount: 10 valueType: PERCENTAGE summary: 10% off entire order discountCodePattern: WELCOME- mode: refilling targetCount: 10000 availableCount: 8612 fillStatus: full startsAt: '2026-03-01T00:00:00.000Z' endsAt: null shopifyDiscountId: '1234567890123' createdAt: '2026-03-01T09:12:00.000Z' updatedAt: '2026-08-14T10:03:11.000Z' - type: discounts attributes: id: 66bb1a2d8f9e0c3d00456def name: Labor Day 20% status: active customizationType: unique expiryType: relative type: basic discountClasses: - order amount: 20 valueType: PERCENTAGE summary: 20% off entire order • Minimum purchase of $50.00 discountCodePattern: LD- durationSeconds: 86400 template: type: BASIC title: Labor Day 20% appliesOncePerCustomer: true usageLimit: 1 combinesWith: orderDiscounts: false productDiscounts: false shippingDiscounts: true customerSelection: type: ALL_CUSTOMERS allCustomers: true customerGets: appliesOnOneTimePurchase: true appliesOnSubscription: false value: type: PERCENTAGE percentage: 20 items: type: INPUT_ALL allItems: true minimumRequirement: type: MINIMUM_SUBTOTAL greaterThanOrEqualToSubtotal: amount: 50 currencyCode: USD shopifyDiscountId: '1234567890456' createdAt: '2026-08-20T10:00:00.000Z' updatedAt: '2026-08-30T16:00:04.000Z' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/discounts/{id}': get: summary: Retrieve a single discount tags: - Discount operationId: getDiscount security: - ApiKeyAuth: [] description: | One discount by id — the list entry's attributes plus usage (the flows, campaigns and popups configured with it, ids and names) and statistics (lifetime counters, no date range). Which statistics are present depends on the discount shape and on omitShopifyData — see DiscountStatistics. parameters: - name: id in: path required: true description: ID of the discount schema: type: string - name: omitShopifyData in: query description: | true (default): no live Shopify call — statistics has sent on code pools and expiring discounts and is empty on general discounts. false: Shopify is called and used, sales and codesCount are added on general discounts and code pools (never on expiring discounts). schema: type: boolean default: true responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/DiscountDetail' examples: refilling-pool: summary: 'GET /discounts/66aa0f1c7e8c9d2b00123abc?omitShopifyData=false' value: data: type: discounts attributes: id: 66aa0f1c7e8c9d2b00123abc name: Welcome 10% status: active customizationType: unique expiryType: fixed type: basic discountClasses: - order amount: 10 valueType: PERCENTAGE summary: 10% off entire order discountCodePattern: WELCOME- mode: refilling targetCount: 10000 availableCount: 8612 fillStatus: full startsAt: '2026-03-01T00:00:00.000Z' endsAt: null shopifyDiscountId: '1234567890123' usage: flows: - id: 6138d0ac2d79e00001210035 name: Welcome flow campaigns: [] optinTools: - id: 64f2a1b2c3d4e5f60718293a name: Mobile - Welcome popup createdAt: '2026-03-01T09:12:00.000Z' updatedAt: '2026-08-14T10:03:11.000Z' statistics: sent: 1388 used: 212 sales: USD: 9418.4 codesCount: 10000 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /segments: get: summary: Retrieve list of segments tags: - Segment operationId: listSegments security: - ApiKeyAuth: [] description: | The site's active segments — name, status, the expression and its description; size with includeSize=true. Page size 5, newest first. Lists: GET /lists. parameters: - name: limit in: query description: Maximum number of segments to return schema: type: integer minimum: 1 maximum: 5 default: 5 - name: offset in: query description: Number of segments to skip, for pagination schema: type: integer minimum: 0 default: 0 - name: ids in: query description: Only these segments schema: type: array items: type: string - name: isMemberOf in: query description: Segments whose expression has a member-of-a-segment condition on this segment or list id schema: type: string - name: includeSize in: query description: Compute the live size of each segment on the page schema: type: boolean default: false responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Segment' examples: segments: summary: An active and a dormant segment value: data: - type: segments attributes: id: 64f2a1b2c3d4e5f60718293a name: Win-back — no order in 90 days status: active editedAt: '2026-06-02T09:14:00.000Z' createdAt: '2025-11-18T14:02:10.000Z' updatedAt: '2026-09-23T22:00:04.000Z' expression: and: - or: - slug: number-of-orders type: number operator: gt value: 0 - or: - slug: placed-an-order type: boolean operator: neq value: true dateFilter: type: in-the-last daysOffset: 90 - or: - slug: member-of-a-segment type: boolean operator: neq values: - id: 64f2a1b2c3d4e5f60718293b name: VIP customers - slug: received-a-flow type: boolean operator: neq dateFilter: type: in-the-last daysOffset: 30 subcondition: slug: sequence category: sequence-id operator: eq values: - id: 6138d0ac2d79e00001210035 name: Win-back flow description: Number of orders is greater than 0 and Has not placed an order in the last 90 days and Is not member of VIP customers or Has not received a flow in the last 30 days flow name is Win-back flow - type: segments attributes: id: 64f2a1b2c3d4e5f60718293c name: Summer 2025 quiz takers status: dormant dormantAt: '2026-03-01T03:00:00.000Z' editedAt: '2025-06-10T08:00:00.000Z' createdAt: '2025-06-10T08:00:00.000Z' updatedAt: '2026-03-01T03:00:00.000Z' expression: and: - or: - slug: subscribed-to-channel type: boolean operator: eq value: sms subcondition: slug: subscription-source category: optin-tool-id operator: eq values: - id: 655637c97825e6ae655fe1c9 name: Summer quiz description: Has subscribed to sms source is Summer quiz 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/segments/{id}': get: summary: Retrieve a single segment tags: - Segment operationId: getSegment security: - ApiKeyAuth: [] description: | One segment by id — the same resource as a list entry, with its live size. Which campaigns target it: GET /campaign-flows?segmentId=. parameters: - name: id in: path required: true description: ID of the segment schema: type: string responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/Segment' examples: segment: summary: 'GET /segments/64f2a1b2c3d4e5f60718293a' value: data: type: segments attributes: id: 64f2a1b2c3d4e5f60718293a name: Win-back — no order in 90 days status: active size: 8312 editedAt: '2026-06-02T09:14:00.000Z' createdAt: '2025-11-18T14:02:10.000Z' updatedAt: '2026-09-23T22:00:04.000Z' expression: and: - or: - slug: number-of-orders type: number operator: gt value: 0 - or: - slug: placed-an-order type: boolean operator: neq value: true dateFilter: type: in-the-last daysOffset: 90 - or: - slug: member-of-a-segment type: boolean operator: neq values: - id: 64f2a1b2c3d4e5f60718293b name: VIP customers - slug: received-a-flow type: boolean operator: neq dateFilter: type: in-the-last daysOffset: 30 subcondition: slug: sequence category: sequence-id operator: eq values: - id: 6138d0ac2d79e00001210035 name: Win-back flow description: Number of orders is greater than 0 and Has not placed an order in the last 90 days and Is not member of VIP customers or Has not received a flow in the last 30 days flow name is Win-back flow 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /lists: get: summary: Retrieve list of lists tags: - List operationId: listLists security: - ApiKeyAuth: [] description: | The site's active manual lists — name and status; size with includeSize=true. Page size 5, newest first. parameters: - name: limit in: query description: Maximum number of lists to return schema: type: integer minimum: 1 maximum: 5 default: 5 - name: offset in: query description: Number of lists to skip, for pagination schema: type: integer minimum: 0 default: 0 - name: ids in: query description: Only these lists schema: type: array items: type: string - name: includeSize in: query description: Compute the live size of each list on the page schema: type: boolean default: false responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/List' examples: lists: summary: An imported list value: data: - type: lists attributes: id: 64f2a1b2c3d4e5f60718293d name: Black Friday 2025 import status: active editedAt: '2025-11-20T10:00:00.000Z' createdAt: '2025-11-20T10:00:00.000Z' updatedAt: '2026-09-23T22:00:04.000Z' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/lists/{id}': get: summary: Retrieve a single list tags: - List operationId: getList security: - ApiKeyAuth: [] description: | One manual list by id — the same resource as a list entry, with its live size. parameters: - name: id in: path required: true description: ID of the list schema: type: string responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/List' examples: list: summary: 'GET /lists/64f2a1b2c3d4e5f60718293d' value: data: type: lists attributes: id: 64f2a1b2c3d4e5f60718293d name: Black Friday 2025 import status: active size: 1204 editedAt: '2025-11-20T10:00:00.000Z' createdAt: '2025-11-20T10:00:00.000Z' updatedAt: '2026-09-23T22:00:04.000Z' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /optin-tools: get: summary: Retrieve list of opt-in tools tags: - OptinTool operationId: listOptinTools security: - ApiKeyAuth: [] description: | List the site's opt-in tools (popups, landing pages, embedded forms, keywords). responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/OptinTool' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/optin-tools/{id}': get: summary: Receive a single opt-in tool tags: - OptinTool operationId: getOptinTool security: - ApiKeyAuth: [] description: | Get opt-in tool by ID parameters: - name: id in: path required: true description: ID of the opt-in tool schema: type: string responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/OptinTool' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/optin-tools/{id}/views/{name}': get: summary: Statistics view of an opt-in tool tags: - OptinTool operationId: getOptinToolView security: - ApiKeyAuth: [] description: | One statistics view of a popup, landing-page or embedded-form opt-in tool. `name` picks the view; `all` returns every section in one response. When the date range is omitted it defaults to the last 7 days. Popups support every view. Landing pages and embedded forms support `optin-summary`, `optin-history` and `subscriptions-history` only — the revenue views and `all` return 400 for them. Keywords support `subscriptions-history` only. A landing page or embedded form has no teaser step and records no bounce, so its `teaserConfirm`, `teaserConfirmRate`, `teaserDecline`, `bounce` and `bounceRate` are always 0. Statistics fields are never null: buckets without activity and empty ranges return 0 counts and 0 rates — zero and "no data" are deliberately not distinguished, matching the dashboard. The only fields that can be absent are the channel-gated email/SMS ones, which are omitted when the tool does not collect that channel. parameters: - name: id in: path required: true description: ID of the opt-in tool schema: type: string - name: name in: path required: true description: The view to return schema: type: string enum: - optin-summary - optin-history - revenue-summary - revenue-history - revenue-by-optin-segments - revenue-by-countries - subscriptions-history - all - name: dateFrom in: query description: | First day of the range, inclusive (YYYY-MM-DD, UTC). Defaults to 7 days before `dateTo`. schema: type: string format: date example: '2026-08-04' - name: dateTo in: query description: | Last day of the range, inclusive — `dateTo=2026-08-10` includes the whole of 2026-08-10 (UTC). Defaults to today. schema: type: string format: date example: '2026-08-10' - name: targetResolution in: query description: Bucket size of the time series — history views and `all` only. Buckets are UTC; weeks start on Monday. schema: type: string enum: - day - week - month - year default: day responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: description: | Always one resource of type optin-tool-views. attributes holds the requested view's data under its name — one key for a single view, all seven for name=all. $ref: '#/components/schemas/OptinToolViews' examples: optin-summary: summary: name=optin-summary value: data: type: optin-tool-views attributes: optin-summary: impression: 41200 teaserConfirm: 890 teaserConfirmRate: 0.0216 teaserDecline: 2140 emailOptin: 610 emailOptinRate: 0.0148 phoneNumberSubmitted: 530 phoneNumberSubmittedRate: 0.0129 smsOptin: 480 smsOptinRate: 0.0117 optin-history: summary: name=optin-history — one bucket per targetResolution unit value: data: type: optin-tool-views attributes: optin-history: - timestamp: '2026-07-27' impression: 5480 emailOptin: 84 emailOptinRate: 0.0153 smsOptin: 66 smsOptinRate: 0.012 - timestamp: '2026-07-28' impression: 0 emailOptin: 0 emailOptinRate: 0 smsOptin: 0 smsOptinRate: 0 revenue-summary: summary: name=revenue-summary value: data: type: optin-tool-views attributes: revenue-summary: associatedRevenue: 12403.5 orders: 96 averageOrderValue: 129.2 revenuePerVisitor: 0.3 orderConversionRate: 0.0023 revenue-history: summary: name=revenue-history — one bucket per targetResolution unit value: data: type: optin-tool-views attributes: revenue-history: - timestamp: '2026-07-27' associatedRevenue: 1710 orders: 13 averageOrderValue: 131.54 revenuePerVisitor: 0.31 orderConversionRate: 0.0024 revenue-by-optin-segments: summary: name=revenue-by-optin-segments value: data: type: optin-tool-views attributes: revenue-by-optin-segments: - optinSegmentType: smsOptin optinSegmentCount: 480 associatedRevenue: 5100 orders: 41 averageOrderValue: 124.39 revenuePerVisitor: 10.63 orderConversionRate: 0.0854 - optinSegmentType: total optinSegmentCount: 41200 associatedRevenue: 12403.5 orders: 96 averageOrderValue: 129.2 revenuePerVisitor: 0.3 orderConversionRate: 0.0023 revenue-by-countries: summary: name=revenue-by-countries value: data: type: optin-tool-views attributes: revenue-by-countries: - countryCode: US impressionCount: 31200 associatedRevenue: 10900 orders: 82 averageOrderValue: 132.93 revenuePerVisitor: 0.35 orderConversionRate: 0.0026 - countryCode: UNKNOWN_COUNTRY impressionCount: 1210 associatedRevenue: 1503.5 orders: 14 averageOrderValue: 107.39 revenuePerVisitor: 1.24 orderConversionRate: 0.0116 subscriptions-history: summary: name=subscriptions-history — one bucket per targetResolution unit value: data: type: optin-tool-views attributes: subscriptions-history: - timestamp: '2026-07-27' subscriptions: 118 - timestamp: '2026-07-28' subscriptions: 0 all: summary: name=all — every view under its own key value: data: type: optin-tool-views attributes: optin-summary: impression: 41200 teaserConfirm: 890 teaserConfirmRate: 0.0216 teaserDecline: 2140 emailOptin: 610 emailOptinRate: 0.0148 phoneNumberSubmitted: 530 phoneNumberSubmittedRate: 0.0129 smsOptin: 480 smsOptinRate: 0.0117 optin-history: - timestamp: '2026-07-27' impression: 5480 emailOptin: 84 emailOptinRate: 0.0153 smsOptin: 66 smsOptinRate: 0.012 revenue-summary: associatedRevenue: 12403.5 orders: 96 averageOrderValue: 129.2 revenuePerVisitor: 0.3 orderConversionRate: 0.0023 revenue-history: - timestamp: '2026-07-27' associatedRevenue: 1710 orders: 13 averageOrderValue: 131.54 revenuePerVisitor: 0.31 orderConversionRate: 0.0024 revenue-by-optin-segments: - optinSegmentType: smsOptin optinSegmentCount: 480 associatedRevenue: 5100 orders: 41 averageOrderValue: 124.39 revenuePerVisitor: 10.63 orderConversionRate: 0.0854 revenue-by-countries: - countryCode: US impressionCount: 31200 associatedRevenue: 10900 orders: 82 averageOrderValue: 132.93 revenuePerVisitor: 0.35 orderConversionRate: 0.0026 subscriptions-history: - timestamp: '2026-07-27' subscriptions: 118 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/optin-tools/views/{name}': get: summary: Statistics view of all opt-in tools of the site tags: - OptinTool operationId: getOptinToolListView security: - ApiKeyAuth: [] description: | The account-level opt-in tool statistics view — every opt-in tool of the site in a single response, the collection counterpart of `/optin-tools/{id}/views/{name}`. `name` picks the view. When the date range is omitted it defaults to the last 7 days. `optin-tools-summary` returns one entry per opt-in tool that recorded any metric event or collected any SMS subscription in the range: the tool's `optinToolName`, `optinToolType` and, for popups, `optinToolTags`, then its raw metric-event unique-session counts merged with its new SMS subscription count. Event keys are sparse — a missing key means 0; `smsSubscriptions` is always present, 0 when none. Because every entry names, types and tags its own tool, a per-type or per-tag total can be computed from this response alone, without a separate `/optin-tools` call. The tags are the tool's current ones: as in the dashboard, the range's statistics are reported per tool under its current configuration. Values are counts, not amounts: this view carries no USD figures; for attributed revenue use the per-tool revenue views. Subscriptions from non-tool sources (imports, customer chat, …) are not part of this view. parameters: - name: name in: path required: true description: The view to return schema: type: string enum: - optin-tools-summary - name: dateFrom in: query description: | First day of the range, inclusive (YYYY-MM-DD, UTC). Defaults to 7 days before `dateTo`. Must not be older than 18 months — the API does not serve older data, and an older `dateFrom` returns 400. schema: type: string format: date example: '2026-08-18' - name: dateTo in: query description: | Last day of the range, inclusive — `dateTo=2026-08-24` includes the whole of 2026-08-24 (UTC). Defaults to today. schema: type: string format: date example: '2026-08-24' responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: description: | Always one resource of type optin-tool-list-views. attributes holds the requested view under its name, keyed by source (opt-in tool ID or slug) inside. $ref: '#/components/schemas/OptinToolListViews' examples: optin-tools-summary: summary: name=optin-tools-summary — sparse event counts; a missing event means 0 value: data: type: optin-tool-list-views attributes: optin-tools-summary: - optinToolId: 655637c97825e6ae655fe1c9 optinToolName: Summer sale — Main optinToolType: popup optinToolTags: - delay - discount-694132dcb842e9d365676043 - micro-yes - one-click-opt-in - opt-in-offer impression: 20400 teaserConfirmation: 512 closePopup: 3100 emailClick: 512 smsOptin: 276 smsSubscriptions: 150 - optinToolId: 655637c97825e6ae655fe1b5 optinToolName: Summer sale — Preferences optinToolType: popup optinToolTags: - button-group - discount-694132dcb842e9d365676043 - exit-intent - in-popup-confirmation - opt-in-offer impression: 18100 teaserConfirmation: 445 engagement: 5210 smsOptin: 190 smsSubscriptions: 120 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /optin-tool-experiments: get: summary: Retrieve list of A/B test experiments tags: - OptinTool operationId: listOptinToolExperiments security: - ApiKeyAuth: [] description: | List the site's opt-in tool A/B test experiments in every status — draft, scheduled, running, ended and cancelled. responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/OptinToolExperiment' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/optin-tool-experiments/{id}': get: summary: Receive a single A/B test experiment tags: - OptinTool operationId: getOptinToolExperiment security: - ApiKeyAuth: [] description: | Get A/B test experiment by ID. An experiment belonging to another site is not visible and returns 404. parameters: - name: id in: path required: true description: ID of the experiment schema: type: string responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/OptinToolExperiment' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/optin-tool-experiments/{id}/views/{name}': get: summary: Statistics view of an A/B test experiment tags: - OptinTool operationId: getOptinToolExperimentView security: - ApiKeyAuth: [] description: | One statistics view of an A/B test experiment — the same numbers as the dashboard's experiment results. `name` picks the section; `all` returns every section in one response. A single request always returns every variant of the experiment: each section is an object keyed by the variant's opt-in tool ID, so the caller never passes `optinToolIds` — the participants are read from the experiment itself. There are no date parameters and no `targetResolution` — every section is a total for the experiment's own window, which is derived from its status: an `ended` experiment uses its full window, a `running` one spans its start until now, and a `draft`, `scheduled` or `cancelled` one has no statistics and returns 400. Statistics fields behave as in the opt-in tool views: counts and rates are never null, so a variant without activity returns 0 rather than being omitted, and rates are 0 when the denominator is 0. The exceptions are the channel-gated email/SMS fields, absent when the tool does not collect that channel, and `metric-event-summary`, whose per-variant map is sparse — only events that occurred appear, and a missing key means 0. parameters: - name: id in: path required: true description: ID of the experiment schema: type: string - name: name in: path required: true description: The view to return schema: type: string enum: - optin-summary - revenue-summary - revenue-by-optin-segments - metric-event-summary - all responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: description: | Always one resource of type optin-tool-experiments-views. attributes holds the requested section under its name, keyed by variant optinToolId — one section key for a single view, all four for name=all. $ref: '#/components/schemas/OptinToolExperimentViews' examples: optin-summary: summary: name=optin-summary — both variants keyed by opt-in tool ID value: data: type: optin-tool-experiments-views attributes: optin-summary: 655637c97825e6ae655fe1c9: impression: 20400 teaserConfirm: 512 teaserConfirmRate: 0.0251 teaserDecline: 1230 emailOptin: 0 emailOptinRate: 0 phoneNumberSubmitted: 310 phoneNumberSubmittedRate: 0.0152 smsOptin: 276 smsOptinRate: 0.0135 subscriptions: 268 655637c97825e6ae655fe1b5: impression: 20600 teaserConfirm: 445 teaserConfirmRate: 0.0216 teaserDecline: 1180 emailOptin: 0 emailOptinRate: 0 phoneNumberSubmitted: 271 phoneNumberSubmittedRate: 0.0132 smsOptin: 240 smsOptinRate: 0.0117 subscriptions: 233 revenue-summary: summary: name=revenue-summary value: data: type: optin-tool-experiments-views attributes: revenue-summary: 655637c97825e6ae655fe1c9: associatedRevenue: 2410.5 orders: 31 averageOrderValue: 77.76 revenuePerVisitor: 0.12 orderConversionRate: 0.0015 655637c97825e6ae655fe1b5: associatedRevenue: 1988.2 orders: 24 averageOrderValue: 82.84 revenuePerVisitor: 0.1 orderConversionRate: 0.0012 revenue-by-optin-segments: summary: name=revenue-by-optin-segments — one array per variant value: data: type: optin-tool-experiments-views attributes: revenue-by-optin-segments: 655637c97825e6ae655fe1c9: - optinSegmentType: noOptin optinSegmentCount: 20124 associatedRevenue: 430.1 orders: 6 averageOrderValue: 71.68 revenuePerVisitor: 0.02 orderConversionRate: 0.0003 - optinSegmentType: smsOptin optinSegmentCount: 276 associatedRevenue: 1980.4 orders: 25 averageOrderValue: 79.22 revenuePerVisitor: 7.18 orderConversionRate: 0.0906 - optinSegmentType: total optinSegmentCount: 20400 associatedRevenue: 2410.5 orders: 31 averageOrderValue: 77.76 revenuePerVisitor: 0.12 orderConversionRate: 0.0015 655637c97825e6ae655fe1b5: - optinSegmentType: noOptin optinSegmentCount: 20360 associatedRevenue: 358.2 orders: 5 averageOrderValue: 71.64 revenuePerVisitor: 0.02 orderConversionRate: 0.0002 - optinSegmentType: smsOptin optinSegmentCount: 240 associatedRevenue: 1630 orders: 19 averageOrderValue: 85.79 revenuePerVisitor: 6.79 orderConversionRate: 0.0792 - optinSegmentType: total optinSegmentCount: 20600 associatedRevenue: 1988.2 orders: 24 averageOrderValue: 82.84 revenuePerVisitor: 0.1 orderConversionRate: 0.0012 metric-event-summary: summary: name=metric-event-summary — sparse per-variant maps; a missing event means 0 value: data: type: optin-tool-experiments-views attributes: metric-event-summary: 655637c97825e6ae655fe1c9: impression: count: 20400 orderValueUSD: 0 teaserConfirmation: count: 512 orderValueUSD: 0 teaserDecline: count: 1230 orderValueUSD: 0 closePopup: count: 3100 orderValueUSD: 0 smsOptin: count: 276 orderValueUSD: 0 smsOptinRevenue: count: 31 orderValueUSD: 2410.5 655637c97825e6ae655fe1b5: impression: count: 20600 orderValueUSD: 0 teaserConfirmation: count: 445 orderValueUSD: 0 teaserDecline: count: 1180 orderValueUSD: 0 engagement: count: 5210 orderValueUSD: 0 smsOptin: count: 240 orderValueUSD: 0 smsOptinRevenue: count: 24 orderValueUSD: 1988.2 all: summary: name=all — every section under its own key value: data: type: optin-tool-experiments-views attributes: optin-summary: 655637c97825e6ae655fe1c9: impression: 20400 teaserConfirm: 512 teaserConfirmRate: 0.0251 teaserDecline: 1230 emailOptin: 0 emailOptinRate: 0 phoneNumberSubmitted: 310 phoneNumberSubmittedRate: 0.0152 smsOptin: 276 smsOptinRate: 0.0135 subscriptions: 268 655637c97825e6ae655fe1b5: impression: 20600 teaserConfirm: 445 teaserConfirmRate: 0.0216 teaserDecline: 1180 emailOptin: 0 emailOptinRate: 0 phoneNumberSubmitted: 271 phoneNumberSubmittedRate: 0.0132 smsOptin: 240 smsOptinRate: 0.0117 subscriptions: 233 revenue-summary: 655637c97825e6ae655fe1c9: associatedRevenue: 2410.5 orders: 31 averageOrderValue: 77.76 revenuePerVisitor: 0.12 orderConversionRate: 0.0015 655637c97825e6ae655fe1b5: associatedRevenue: 1988.2 orders: 24 averageOrderValue: 82.84 revenuePerVisitor: 0.1 orderConversionRate: 0.0012 revenue-by-optin-segments: 655637c97825e6ae655fe1c9: - optinSegmentType: noOptin optinSegmentCount: 20124 associatedRevenue: 430.1 orders: 6 averageOrderValue: 71.68 revenuePerVisitor: 0.02 orderConversionRate: 0.0003 - optinSegmentType: smsOptin optinSegmentCount: 276 associatedRevenue: 1980.4 orders: 25 averageOrderValue: 79.22 revenuePerVisitor: 7.18 orderConversionRate: 0.0906 - optinSegmentType: total optinSegmentCount: 20400 associatedRevenue: 2410.5 orders: 31 averageOrderValue: 77.76 revenuePerVisitor: 0.12 orderConversionRate: 0.0015 655637c97825e6ae655fe1b5: - optinSegmentType: noOptin optinSegmentCount: 20360 associatedRevenue: 358.2 orders: 5 averageOrderValue: 71.64 revenuePerVisitor: 0.02 orderConversionRate: 0.0002 - optinSegmentType: smsOptin optinSegmentCount: 240 associatedRevenue: 1630 orders: 19 averageOrderValue: 85.79 revenuePerVisitor: 6.79 orderConversionRate: 0.0792 - optinSegmentType: total optinSegmentCount: 20600 associatedRevenue: 1988.2 orders: 24 averageOrderValue: 82.84 revenuePerVisitor: 0.1 orderConversionRate: 0.0012 metric-event-summary: 655637c97825e6ae655fe1c9: impression: count: 20400 orderValueUSD: 0 teaserConfirmation: count: 512 orderValueUSD: 0 teaserDecline: count: 1230 orderValueUSD: 0 closePopup: count: 3100 orderValueUSD: 0 smsOptin: count: 276 orderValueUSD: 0 smsOptinRevenue: count: 31 orderValueUSD: 2410.5 655637c97825e6ae655fe1b5: impression: count: 20600 orderValueUSD: 0 teaserConfirmation: count: 445 orderValueUSD: 0 teaserDecline: count: 1180 orderValueUSD: 0 engagement: count: 5210 orderValueUSD: 0 smsOptin: count: 240 orderValueUSD: 0 smsOptinRevenue: count: 24 orderValueUSD: 1988.2 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/carts/{id}': put: summary: Update cart tags: - Cart operationId: updateCart security: - ApiKeyAuth: [] description: | Update the cart's content. Endpoint overwrites the cart's content with the new one. parameters: - name: id in: path required: true description: ID of the cart (session) schema: type: string requestBody: required: true content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/UpdateCart' responses: '204': description: No content 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' delete: summary: Clear cart tags: - Cart operationId: clearCart security: - ApiKeyAuth: [] description: | Clear the cart's content. parameters: - name: id in: path required: true description: ID of the cart (session) schema: type: string responses: '204': description: No content 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /abandonments: post: summary: Abandon a session tags: - Abandonment operationId: postAbandonment security: - ApiKeyAuth: [] description: | Trigger an abandonment event in Recart. It sends the associated abandonment flow to the recipient. Flow must be active to send the message. requestBody: required: true content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/AbandonCart' responses: '200': description: OK 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /orders: post: summary: Create an order tags: - Order operationId: postOrder security: - ApiKeyAuth: [] description: | Create an order in Recart. It sends the associated receipt flow to the recipient. Flow must be active to send the message. requestBody: required: true content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/CreateOrder' responses: '202': description: Created 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/orders/{id}': put: summary: Update an order tags: - Order operationId: updateOrder security: - ApiKeyAuth: [] description: | Update an order in Recart. parameters: - name: id in: path required: true description: Id of the order schema: type: number example: 1234567890 requestBody: required: true content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/UpdateOrder' responses: '202': description: No content 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /fulfillments: post: summary: Fulfill an order tags: - Order operationId: fulfillOrder security: - ApiKeyAuth: [] description: | Fulfill an order. requestBody: required: true content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/FulfillOrder' responses: '202': description: No content 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /subscribers: get: summary: Find subscribers by phone number tags: - Subscriber operationId: findSubscribers security: - ApiKeyAuth: [] description: | The subscribers whose SMS number equals `phoneNumber` — normally one entry, an empty list when none. The number is a lookup key only and is never returned; the resources are the same as GET /subscribers/{id}. Phone number, email and names are never part of the response. parameters: - name: phoneNumber in: query required: true description: Phone number of the subscriber in E.164 format, with the leading plus schema: type: string pattern: '^\+[1-9]\d{6,14}$' example: '+15550000000' - name: channel in: query description: | Channels to return; each selected channel is a key of the resource. Defaults to sms, the only channel served today. schema: type: array items: type: string enum: - sms default: - sms responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Subscriber' examples: one-match: summary: One subscriber behind the number value: data: - type: subscribers attributes: id: 66aa0f1c7e8c9d2b00123abc timezone: America/Chicago segments: [] createdAt: '2026-03-04T18:22:10.000Z' updatedAt: '2026-03-04T18:22:10.000Z' sms: status: subscribed subscribedAt: '2026-03-04T18:22:10.000Z' lastInteractionAt: '2026-03-04T18:22:10.000Z' subscriptionSource: type: import id: 66b1c2d3e4f5a6b7c8d9e0f1 name: vip-customers-2026-03.csv country: US optinHistory: - type: optin createdAt: '2026-03-04T18:22:10.000Z' source: type: import id: 66b1c2d3e4f5a6b7c8d9e0f1 name: vip-customers-2026-03.csv no-match: summary: No subscriber has this number value: data: [] 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' patch: summary: Update subscriber's custom attributes tags: - Subscriber operationId: patchSubscriber security: - ApiKeyAuth: [] description: | Update the custom attributes of an SMS subscriber identified by phone number. Only the custom attributes included in the request are modified; attributes that are not provided remain unchanged. parameters: - name: phoneNumber in: query required: true description: Phone number of the subscriber schema: type: string requestBody: required: true content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/PatchSubscriber' responses: '204': description: No content 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/subscribers/{id}': get: summary: Retrieve a single subscriber tags: - Subscriber operationId: getSubscriber security: - ApiKeyAuth: [] description: | One subscriber by internal id — timezone, current segments and, per selected channel, status, dates, acquiring source, country and the opt-in / opt-out history. Phone number, email and names are never returned. To find the id behind a phone number use GET /subscribers?phoneNumber=. parameters: - name: id in: path required: true description: Internal ID of the subscriber schema: type: string - name: channel in: query description: | Channels to return; each selected channel is a key of the resource. Defaults to sms, the only channel served today. schema: type: array items: type: string enum: - sms default: - sms responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/Subscriber' examples: subscriber: summary: A subscriber who opted out with a keyword value: data: type: subscribers attributes: id: 66aa0f1c7e8c9d2b00123abc timezone: America/Chicago segments: - id: 64f2a1b2c3d4e5f60718293a name: VIP customers type: segment - id: 64f2a1b2c3d4e5f60718293b name: Black Friday 2025 buyers type: list createdAt: '2026-03-04T18:22:10.000Z' updatedAt: '2026-08-30T16:03:41.000Z' sms: status: unsubscribed subscribedAt: '2026-03-04T18:22:10.000Z' lastInteractionAt: '2026-08-30T16:03:41.000Z' subscriptionSource: type: popup id: 655637c97825e6ae655fe1c9 name: Mobile - Preferences - Custom Images country: US optinHistory: - type: optin createdAt: '2026-03-04T18:22:10.000Z' source: type: popup id: 655637c97825e6ae655fe1c9 name: Mobile - Preferences - Custom Images sourceUrl: 'https://trueclassic.com/collections/tees?utm_source=meta' - type: optout createdAt: '2026-08-30T16:03:41.000Z' source: type: keyword 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/subscribers/views/{name}': get: summary: Statistics view of the site's subscribers tags: - Subscriber operationId: getSubscribersView security: - ApiKeyAuth: [] description: | One statistics view over the site's subscribers. `name` picks the view. When the date range is omitted it defaults to the last 7 days. `list-summary` returns the list statistics for the range: list size at the end of the range, new subscriptions (gross — re-subscribes included), subscriber-initiated unsubscriptions by how the opt-out arrived (keyword, ai, optOutLink, dashboard, publicApi, integration) and automated cleaning by reason (deactivatedNumber, knownLitigator, landline, reassigned). Net growth is not a field — compute subscriptions − unsubscriptions − cleaning. `list-history` returns the same statistics per UTC calendar day of the range, one entry per day, without bucketing. `countries-summary` returns the currently subscribed numbers by country (the phone number's carrier country), sorted descending. It is a snapshot: it takes no date range, and a date range returns 400. `subscription-sources` returns the new SMS subscriptions collected in the range, one entry per source — where the subscribers came from: opt-in tools by type (popup, landing-page, embedded-form, keyword), and non-tool sources (import, custom-integration, public-api, shopify_checkout, …). Every subscription counts toward exactly one source; a source without SMS subscriptions in the range is absent. Entries are sorted descending by smsSubscriptions. For the per-tool split use /optin-tools/views/optin-tools-summary. The data of list-summary, list-history and countries-summary is grouped by channel: `channel` selects the channels and defaults to sms. The legacy facebook channel is not served. parameters: - name: name in: path required: true description: The view to return schema: type: string enum: - subscription-sources - list-summary - list-history - countries-summary - name: dateFrom in: query description: | First day of the range, inclusive (YYYY-MM-DD, UTC). Defaults to 7 days before `dateTo`. Must not be older than 18 months — the API does not serve older data, and an older `dateFrom` returns 400. schema: type: string format: date example: '2026-08-18' - name: dateTo in: query description: | Last day of the range, inclusive — `dateTo=2026-08-24` includes the whole of 2026-08-24 (UTC). Defaults to today. schema: type: string format: date example: '2026-08-24' - name: channel in: query description: | Channels to return — list-summary, list-history and countries-summary only. Each selected channel appears as a key in the view's data. Defaults to sms; the legacy facebook channel is not served. schema: type: array items: type: string enum: - sms default: - sms responses: '200': description: Ok content: application/vnd.api+json: schema: type: object properties: data: description: | Always one resource of type subscribers-views; attributes holds the requested view under its name. $ref: '#/components/schemas/SubscribersViews' examples: subscription-sources: summary: name=subscription-sources — one entry per source value: data: type: subscribers-views attributes: subscription-sources: - source: import smsSubscriptions: 1200 - source: popup smsSubscriptions: 419 - source: shopify_checkout smsSubscriptions: 86 - source: public-api smsSubscriptions: 12 list-summary: summary: name=list-summary — the range total, grouped by channel value: data: type: subscribers-views attributes: list-summary: sms: subscribers: 48210 subscriptions: 1412 unsubscriptions: keyword: 171 ai: 22 optOutLink: 39 dashboard: 3 publicApi: 1 integration: 0 cleaning: deactivatedNumber: 44 knownLitigator: 2 landline: 9 reassigned: 6 list-history: summary: name=list-history — one entry per UTC calendar day value: data: type: subscribers-views attributes: list-history: - date: '2026-09-12' sms: subscribers: 48042 subscriptions: 201 unsubscriptions: keyword: 24 ai: 3 optOutLink: 6 dashboard: 0 publicApi: 0 integration: 0 cleaning: deactivatedNumber: 7 knownLitigator: 0 landline: 1 reassigned: 1 - date: '2026-09-13' sms: subscribers: 48210 subscriptions: 212 unsubscriptions: keyword: 26 ai: 4 optOutLink: 5 dashboard: 1 publicApi: 0 integration: 0 cleaning: deactivatedNumber: 6 knownLitigator: 0 landline: 1 reassigned: 1 countries-summary: summary: name=countries-summary — subscribed numbers by country value: data: type: subscribers-views attributes: countries-summary: sms: - countryCode: US subscribers: 41200 - countryCode: CA subscribers: 5130 - countryCode: GB subscribers: 1880 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /subscriptions: post: summary: Initiate SMS subscription tags: - Subscription operationId: postSubscription security: - ApiKeyAuth: [] description: | Trigger an SMS subscription flow in Recart. It sends the associated welcome flow to the recipient. Flow must be active to comply TCPA regulations. requestBody: required: true content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/PostSubscription' responses: '202': description: Accepted 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' delete: summary: Unsubscribe SMS subscriber tags: - Subscription operationId: deleteSubscription security: - ApiKeyAuth: [] description: | Unsubscribe an SMS subscriber if it's not unsubscribed yet. parameters: - name: phoneNumber in: query required: true description: Phone number of the subscriber schema: type: string responses: '204': description: No content 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /event-sources: post: summary: Create new event source tags: - Event operationId: createEventSource security: - ApiKeyAuth: [] description: | Create a new source to start sending events requestBody: required: true content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/PostEventSource' responses: '201': description: Created 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /events: post: summary: Post an event tags: - Event operationId: postEvent security: - ApiKeyAuth: [] description: | Post an event which can be used to trigger flows in Recart. Three preconditions must hold, each of which fails with its own status code: - the event source (`source.category` and `source.name`) is registered for the site via `POST /event-sources`, - `phoneNumber` belongs to an existing subscriber — this endpoint never creates one, - that subscriber has an active SMS subscription. A newly registered event source does not become usable instantly. Allow a short delay after creating one before posting the first event against it, and expect the first events to be able to fail with `417` until it has propagated. Whether a flow is actually listening for the event is *not* checked. If no active Integration flow uses the event source as its trigger, the event is still accepted and simply results in no message — so confirm the flow is active in the Recart dashboard when events succeed but nothing is sent. The event is queued for processing, so `200` confirms that it was accepted, not that a message was sent. The `200` response body is the plain-text string `OK`, not a JSON:API document — do not parse it as JSON. requestBody: required: true content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/PostEvent' responses: '200': description: | The event was accepted and queued for processing. The body is the plain-text string `OK`. content: text/plain: schema: type: string example: OK '400': description: | `ERR_BAD_REQUEST` — the payload failed validation, in which case `detail` lists the offending fields, or `phoneNumber` could not be parsed as a phone number. content: application/vnd.api+json: schema: $ref: '#/components/schemas/HttpErrorBody' '401': description: '`ERR_UNAUTHORIZED` — the `X-Recart-API-Key` header is missing.' content: application/vnd.api+json: schema: $ref: '#/components/schemas/HttpErrorBody' '403': description: '`ERR_FORBIDDEN` — the API key is unknown or has been revoked.' content: application/vnd.api+json: schema: $ref: '#/components/schemas/HttpErrorBody' '404': description: | `ERR_NOT_FOUND` — no subscriber exists for `phoneNumber`. Subscribe the phone number first; posting an event does not create a subscriber. content: application/vnd.api+json: schema: $ref: '#/components/schemas/HttpErrorBody' '415': description: | `ERR_UNSUPPORTED_MEDIA_TYPE` — `Content-Type` must be `application/vnd.api+json` or `application/json`. A `Content-Type` the API cannot parse at all is rejected earlier, before this error format applies, and returns an unstructured plain-text body. A malformed JSON body is rejected the same way, with `400`. content: application/vnd.api+json: schema: $ref: '#/components/schemas/HttpErrorBody' '417': description: | `ERR_EXPECTATION_FAILED` — a precondition on the account is not met. Either no event source is registered for the site with this `source.category` and `source.name` pair, or the subscriber exists but does not have an active SMS subscription. The two cases are distinguished by `detail`. content: application/vnd.api+json: schema: $ref: '#/components/schemas/HttpErrorBody' '500': description: | `ERR_INTERNAL_SERVER_ERROR` — the event passed validation but the request could not be processed, either because the subscriber could not be looked up or because the event could not be queued. The event was not processed, so it is safe to retry. Failures reaching an upstream service can also surface as other `5XX` statuses with an unstructured body, so treat the whole `5XX` range as retryable rather than matching on `500` alone. content: application/vnd.api+json: schema: $ref: '#/components/schemas/HttpErrorBody' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /webhooks: get: summary: Retrieve list of webhooks tags: - Webhook operationId: listWebhooks security: - ApiKeyAuth: [] description: Retrieve list of webhooks responses: '200': description: OK content: application/vnd.api+json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Webhook' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' post: summary: Create a new webhook tags: - Webhook operationId: createWebhook security: - ApiKeyAuth: [] description: Create a new webhook requestBody: required: true content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/Webhook' responses: '201': description: Created 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' callbacks: Incoming message: '{$request.body#/data/attributes/address}': post: requestBody: required: true content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/IncomingMessage' responses: '200': description: Your server returns this code if it accepts the callback Outgoing message: '{$request.body#/data/attributes/address}': post: requestBody: required: true content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/OutgoingMessage' responses: '200': description: Your server returns this code if it accepts the callback Subscribers unsubscribe: '{$request.body#/data/attributes/address}': post: requestBody: required: true content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/SubscribersUnsubscribe' responses: '200': description: Your server returns this code if it accepts the callback Subscribers subscribe: '{$request.body#/data/attributes/address}': post: requestBody: required: true content: application/json: schema: type: object properties: data: $ref: '#/components/schemas/SubscribersSubscribe' responses: '200': description: Your server returns this code if it accepts the callback '/webhooks/{id}': get: summary: Recieve a single webhook tags: - Webhook operationId: getWebhook security: - ApiKeyAuth: [] description: Recieve a single webhook parameters: - name: id in: path required: true description: ID of the webhook schema: type: string responses: '200': description: OK content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/Webhook' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' delete: summary: Remove an existing webhook tags: - Webhook operationId: deleteWebhook security: - ApiKeyAuth: [] description: Remove an existing webhook parameters: - name: id in: path required: true description: ID of the webhook schema: type: string responses: '204': description: No content 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' /messages: post: summary: Send message(s) to a subscriber tags: - Message operationId: postMessages security: - ApiKeyAuth: [] description: | Trigger SMS/MMS messages. Maximum 10 messages can be sent in a single request. Requester must comply with TCPA regulations, and make sure the message is not sent in quiet hours. The site must have an active or trial SMS subscription, otherwise the request fails with `417`. Messages are queued in the order given rather than sent inline, so `202` confirms that they were accepted for delivery, not that they were delivered. The response returns one entry per message; poll `GET /messages/{id}` with the returned IDs to follow their delivery status. requestBody: required: true content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/PostMessages' responses: '202': description: | The messages were accepted and queued for delivery, one entry per message, in the order they were given. content: application/vnd.api+json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/AcceptedMessage' '400': description: | `ERR_BAD_REQUEST` — the payload failed validation, in which case `detail` lists the offending fields, or `phoneNumber` could not be parsed as a phone number. Validation covers the documented limits: at most 10 messages, `body` at most 1024 characters, `type` must be `promotional`, and `attachment` must end in `.jpg`, `.jpeg`, `.png`, or `.gif`. content: application/vnd.api+json: schema: $ref: '#/components/schemas/HttpErrorBody' '401': description: '`ERR_UNAUTHORIZED` — the `X-Recart-API-Key` header is missing.' content: application/vnd.api+json: schema: $ref: '#/components/schemas/HttpErrorBody' '403': description: '`ERR_FORBIDDEN` — the API key is unknown or has been revoked.' content: application/vnd.api+json: schema: $ref: '#/components/schemas/HttpErrorBody' '415': description: | `ERR_UNSUPPORTED_MEDIA_TYPE` — `Content-Type` must be `application/vnd.api+json` or `application/json`. content: application/vnd.api+json: schema: $ref: '#/components/schemas/HttpErrorBody' '417': description: | `ERR_EXPECTATION_FAILED` — the site does not have an active or trial SMS subscription, so no messages can be sent until billing is resolved. No message in the request was queued. content: application/vnd.api+json: schema: $ref: '#/components/schemas/HttpErrorBody' '500': description: | The request passed validation but could not be processed. Messages are queued one by one, so a failure partway through leaves the earlier messages of the request already queued for delivery. No message IDs are returned in this case, so a blind retry of the whole request can duplicate the messages that already went through. Unlike the `4XX` responses, this status is not guaranteed to use the standard error envelope — an unstructured plain-text body is possible — so do not match on `errors[].code` here. 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/messages/{id}': get: summary: Returns the message's status by its ID tags: - Message operationId: getMessage security: - ApiKeyAuth: [] description: Returns the status of the selected message. parameters: - in: path name: id description: ID of the message required: true schema: type: string responses: '200': description: OK content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/OutgoingMessage' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' '/lists/{id}/phone-numbers': post: description: Add or remove phone numbers to a list summary: Add or remove phone numbers to a list operationId: modifyListMembers security: - ApiKeyAuth: [] tags: - List parameters: - in: path name: id required: true description: ID of the list schema: type: string requestBody: required: true content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/ModifyListMembersRequest' responses: '200': description: OK content: application/vnd.api+json: schema: type: object properties: data: $ref: '#/components/schemas/ModifyListMembersResponse' 4XX: $ref: '#/components/responses/HttpError' 5XX: $ref: '#/components/responses/HttpError' components: securitySchemes: ApiKeyAuth: type: apiKey in: header name: X-Recart-API-Key description: It can be obtained in Recart account after contacting Support responses: HttpError: description: HTTP Error response content: application/vnd.api+json: schema: $ref: '#/components/schemas/HttpErrorBody' schemas: HttpErrorBody: type: object required: - errors properties: errors: type: array items: type: object required: - id - code - title - detail properties: id: type: string example: 17035478-01a9-4aeb-a13c-88ab51e6fee3 code: type: string example: ERR_BAD_REQUEST title: type: string example: Bad request detail: type: string example: '' Account: type: - object required: - type - attributes properties: type: type: string enum: - accounts attributes: type: object required: - id - name - domain - currency properties: id: type: string description: ID of the account example: 65491e6a1d600d2c00414601 name: type: string description: Name of the account as shown in the Recart dashboard example: Example Store domain: type: string description: Storefront domain of the account example: examplestore.com currency: type: string description: Currency of the account as an ISO 4217 code example: USD timezone: type: - string - 'null' description: Time zone of the account as an IANA time zone name, null when the account has not set one example: America/New_York Flow: type: - object required: - type - attributes properties: type: type: string enum: - flows attributes: type: object required: - id - name - tags - status properties: id: type: string description: ID of flow example: 655637c97825e6ae655fe1b5 name: type: string description: Name of flow example: Welcome flow tags: type: array items: type: string description: Flow tags example: - automated - welcome status: type: string description: Status of flow enum: - draft - active - inactive - cancelled AutomatedFlowAttributes: type: object required: - id - name - status - tags properties: id: type: string description: ID of the automated flow example: 655637c97825e6ae655fe1b5 name: type: string description: Name of the automated flow example: Welcome flow status: type: string description: Status of the automated flow enum: - draft - active - inactive - cancelled tags: type: array items: type: string description: Flow tags example: - default-welcome - automated isQuietHoursEnabled: type: boolean description: Whether messages from this flow are held during the subscriber's quiet hours isSmartSendingEnabled: type: boolean description: Whether Smart Sending is enabled, suppressing sends to recently-messaged subscribers segmentId: type: string description: ID of the segment gating entry into the flow, if configured triggerDiscountId: type: string description: ID of the discount code associated with the flow's trigger, if configured createdAt: type: string format: date-time description: When the flow was created updatedAt: type: string format: date-time description: When the flow was last updated AutomatedFlow: type: - object required: - type - attributes properties: type: type: string enum: - automated-flows attributes: $ref: '#/components/schemas/AutomatedFlowAttributes' AutomatedFlowDetail: type: - object required: - type - attributes properties: type: type: string enum: - automated-flows attributes: allOf: - $ref: '#/components/schemas/AutomatedFlowAttributes' - type: object required: - entryFlowItemId - items properties: entryFlowItemId: type: string description: ID of the first item in the flow items: type: array description: Every item of the flow, linked by resolved ids items: $ref: '#/components/schemas/FlowItem' CampaignAttributes: type: object required: - id - name - status - campaignType properties: id: type: string description: ID of the campaign example: 66aa11b7825e6ae655fe200 name: type: string description: Name of the campaign example: Labor Day Sale status: type: string description: The dashboard's send status of the campaign enum: - draft - scheduled - processing - sending - sent - failed - cancelled - evaluating - noWinner campaignType: type: string description: Whether the campaign sends one message or runs an adaptive test across variants enum: - standard - adaptive scheduledFor: type: string format: date-time nullable: true description: When the campaign is scheduled to send; null when not scheduled scheduleType: type: string description: Whether scheduledFor is interpreted in the site's timezone or in each subscriber's own timezone enum: - siteTimezone - subscriberTimezone sentAt: type: string format: date-time description: When the campaign was actually sent deliveredSubscriberCount: type: integer description: Number of subscribers the campaign was delivered to includeSegments: type: array description: Segments the campaign audience includes items: $ref: '#/components/schemas/SegmentReference' excludeSegments: type: array description: Segments the campaign audience excludes items: $ref: '#/components/schemas/SegmentReference' isQuietHoursEnabled: type: boolean description: Whether messages from this campaign are held during the subscriber's quiet hours adaptiveTest: description: Adaptive test state (campaignType=adaptive only) $ref: '#/components/schemas/CampaignAdaptiveTest' discountUsage: type: array description: | Discounts the campaign's messages reference. referenceCount is the number of places in the campaign that reference the discount — configuration, not code consumption. items: type: object required: [id, referenceCount] properties: id: { type: string } referenceCount: { type: integer } discountCodePoolUsage: type: array description: | Discount code pools the campaign's messages reference. referenceCount is the number of places in the campaign that reference the pool — configuration, not code consumption. items: type: object required: [id, referenceCount] properties: id: { type: string } referenceCount: { type: integer } failedReason: type: string description: Why the campaign send failed (status=failed only) failedAt: type: string format: date-time description: When the campaign send failed (status=failed only) cancelledAt: type: string format: date-time description: When the campaign was cancelled (status=cancelled only) createdAt: type: string format: date-time description: When the campaign was created updatedAt: type: string format: date-time description: When the campaign was last updated SegmentReference: type: object description: | A segment of the campaign audience, or a resolved value of an expression condition. name is the referenced entity's current name, or an empty string when it could not be resolved (for example a deleted segment). required: - id - name properties: id: type: string description: ID of the segment example: 655637c97825e6ae655fe300 name: type: string description: Current name of the segment, empty when unresolved example: VIP customers Campaign: type: - object required: - type - attributes properties: type: type: string enum: - campaigns attributes: $ref: '#/components/schemas/CampaignAttributes' CampaignDetail: type: - object required: - type - attributes properties: type: type: string enum: - campaigns attributes: allOf: - $ref: '#/components/schemas/CampaignAttributes' - type: object required: - entryFlowItemId - items properties: entryFlowItemId: type: string description: ID of the first item in the flow items: type: array description: Every item of the flow, linked by resolved ids items: $ref: '#/components/schemas/FlowItem' FlowMessage: type: object description: One SMS/MMS message of an sms flow item properties: text: type: string description: Message body imageUrl: type: string nullable: true description: MMS image attached to the message FlowItemBranch: type: object description: | One outgoing branch of a split item. conditional-split branches use conditions or expression with nextItemId; random-split branches use percentage with nextItemId. properties: conditions: type: array items: type: object description: v1 conditional split conditions expression: $ref: '#/components/schemas/Expression' description: | v2 conditional split expression: `and[].or[]` of conditions, each with a `slug`, `type`, `operator` and, depending on the slug, a `value`, a `dateFilter` (time window the condition applies to) and `filters` (occurrence or count). A condition narrows its match with either one `subcondition` or, for `visited-page`, a `subconditions` list whose rows all apply to the same page view; each row has `slug`, `category`, `operator` and a `value`, absent when the operator is `exist`. Conditions and subcondition rows whose value is a list of IDs carry `values` instead of `value`: one `{ id, name }` entry per ID, where `name` is the current name of the referenced segment, flow, opt-in tool, product, variant or Klaviyo list, or an empty string when it could not be resolved. This applies to `member-of-a-segment` (segment ids, on the condition), and on the subcondition row for the flow subcondition (flow IDs), `subscription-source`/`optin-tool-id` (opt-in tool ids), `product`/`product-id` and `product-variant` (Shopify ids), `klaviyo-segment-or-list` (Klaviyo ids). example: and: - or: - slug: member-of-a-segment type: boolean operator: eq values: - id: 655637c97825e6ae655fe900 name: VIP customers - id: 655637c97825e6ae655fe901 name: '' percentage: type: number description: Share of traffic sent down this arm (random split) nextItemId: type: string nullable: true description: ID of the next item on this branch; null means end of branch (dead arm) FlowItem: type: object description: | One item of the flow's item graph. The resource `type` is always `flow-item`; the shape is picked by `attributes.type`. Items link to each other by resolved ids — `nextItemId` (or a branch's `nextItemId`) — rather than nesting; null means end of branch. An internal item type this API doesn't model is returned with `attributes.type` "unsupported" and only its id. required: - type - attributes properties: type: type: string enum: - flow-item attributes: type: object required: - type - id properties: type: type: string description: Kind of item enum: - sms - delay - conditional-split - random-split - adaptive-test - user-input - unsupported id: type: string description: ID of the item name: type: string description: Item's display name (sms only) messages: type: array description: Messages to send (sms only) items: $ref: '#/components/schemas/FlowMessage' discountCodes: type: array description: Static discount codes attached to the message (sms only) items: type: string discounts: type: array description: Discounts attached to the message (sms only) items: type: object discountCodePoolId: type: string description: ID of the discount code pool the message draws a unique code from (sms only) uniqueDiscountIssuanceType: type: string description: How a unique discount code is issued to the subscriber (sms only) replyKeywordSettings: type: object description: Keyword auto-reply configuration for this message (sms only) delayType: type: string description: Kind of delay (delay only) enum: - delay - delay-until - delay-scheduled durationInSeconds: type: integer description: Length of the delay, in seconds (delay only) branches: type: array description: Outgoing branches (conditional-split, random-split) items: $ref: '#/components/schemas/FlowItemBranch' defaultNextItemId: type: string nullable: true description: ID of the next item when no branch matches (conditional-split only) isSticky: type: boolean description: Whether a returning subscriber is kept on the same arm (random-split only) adaptiveTest: type: object description: Adaptive test configuration (adaptive-test only) properties: variants: type: array description: Variant flow items under test items: type: object properties: flowItemId: type: string description: ID of the variant's flow item evaluation: type: object description: Evaluation configuration used to pick a winner audienceSplitPercentage: type: number description: Share of the audience sampled before picking a winner fieldName: type: string description: | Name of the captured field. LEGACY: user-input items are no longer creatable; existing flows may still contain one. validationRule: type: string description: | Validation applied to the subscriber's reply. LEGACY: user-input items are no longer creatable; existing flows may still contain one. skippedNextItemId: type: string nullable: true description: | ID of the next item when the subscriber doesn't respond. LEGACY: user-input items are no longer creatable; existing flows may still contain one. nextItemId: type: string nullable: true description: ID of the next item; null means end of branch (sms, delay, user-input) CampaignAdaptiveTest: type: object description: Adaptive test state of a campaign properties: adaptiveTestStatus: type: string description: | running while the test variants are being evaluated; complete_with_winner when a variant won and was rolled out; complete_no_winner when no variant stood out; complete_control_kept when the control message beat every variant and was kept. enum: - running - complete_with_winner - complete_no_winner - complete_control_kept adaptiveTestResult: type: object description: Outcome of the test, present once evaluated properties: winnerFlowItemId: type: string description: ID of the winning variant's flow item wasTiebroken: type: boolean completedAt: type: string format: date-time testVariantsDispatchedAt: type: string format: date-time description: When the test variants were sent to the sample audience AdaptiveTestVariantEvaluationStats: type: object description: | The variant's totals frozen at the moment its adaptive test was evaluated — the numbers the winner was picked on. The evaluation runs once, when the evaluation window closes (testVariantsDispatchedAt plus the window), and takes each variant's lifetime totals as they stood then. It is a snapshot, not a range query: clicks, orders and opt-outs that arrive later are not added, and the winner's rollout to the rest of the audience is not included. Amounts are keyed by ISO 4217 code: USD always, the store currency additionally when it is not USD. Rates with a zero denominator are 0. required: - sent - clickRate - sales - spent - roi - optOutRate properties: sent: type: integer description: SMS and MMS messages sent to the test audience by this variant example: 1184 clickRate: type: number description: Clicks / sent example: 0.0621 sales: type: object additionalProperties: type: number description: Attributed order value per currency (ISO 4217 code) example: USD: 1420.5 spent: type: object additionalProperties: type: number description: SMS and MMS cost per currency (ISO 4217 code) example: USD: 35.52 roi: type: number description: sales.USD / spent.USD example: 39.99 optOutRate: type: number description: Opt-outs attributed to the variant / sent example: 0.0034 AdaptiveFlowSummary: type: object description: | One adaptive campaign's test, as evaluated and as it stands now. Each variant carries evaluationStats — the snapshot the winner was picked on, present once the test has completed — next to allTimeStats, the variant's lifetime totals computed at request time, which keep growing with late activity and, for the winner, include the rollout to the rest of the audience. required: - id - name - adaptiveTest - variants properties: id: type: string description: ID of the campaign example: 66aa11b7825e6ae655fe200 name: type: string description: Name of the campaign example: Labor Day Sale adaptiveTest: $ref: '#/components/schemas/CampaignAdaptiveTest' variants: type: array description: The variants under test, in the order of the adaptive-test item items: type: object required: - flowItemId - allTimeStats properties: flowItemId: type: string description: ID of the variant's flow item — the same id as items[] on the campaign detail and the keys of flow-items-summary evaluationStats: $ref: '#/components/schemas/AdaptiveTestVariantEvaluationStats' allTimeStats: description: The variant's lifetime totals at request time; recipients equals sent $ref: '#/components/schemas/FlowStatistics' FlowStatistics: type: object description: | Range totals of one flow, campaign, group or message — the same numbers as the dashboard. Rates with a zero denominator are 0. Amounts are keyed by ISO 4217 code: USD always, the store currency additionally when it is not USD. recipients and revenuePerRecipient are present on every view except sms-summary: the SMS channel total is aggregated without the first-message cohort that defines recipients, and its sent counts every message of every flow, so the number cannot be derived from it. The dashboard's Automated Flows header, built on the same data, shows RPM and no recipients for the same reason. Where the dashboard shows Recipients and RPR — the Campaigns header — read the blast entry of flow-groups-summary. required: - sent - clicked - clickRate - converted - sales - spent - roi - optOutRate - spamRate - revenuePerMessage properties: sent: type: integer description: SMS and MMS messages sent example: 41200 recipients: type: integer description: | Subscribers who received the flow's first message. Present on flow-groups-summary, automated-flows-summary, campaign-flows-summary, flow-summary and flow-items-summary (where it equals the item's sent — a message reaches a subscriber at most once); absent on sms-summary. example: 38900 clicked: type: integer description: Clicks on a link in one of the flow's messages example: 2140 clickRate: type: number description: Clicks / sent example: 0.0519 converted: type: integer description: Attributed orders example: 312 sales: type: object additionalProperties: type: number description: Attributed order value per currency (ISO 4217 code) example: USD: 24810.5 EUR: 22890.2 spent: type: object additionalProperties: type: number description: SMS and MMS cost per currency (ISO 4217 code) example: USD: 1236 roi: type: number description: sales.USD / spent.USD example: 20.07 optOutRate: type: number description: Opt-outs attributed to the flow / recipients example: 0.0041 spamRate: type: number description: Carrier spam rejections / sent example: 0.0002 revenuePerRecipient: type: number description: | sales.USD / recipients — the dashboard's RPR. Present wherever recipients is; absent on sms-summary. Equals revenuePerMessage on flow-items-summary. example: 0.64 revenuePerMessage: type: number description: sales.USD / sent — the dashboard's RPM example: 0.6 FlowGroupStatisticsItem: allOf: - type: object required: - group properties: group: type: string description: Flow group tag example: abandonment - $ref: '#/components/schemas/FlowStatistics' AutomatedFlowStatisticsItem: allOf: - type: object required: - flowId - name properties: flowId: type: string description: ID of the automated flow example: 6138d0ac2d79e00001210035 name: type: string description: Name of the automated flow example: Abandoned Cart - $ref: '#/components/schemas/FlowStatistics' CampaignFlowStatisticsItem: allOf: - type: object required: - flowId - name properties: flowId: type: string description: The campaign's flow id example: 68a0f1c7e8c9d2b001234abc name: type: string description: Name of the campaign example: Labor Day 20% off - $ref: '#/components/schemas/FlowStatistics' FlowViews: type: - object required: - type - attributes properties: type: type: string enum: - flow-views attributes: type: object description: | The requested view's data under its name — exactly one key per request. minProperties: 1 properties: sms-summary: description: SMS channel totals for the range, optionally narrowed by tags $ref: '#/components/schemas/FlowStatistics' flow-groups-summary: type: array description: Totals per flow group, campaigns included as blast items: $ref: '#/components/schemas/FlowGroupStatisticsItem' automated-flows-summary: type: array description: Totals per automated flow of the site items: $ref: '#/components/schemas/AutomatedFlowStatisticsItem' campaign-flows-summary: type: array description: Totals per campaign with activity in the range items: $ref: '#/components/schemas/CampaignFlowStatisticsItem' AutomatedFlowViews: type: - object required: - type - attributes properties: type: type: string enum: - automated-flow-views attributes: type: object description: | The requested view's data under its name — exactly one key per request. minProperties: 1 properties: flow-summary: description: The flow's totals for the range $ref: '#/components/schemas/FlowStatistics' flow-items-summary: type: object description: | Totals per message item, keyed by flowItemId — the same id as items[] on the flow detail. Only items that recorded activity in the range appear; a missing key means no activity. Per item, recipients equals sent (a message reaches a subscriber at most once), so revenuePerRecipient equals revenuePerMessage. additionalProperties: $ref: '#/components/schemas/FlowStatistics' CampaignFlowViews: type: - object required: - type - attributes properties: type: type: string enum: - campaign-flow-views attributes: type: object description: | The requested view's data under its name — exactly one key per request. minProperties: 1 properties: flow-summary: description: The campaign's totals for the range $ref: '#/components/schemas/FlowStatistics' flow-items-summary: type: object description: | Totals per message item, keyed by flowItemId — the same id as items[] on the campaign detail; adaptive-test variants are message items, so each variant is its own key. Only items that recorded activity in the range appear. Per item, recipients equals sent, so revenuePerRecipient equals revenuePerMessage. additionalProperties: $ref: '#/components/schemas/FlowStatistics' adaptive-flow-summary: description: The campaign's adaptive test with per-variant evaluation and lifetime statistics (adaptive campaigns only) $ref: '#/components/schemas/AdaptiveFlowSummary' DiscountAttributes: type: object required: - id - name - status - customizationType - type - discountClasses - shopifyDiscountId - createdAt - updatedAt properties: id: type: string description: ID of the discount example: 66aa0f1c7e8c9d2b00123abc name: type: string description: Name of the discount example: Welcome 10% status: type: string description: Computed from startsAt / endsAt; expired also after deactivation enum: - active - scheduled - expired customizationType: type: string description: unique = each customer gets a different code; general = one shared code enum: - unique - general expiryType: type: string description: | unique only. fixed = a code pool whose codes expire at the end date set when the discount was created. relative = an expiring code created on demand; its expiration timer starts the moment the customer receives the code via popup or SMS. enum: - fixed - relative type: type: string description: | Shopify discount type; with discountClasses it is the dashboard's type (basic + product = Amount off product, basic + order = Amount off order) enum: - basic - bxgy - free-shipping - app discountClasses: type: array description: | Shopify discount classes of the discount. Together with the price rule's combination settings they define which other discounts it can be combined with in one checkout, see https://help.shopify.com/en/manual/discounts/discount-combinations items: type: string enum: - product - order - shipping amount: type: number description: Not on app discounts example: 10 valueType: type: string description: Not on app discounts enum: - PERCENTAGE - FIXED_AMOUNT - FREE_SHIPPING - UNKNOWN summary: type: string description: Shopify's one-line description of value, target and conditions; not on app discounts example: 10% off entire order appTitle: type: string description: App discounts only — the Shopify app that owns the discount code: type: string description: general only example: WELCOME10 discountCodePattern: type: string description: unique only — the code prefix example: WELCOME- mode: type: string description: code pools only — refilling pools serve flows and popups, non-refilling pools serve campaigns enum: - refilling - non-refilling targetCount: type: integer description: code pools only example: 10000 availableCount: type: integer description: code pools only — codes not yet issued example: 8612 fillStatus: type: string description: code pools only — filling = codes still uploading to Shopify enum: - needFilling - filling - full durationSeconds: type: integer description: expiring only — validity from the moment the code is issued example: 86400 template: type: object additionalProperties: true description: | expiring only — the Shopify discount input each issued code's price rule is created from, as stored (type, title, appliesOncePerCustomer, usageLimit, combinesWith, customerSelection, customerGets, minimumRequirement, destinationSelection for free shipping) startsAt: type: string format: date-time description: Not on expiring discounts endsAt: type: string format: date-time nullable: true description: null = no end date; not on expiring discounts shopifyDiscountId: type: string description: The Shopify discount (price rule) id example: '1234567890123' createdAt: type: string format: date-time updatedAt: type: string format: date-time Discount: type: - object required: - type - attributes properties: type: type: string enum: - discounts attributes: $ref: '#/components/schemas/DiscountAttributes' DiscountStatistics: type: object description: | Lifetime counters of one discount, no date range. Which fields are present depends on the discount shape and on omitShopifyData: - sent — code pools and expiring discounts (customizationType unique), whatever omitShopifyData is; never on general discounts (a shared static code has no issuance record). Recart's count of codes issued to subscribers by a message or popup, not deliveries. - used, sales, codesCount — only with omitShopifyData=false, and only on general discounts and code pools; never on expiring discounts (each issued code is its own Shopify price rule, the stored one is never redeemed). Shopify's own counters, refreshed asynchronously — they can lag recent orders by minutes. Per shape: general → {} by default, used + sales + codesCount with omitShopifyData=false; code pool → sent by default, all four with omitShopifyData=false; expiring → sent, whatever the flag. properties: sent: type: integer description: Codes issued to subscribers from the pool or created on demand. Present on code pools and expiring discounts whatever omitShopifyData is; absent on general discounts example: 1388 used: type: integer description: Orders that redeemed the discount (Shopify asyncUsageCount). Present only with omitShopifyData=false, on general discounts and code pools; absent on expiring discounts example: 212 sales: type: object additionalProperties: type: number description: Shopify total sales keyed by currency code — the store currency only, no conversion. Same availability as used example: USD: 9418.4 codesCount: type: integer description: Codes Shopify holds for the discount, 1 for general. Same availability as used example: 10000 DiscountDetail: type: - object required: - type - attributes properties: type: type: string enum: - discounts attributes: allOf: - $ref: '#/components/schemas/DiscountAttributes' - type: object required: - usage - statistics properties: usage: type: object description: Where the discount is configured — configuration references, not code consumption required: - flows - campaigns - optinTools properties: flows: type: array description: Automated flows; a campaign's own flow is listed under campaigns only items: $ref: '#/components/schemas/UsageReference' campaigns: type: array items: $ref: '#/components/schemas/UsageReference' optinTools: type: array items: $ref: '#/components/schemas/UsageReference' statistics: $ref: '#/components/schemas/DiscountStatistics' UsageReference: type: object required: - id - name properties: id: type: string example: 6138d0ac2d79e00001210035 name: type: string description: Empty when the referenced entity no longer exists example: Welcome flow Segment: type: - object required: - type - attributes properties: type: type: string enum: - segments attributes: type: object required: - id - name - status - createdAt - updatedAt properties: id: type: string example: 64f2a1b2c3d4e5f60718293a name: type: string example: Win-back — no order in 90 days status: type: string enum: - active - calculating - syncing - unable-to-sync - dormant description: | The dashboard's Status column. active = membership kept current. calculating = segment being (re)computed. syncing = Klaviyo sync in progress. unable-to-sync = Klaviyo sync failed or the Klaviyo list was deleted. dormant = unused for 30 days (14 for Klaviyo-based), membership dropped, size 0. size: type: integer description: | Currently subscribed SMS subscribers, live; 0 while dormant. On the list only with includeSize=true, on the detail always. example: 8312 dormantAt: type: string format: date-time description: dormant only editedAt: type: string format: date-time description: Last change to name or expression createdAt: type: string format: date-time updatedAt: type: string format: date-time expression: $ref: '#/components/schemas/Expression' description: The membership rule, AND of ORs, ids resolved to names description: type: string description: The expression description in a sentence example: Number of orders is greater than 0 and Has not placed an order in the last 90 days List: type: - object required: - type - attributes properties: type: type: string enum: - lists attributes: type: object required: - id - name - status - createdAt - updatedAt properties: id: type: string example: 64f2a1b2c3d4e5f60718293d name: type: string example: Black Friday 2025 import status: type: string enum: - active - importing - syncing - unable-to-sync - dormant description: The dashboard's Status column — importing = list import running; the rest as on Segment size: type: integer description: | Currently subscribed SMS subscribers, live; 0 while dormant. On the list only with includeSize=true, on the detail always. example: 1204 dormantAt: type: string format: date-time description: dormant only editedAt: type: string format: date-time description: Last change to the name createdAt: type: string format: date-time updatedAt: type: string format: date-time Expression: type: object required: - and properties: and: type: array description: Every group must hold items: type: object required: - or properties: or: type: array description: At least one condition of the group must hold items: $ref: '#/components/schemas/Condition' Condition: type: object required: - slug - type properties: slug: type: string example: placed-an-order type: type: string enum: - boolean - number - string - date - array operator: type: string enum: - eq - neq - lt - gt - include - not_include - exist - not_exist description: Absent on date conditions field: type: string description: subscriber-detail only value: description: String, number, boolean or array of strings; absent when values is present values: type: array description: Replaces value when it is an entity id; name empty when unresolved items: $ref: '#/components/schemas/SegmentReference' dateFilter: type: object properties: type: type: string enum: - all - between - not-between - since - until - 'on' - in-the-last - not-in-the-last - exist - not-exist dateFrom: type: string format: date-time dateTo: type: string format: date-time daysOffset: type: integer filters: type: object description: occurrence narrows to the first or last event; count (visited-page) asks for at least min matching page views properties: occurrence: type: string enum: - first - last count: type: object required: - min properties: min: type: integer minimum: 1 subcondition: $ref: '#/components/schemas/Subcondition' subconditions: type: array description: visited-page only — rows that all apply to the same page view (page, product, collection, utm), in place of subcondition items: $ref: '#/components/schemas/Subcondition' Subcondition: type: object description: Narrows a condition to one entity or attribute; value is the literal, values the resolved { id, name } entries required: - slug - category - operator properties: slug: type: string enum: - flow - product - subscription-source - location-category - klaviyo-segment-or-list - page - collection - utm category: type: string operator: type: string enum: - eq - neq - lt - gt - include - not_include - exist - not_exist value: description: Literal, absent when values is present values: type: array items: $ref: '#/components/schemas/SegmentReference' OptinTool: type: - object required: - type - attributes properties: type: type: string enum: - optin-tools attributes: type: object required: - id - name - type - status - devices - channels properties: id: type: string description: ID of the opt-in tool example: 655637c97825e6ae655fe1b5 name: type: string description: Name of the opt-in tool example: Mobile - Preferences - Custom Images type: type: string description: Type of the opt-in tool enum: - popup - landing-page - embedded-form - keyword status: type: string description: Status of the opt-in tool enum: - active - draft - inactive devices: type: array description: Devices the tool targets items: type: string enum: - mobile - desktop channels: type: array description: Channels the tool collects items: type: string enum: - email - sms statusSchedule: type: object description: Upcoming scheduled status transitions. UTC Date and time in ISO 8601 format properties: activateAt: type: string format: date-time example: '2026-08-03T14:00:00.000+02:00' inactivateAt: type: string format: date-time example: '2026-08-10T14:00:00.000+02:00' optinMethod: type: object description: What handles a new opt-in required: - type properties: type: type: string description: Type of the message handler enum: - flow - integration flowId: type: string description: ID of the flow the tool feeds (type flow only) example: 655637c97825e6ae655fe1c2 experimentIds: type: array description: IDs of A/B experiments the tool participates in items: type: string example: - 655637c97825e6ae655fe1d9 steps: type: array description: Steps of the tool (popup only) items: type: string enum: - teaser - email - sms - smsWithEmail - oneTimePassword - oneClickVerification - oneClickOptin - success messagingType: type: string description: Messaging type of the tool (popup only) enum: - two-way - one-way tags: type: array items: type: string description: | Tags Recart derives from the popup's configuration on every save. Lowercase kebab-case, sorted. Popups only. Current groups: template (opt-in-offer, back-in-stock), opt-in method (email-only, phone-number-only, in-popup-confirmation, one-click-opt-in, reply-sms-consent), trigger (delay, exit-intent, returning-delay, external-trigger), engagement tool (plinko, spin-the-wheel, button-group, micro-yes) and discount (`discount-`, see `GET /discounts/{id}`). A popup carries exactly one template and one opt-in method tag, at most one trigger and one discount tag, and one engagement tool tag when it has a teaser step: tags of one group never share a popup, so per-tag totals within a group add up, while tags from different groups overlap. The vocabulary can grow; treat unknown tags as opaque. The tags describe the popup's current configuration; as in the dashboard, statistics are reported per tool under its current configuration. Not related to the `tags` of an opt-in tool experiment. example: - delay - discount-694132dcb842e9d365676043 - micro-yes - one-click-opt-in - opt-in-offer settings: type: object description: | Full tool settings (type-dependent). Returned only by getOptinTool; the collection endpoint omits it. RevenueMetrics: type: object description: | Revenue attributed to the opt-in tool: orders placed within 7 days of an interaction with the tool in the same session. Amounts are in USD, rounded to 2 decimal places. Fields are never null: a range without attributed orders returns 0 amounts, and rates are 0 when the denominator is 0. required: - associatedRevenue - orders - averageOrderValue - revenuePerVisitor - orderConversionRate properties: associatedRevenue: type: number description: Total value of the orders attributed to the opt-in tool, in USD example: 12403.5 orders: type: integer description: Number of orders attributed to the opt-in tool example: 96 averageOrderValue: type: number description: associatedRevenue / orders, in USD example: 129.2 revenuePerVisitor: type: number description: associatedRevenue / impressions, in USD example: 0.3 orderConversionRate: type: number description: orders / impressions example: 0.0023 OptinToolOptinSummaryData: type: object description: | Opt-in performance totals for the range. Counts are unique sessions. Email/SMS fields appear only when the tool collects that channel. Fields are never null: a range without data returns 0 counts and 0 rates. required: - impression - teaserConfirm - teaserConfirmRate - teaserDecline properties: impression: type: integer description: Unique sessions in which the popup was displayed example: 41200 teaserConfirm: type: integer description: Unique sessions that clicked the teaser and opened the popup example: 890 teaserConfirmRate: type: number description: teaserConfirm / impression example: 0.0216 teaserDecline: type: integer description: Unique sessions that dismissed the teaser example: 2140 emailOptin: type: integer description: Unique sessions that submitted an email address on the popup example: 610 emailOptinRate: type: number description: emailOptin / impression example: 0.0148 phoneNumberSubmitted: type: integer description: Unique sessions that submitted a phone number on the popup example: 530 phoneNumberSubmittedRate: type: number description: phoneNumberSubmitted / impression example: 0.0129 smsOptin: type: integer description: Unique sessions that completed the SMS opt-in example: 480 smsOptinRate: type: number description: smsOptin / impression example: 0.0117 OptinToolOptinHistoryBucket: type: object required: - timestamp - impression properties: timestamp: type: string format: date description: Start of the bucket, in UTC (weeks start on Monday) example: '2026-07-27' impression: type: integer description: Unique sessions in which the popup was displayed within the bucket emailOptin: type: integer description: Unique sessions that submitted an email address within the bucket emailOptinRate: type: number description: emailOptin / impression within the bucket smsOptin: type: integer description: Unique sessions that completed the SMS opt-in within the bucket smsOptinRate: type: number description: smsOptin / impression within the bucket OptinToolRevenueHistoryBucket: allOf: - type: object required: - timestamp properties: timestamp: type: string format: date description: Start of the bucket, in UTC (weeks start on Monday) example: '2026-07-27' - $ref: '#/components/schemas/RevenueMetrics' OptinToolRevenueByOptinSegmentsItem: allOf: - type: object required: - optinSegmentType - optinSegmentCount properties: optinSegmentType: type: string description: | The deepest opt-in stage the sessions in this row reached (noOptin / emailOptin / smsOptin / emailAndSMSOptin); the total row sums the whole funnel enum: - noOptin - emailOptin - smsOptin - emailAndSMSOptin - total optinSegmentCount: type: integer description: Unique sessions whose deepest opt-in stage is this segment - $ref: '#/components/schemas/RevenueMetrics' OptinToolRevenueByCountriesItem: allOf: - type: object required: - countryCode - impressionCount properties: countryCode: type: string description: | ISO 3166-1 alpha-2 country code of the visitors; example: US impressionCount: type: integer description: Unique sessions in which the popup was displayed in this country - $ref: '#/components/schemas/RevenueMetrics' OptinToolSubscriptionsHistoryBucket: type: object required: - timestamp - subscriptions properties: timestamp: type: string format: date description: Start of the bucket, in UTC (weeks start on Monday) example: '2026-07-27' subscriptions: type: integer description: New SMS subscribers the opt-in tool collected within the bucket OptinToolViews: type: - object required: - type - attributes properties: type: type: string enum: - optin-tool-views attributes: type: object description: | The requested view's data under its name — exactly one key for a single view, all seven for name=all. History and breakdown values are arrays (one element per bucket / country / segment). minProperties: 1 properties: optin-summary: description: Opt-in performance totals for the range $ref: '#/components/schemas/OptinToolOptinSummaryData' optin-history: type: array description: Opt-in performance per bucket; one bucket per targetResolution unit, gaps zero-filled items: $ref: '#/components/schemas/OptinToolOptinHistoryBucket' revenue-summary: description: Revenue attributed to the tool, totals for the range $ref: '#/components/schemas/RevenueMetrics' revenue-history: type: array description: Attributed revenue per bucket; one bucket per targetResolution unit, gaps zero-filled items: $ref: '#/components/schemas/OptinToolRevenueHistoryBucket' revenue-by-optin-segments: type: array description: Attributed revenue split by opt-in segment; one element per segment plus a total row items: $ref: '#/components/schemas/OptinToolRevenueByOptinSegmentsItem' revenue-by-countries: type: array description: Impressions and attributed revenue per country, sorted desc by associatedRevenue; UNKNOWN_COUNTRY included items: $ref: '#/components/schemas/OptinToolRevenueByCountriesItem' subscriptions-history: type: array description: New SMS subscribers collected by the tool per bucket; one bucket per targetResolution unit, gaps zero-filled items: $ref: '#/components/schemas/OptinToolSubscriptionsHistoryBucket' OptinToolsSummaryItem: type: object description: | One opt-in tool's totals for the range — the tool's identity, then its raw metric-event unique-session counts merged with the new SMS subscriptions it collected. Besides optinToolId, optinToolName, optinToolType, optinToolTags and smsSubscriptions, every key is a MetricEvent value (see the MetricEvent schema) with its count; only events that occurred appear, a missing key means 0. required: - optinToolId - optinToolName - optinToolType - smsSubscriptions properties: optinToolId: type: string example: '655637c97825e6ae655fe1c9' optinToolName: type: string description: Name of the opt-in tool example: Mobile - Preferences - Custom Images optinToolType: type: string description: Type of the opt-in tool enum: - popup - landing-page - embedded-form - keyword optinToolTags: type: array items: type: string description: | The tool's current tags (see OptinTool.tags). Absent for tools without tags. example: - delay - discount-694132dcb842e9d365676043 - micro-yes - one-click-opt-in - opt-in-offer smsSubscriptions: type: integer description: New SMS subscriptions collected by the tool in the range example: 150 additionalProperties: type: integer description: MetricEvent → number of unique sessions the event occurred in example: 20400 OptinToolListViews: type: - object required: - type - attributes properties: type: type: string enum: - optin-tool-list-views attributes: type: object description: | The requested view's data under its name — exactly one key per request. minProperties: 1 properties: optin-tools-summary: type: array description: | One entry per opt-in tool that recorded any metric event or collected any SMS subscription in the range. items: $ref: '#/components/schemas/OptinToolsSummaryItem' OptinToolExperiment: type: - object required: - type - attributes properties: type: type: string enum: - optin-tool-experiments attributes: type: object required: - id - name - status - dateFrom - dateTo - optinToolIds - createdAt - updatedAt properties: id: type: string description: ID of the experiment example: 655637c97825e6ae655fe1d9 name: type: string description: Name of the experiment example: Teaser vs no teaser status: type: string description: | Status of the experiment. `draft` is still being set up in the A/B test wizard, `scheduled` waits for `dateFrom`, `cancelled` was called off before it ran. Only a `running` or `ended` experiment has statistics; the views of any other status return 400. enum: - draft - scheduled - running - ended - cancelled dateFrom: type: string format: date-time description: Start of the experiment window. UTC date and time in ISO 8601 format example: '2026-07-27T00:00:00.000Z' dateTo: type: string format: date-time description: | End of the experiment window, exclusive. UTC date and time in ISO 8601 format. For a running experiment this is the planned end; statistics stop at the current time instead. example: '2026-08-10T00:00:00.000Z' optinToolIds: type: array description: | IDs of the opt-in tools taking part in the experiment — its variants. Statistics views return one entry per ID. items: type: string example: - 655637c97825e6ae655fe1c9 - 655637c97825e6ae655fe1b5 variants: type: array description: | Traffic split of the experiment, one entry per opt-in tool in `optinToolIds`. Present for experiments created in the A/B test wizard; older experiments split traffic evenly and have no designated control. items: $ref: '#/components/schemas/OptinToolExperimentVariant' primaryMetric: type: string description: | Metric the experiment is decided on. Present for experiments created in the A/B test wizard; older experiments were decided on opt-in rate. `emailOptin` and `smsOptin` are opt-in rates, the rest are the `revenue-summary` metrics. enum: - emailOptin - smsOptin - associatedRevenue - orders - averageOrderValue - revenuePerVisitor - orderConversionRate example: smsOptin winnerOptinToolId: type: string description: | ID of the variant Recart picked as the winner, present once the experiment has ended. Picked on the highest `primaryMetric` value — opt-in rate when there is none — this is not a statistical significance test. example: 655637c97825e6ae655fe1c9 winnerMetricValue: type: number description: | Value of `primaryMetric` for the winning variant, present with `winnerOptinToolId`. Rates are fractions (0.0135 = 1.35%), revenue amounts are in USD. For an experiment without a `primaryMetric` this is the winner's opt-in rate. example: 0.0135 winnerOptinRate: type: number description: | Opt-in rate of the winning variant. Set only for experiments without a `primaryMetric`; `winnerMetricValue` carries the same number for those. example: 0.0135 tags: type: array description: | Tags the merchant put on the experiment in the A/B test wizard, in the order they were added. items: $ref: '#/components/schemas/OptinToolExperimentTag' notes: type: string description: Free-text notes the merchant wrote on the experiment example: Testing a shorter headline on the mobile popup createdAt: type: string format: date-time description: Creation time of the experiment. UTC date and time in ISO 8601 format example: '2026-07-20T09:14:33.000Z' updatedAt: type: string format: date-time description: Last modification time of the experiment. UTC date and time in ISO 8601 format example: '2026-08-10T00:00:01.000Z' OptinToolExperimentVariant: type: object description: One variant of an A/B test experiment and its share of traffic. required: - optinToolId - weight - isControl properties: optinToolId: type: string description: ID of the opt-in tool shown as this variant example: 655637c97825e6ae655fe1c9 weight: type: number description: | Share of eligible visitors assigned to this variant, as a fraction of 1. The weights of an experiment sum to 1. minimum: 0 maximum: 1 example: 0.5 isControl: type: boolean description: | Whether this variant is the control the others are compared against. Exactly one variant of an experiment is the control. example: true OptinToolExperimentTag: type: object description: A tag attached to an A/B test experiment. required: - value - label properties: value: type: string description: Stable key of the tag, unique within the site example: headline label: type: string description: Display name of the tag as shown in the dashboard example: Headline OptinToolExperimentOptinSummaryData: description: | Opt-in performance totals of one variant for the experiment's window — the same fields as an opt-in tool's optin-summary, plus the subscribers the variant collected. allOf: - $ref: '#/components/schemas/OptinToolOptinSummaryData' - type: object required: - subscriptions properties: subscriptions: type: integer description: New SMS subscribers the variant collected example: 268 MetricEvent: type: string description: | Raw popup metric event identifier. Revenue is carried only by impressionRevenue, emailClickRevenue and smsOptinRevenue; orderValueUSD is 0 for every other event. enum: - teaserConfirmation - teaserDecline - smsClick - emailClick - closePopup - openMinimized - closeMinimized - impression - minimizedImpression - close - smsOptin - optinRequestSent - successClick - engagement - emailAutofill - smsAutofill - oneTimePasswordAutofill - oneTimePasswordClick - oneTimePasswordResend - oneClickVerificationClick - oneClickVerificationAutofill - oneClickVerificationResend - oneClickThisIsntMe - impressionRevenue - emailClickRevenue - smsOptinRevenue - oneClickReturningVisitorSMSClick - oneClickReturningVisitorEmailClick - oneClickReturningVisitorSuccessClick - oneClickReturningVisitorClose - oneClickReturningVisitorClosePopup - oneClickReturningVisitorCloseMinimized - oneClickReturningVisitorImpression - oneClickReturningVisitorMinimizedImpression - oneClickReturningVisitorVerificationClick - oneClickReturningVisitorVerificationAutofill - oneClickReturningVisitorVerificationResend - oneClickReturningVisitorThisIsntMe - oneClickReturningVisitorTeaserDecline - oneClickReturningVisitorTeaserConfirmation - oneClickReturningVisitorOpenMinimized - oneClickReturningVisitorAutofill - oneClickNewVisitorSMSClick - oneClickNewVisitorEmailClick - oneClickNewVisitorSuccessClick - oneClickNewVisitorClose - oneClickNewVisitorClosePopup - oneClickNewVisitorCloseMinimized - oneClickNewVisitorImpression - oneClickNewVisitorMinimizedImpression - oneClickNewVisitorVerificationClick - oneClickNewVisitorVerificationAutofill - oneClickNewVisitorVerificationResend - oneClickNewVisitorThisIsntMe - oneClickNewVisitorTeaserDecline - oneClickNewVisitorTeaserConfirmation - oneClickNewVisitorOpenMinimized - oneClickNewVisitorAutofill MetricEventStatistic: type: object description: Raw count and attributed order value of a single metric event required: - count - orderValueUSD properties: count: type: integer description: Number of times the event occurred example: 31 orderValueUSD: type: number description: | Value of the orders attributed to the event, in USD, rounded to 2 decimal places. 0 for every event other than impressionRevenue, emailClickRevenue and smsOptinRevenue. example: 2410.5 OptinToolExperimentViews: type: - object required: - type - attributes properties: type: type: string enum: - optin-tool-experiments-views attributes: type: object description: | The requested section under its name — exactly one key for a single view, all four for name=all. Every section is an object keyed by the variant's opt-in tool ID, holding that variant's totals for the experiment's window. minProperties: 1 properties: optin-summary: type: object description: Opt-in performance totals per variant additionalProperties: $ref: '#/components/schemas/OptinToolExperimentOptinSummaryData' revenue-summary: type: object description: Attributed revenue totals per variant additionalProperties: $ref: '#/components/schemas/RevenueMetrics' revenue-by-optin-segments: type: object description: | Attributed revenue split by opt-in segment per variant; one element per segment plus a total row additionalProperties: type: array items: $ref: '#/components/schemas/OptinToolRevenueByOptinSegmentsItem' metric-event-summary: type: object description: | Raw metric event counts per variant, available for significance math. Each variant holds a sparse map whose keys are MetricEvent values — only events that occurred within the experiment's window appear, and a missing key means 0. additionalProperties: type: object propertyNames: $ref: '#/components/schemas/MetricEvent' additionalProperties: $ref: '#/components/schemas/MetricEventStatistic' UpdateCart: type: - object required: - type - attributes properties: type: type: string enum: - carts attributes: type: object required: - totalPrice - recoveryUrl - lineItems properties: totalPrice: type: object required: - value - currency properties: value: type: number format: double description: Value of cart example: 4.2 currency: type: string description: Currency of the cart example: USD recoveryUrl: type: string format: uri description: URL of the cart recovery page example: 'https://example.com/cart' lineItems: type: array items: type: object required: - productId - name - quantity - price properties: productId: type: string format: int64 description: ID of the product example: '9007199254740991' variantId: type: string format: int64 description: ID of the product variant example: '9007199254740991' name: type: string description: Name of the product example: Product name quantity: type: integer format: int32 description: Quantity of the product example: 1 price: type: object required: - value - currency properties: value: type: number format: double description: Value of cartItem example: 4.2 currency: type: string description: Currency of the cartItem example: USD FulfillOrder: type: - object required: - type - attributes properties: type: type: string enum: - fulfillments attributes: type: object required: - orderNumber - orderId - createdAt properties: orderNumber: type: string format: int64 description: Order number example: '9007199254740991' orderId: type: string format: int64 description: Order ID example: '9007199254740991' phoneNumber: type: string description: Preferably E.164 format example: '+36301234567' sessionId: type: string description: Recart identifier of the purchase session. Use `_recart.getSessionId()` on the merchant's store when Recart script is running. example: 655637bfaf3c6463c0f06d3e createdAt: type: string description: UTC Date and time in ISO 8601 format example: '2021-08-10T14:00:00.000+02:00' trackingCompany: type: string description: Name of the tracking company example: UPS trackingNumber: type: string description: Tracking number example: '12344321' trackingUrl: type: string format: uri description: Tracking URL example: 'https://track.me' AbandonCart: type: - object required: - type - attributes properties: type: type: string enum: - abandonments attributes: type: object required: - type - sessionId properties: type: type: string description: 'Type of the abandonment, "cart" and "browse" are supported' example: cart sessionId: type: string description: Recart identifier of the purchase session. Use `_recart.getSessionId()` on the merchant's store when Recart script is running. example: 655637bfaf3c6463c0f06d3e productId: type: string format: int64 description: ID of the product example: '9007199254740991' PostSubscription: type: object required: - type - attributes properties: type: type: string enum: - subscriptions attributes: type: object description: Attributes of the subscriber required: - phoneNumber - source properties: phoneNumber: type: string description: Preferably E.164 format example: '+36301234567' source: type: object required: - category - name properties: category: type: string description: Source category example: amped name: type: string description: Source name example: subscription externalId: type: string description: Optional identifier example: 2024 june campaign browser: type: object properties: userAgent: type: string description: User agent of the browser example: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko)' language: type: string description: Language of the browser example: en url: type: string format: uri description: URL of the browser page example: 'https://cars.myshopify.com/buy-this' sessionId: type: string description: Recart identifier of the purchase session. Use `_recart.getSessionId()` on the merchant's store when Recart script is running. example: 655637bfaf3c6463c0f06d3e shopperId: type: string deprecated: true description: 'Deprecated: the `_recart.getShopperId()` method used to source this value has been removed and there is no replacement. This field is retained for backward compatibility but should no longer be relied upon.' example: 655637c97825e6ae655fe1b5 firstName: type: string description: First name of the subscriber example: John lastName: type: string description: Last name of the subscriber example: Doe timezone: type: string description: Timezone of the subscriber example: Europe/Budapest location: type: object properties: city: type: string description: City example: New York province: type: string description: Province example: New York zip: type: string description: ZIP code example: '12345' country: type: string description: Country example: US ipAddress: type: string format: ipv4 description: IP address of the subscriber example: 192.158.1.38 SubscriptionSource: type: object description: | Where a subscription or an opt-out came from. For a subscription or an optin event `type` is the acquiring source — an opt-in tool type (popup, landing-page, embedded-form, keyword) or a non-tool source (import, custom-integration, public-api, shopify_checkout, …). For an optout event it is the reason: keyword, ai, opt_out_link, manual (dashboard), public-api, or a cleaning reason (deactivated_number, known_litigator, landline, reassigned). `id` and `name` are present when the source is an entity: the opt-in tool (its name) or the import (its file name); name is an empty string when it could not be resolved. required: - type properties: type: type: string description: Source slug or opt-out reason example: popup id: type: string description: ID of the opt-in tool or import behind the source example: 655637c97825e6ae655fe1c9 name: type: string description: Name of the opt-in tool, or file name of the import; empty when unresolved example: Mobile - Preferences - Custom Images Optin: type: object description: One opt-in or opt-out event of a channel. required: - type - createdAt properties: type: type: string description: optin = the subscriber joined the channel; optout = the subscriber left it enum: - optin - optout createdAt: type: string format: date-time description: When the event happened source: $ref: '#/components/schemas/SubscriptionSource' sourceUrl: type: string description: optin only — the page the opt-in happened on, query string included integrationSlug: type: string description: optin only — the integration that created the subscription example: klaviyo Subscriber: type: object description: | One subscriber — no phone number, email or name. Channel data sits under the channel key; only the channels selected with `channel` are present. required: - type - attributes properties: type: type: string enum: - subscribers attributes: type: object required: - id - segments - createdAt - updatedAt properties: id: type: string description: Internal ID of the subscriber example: 66aa0f1c7e8c9d2b00123abc timezone: type: string description: IANA timezone name assigned to the subscriber example: America/New_York segments: type: array description: Segments the subscriber is a member of right now — no membership history items: type: object required: - id - name - type properties: id: type: string description: ID of the segment example: 64f2a1b2c3d4e5f60718293a name: type: string description: Name of the segment as shown in the dashboard example: VIP customers type: type: string description: segment = dynamic, rule-based; list = manually managed enum: - segment - list createdAt: type: string format: date-time description: When the subscriber record was created — the first time the subscriber was seen on any channel updatedAt: type: string format: date-time description: Last change to the subscriber record sms: type: object description: The subscriber's SMS channel required: - status - subscriptionSource - optinHistory properties: status: type: string description: subscribed while the number receives SMS; unsubscribed after any opt-out or cleaning removal enum: - subscribed - unsubscribed subscribedAt: type: string format: date-time description: When the current SMS subscription started; reset by a re-subscribe lastInteractionAt: type: string format: date-time description: Last inbound event on the channel — the opt-in, a STOP or START keyword reply, or an import touching the record subscriptionSource: $ref: '#/components/schemas/SubscriptionSource' country: type: string description: Country code of the phone number from the carrier lookup example: US optinHistory: type: array description: Every opt-in and opt-out event of the channel, oldest first items: $ref: '#/components/schemas/Optin' SubscriptionSourcesItem: type: object description: | New SMS subscriptions collected from one source in the range. A source is either an opt-in tool type (popup, landing-page, embedded-form, keyword) or a non-tool source slug (import, custom-integration, public-api, shopify_checkout, …). required: - source - smsSubscriptions properties: source: type: string example: popup smsSubscriptions: type: integer example: 419 SubscriberListStatistics: type: object description: | List statistics of one period, grouped by channel — only the channels selected with `channel` are present. properties: sms: type: object description: | SMS list statistics — list size at the end of the period, and the subscriptions, opt-outs and cleaning removals within it. required: - subscribers - subscriptions - unsubscriptions - cleaning properties: subscribers: type: integer description: SMS subscribers at the end of the period (list size). example: 48210 subscriptions: type: integer description: New SMS subscriptions in the period, gross — re-subscribes included. example: 1412 unsubscriptions: type: object description: Subscriber-initiated SMS opt-outs in the period, by how the opt-out arrived. required: - keyword - ai - optOutLink - dashboard - publicApi - integration properties: keyword: type: integer description: STOP or another unsubscribe keyword texted in (AI-detected replies excluded). example: 171 ai: type: integer description: Free-text replies the AI intent classifier recognized as an opt-out. example: 22 optOutLink: type: integer description: The opt-out link in a message. example: 39 dashboard: type: integer description: Unsubscribed by the merchant in the dashboard. example: 3 publicApi: type: integer description: Unsubscribed through the public API (DELETE /subscriptions). example: 1 integration: type: integer description: Opt-outs synced from an integration such as Klaviyo. example: 0 cleaning: type: object description: Automated list cleaning in the period, by reason. required: - deactivatedNumber - knownLitigator - landline - reassigned properties: deactivatedNumber: type: integer description: The carrier reported the number as deactivated. example: 44 knownLitigator: type: integer description: The number is on the known-litigator list. example: 2 landline: type: integer description: Landline number, cannot receive SMS. example: 9 reassigned: type: integer description: The number was reassigned to a new owner. example: 6 SubscriberListHistoryItem: allOf: - type: object required: - date properties: date: type: string format: date description: The UTC calendar day the statistics belong to. example: '2026-08-31' - $ref: '#/components/schemas/SubscriberListStatistics' SubscribersByCountry: type: object description: Currently subscribed numbers by country, grouped by channel. properties: sms: type: array description: Sorted by subscribers, descending. items: type: object required: - countryCode - subscribers properties: countryCode: type: string description: Country code of the phone number from the carrier lookup. example: US subscribers: type: integer description: Currently subscribed SMS subscribers with a number in this country. example: 41200 SubscribersViews: type: - object required: - type - attributes properties: type: type: string enum: - subscribers-views attributes: type: object description: | The requested view's data under its name — exactly one key per request. minProperties: 1 properties: subscription-sources: type: array description: | One entry per subscription source, sorted descending by smsSubscriptions. items: $ref: '#/components/schemas/SubscriptionSourcesItem' list-summary: $ref: '#/components/schemas/SubscriberListStatistics' list-history: type: array description: One entry per UTC calendar day of the range. items: $ref: '#/components/schemas/SubscriberListHistoryItem' countries-summary: $ref: '#/components/schemas/SubscribersByCountry' PatchSubscriber: type: object required: - type - attributes properties: type: type: string enum: - subscribers attributes: type: object description: Attributes of the subscriber to update required: - customAttributes properties: customAttributes: type: object description: > Merchant-defined custom attributes as key/value pairs. PATCH/merge semantics: keys included in the request are set or overwritten; a key with a `null` value is deleted; keys not included are left unchanged. Limits: maximum 30 attributes per subscriber; the entire `customAttributes` object must not exceed 16 KB (enforced by the API server). Keys must match `^(?!recart_)[A-Za-z][A-Za-z0-9_]{0,63}$` (start with a letter, alphanumeric or underscore, max 64 characters, no spaces; the `recart_` prefix is reserved). Values must be a string (max 1024 characters), number, boolean, an array of up to 100 strings (each max 255 characters), or `null` to delete the attribute. Nested objects are not allowed. maxProperties: 30 propertyNames: pattern: '^(?!recart_)[A-Za-z][A-Za-z0-9_]{0,63}$' additionalProperties: oneOf: - type: string maxLength: 1024 - type: number - type: boolean - type: array maxItems: 100 items: type: string maxLength: 255 - type: 'null' example: loyalty_tier: gold lifetime_orders: 7 vip: true last_review_at: '2026-06-01T10:00:00Z' favorite_categories: - shoes - bags Webhook: type: object required: - type - attributes properties: type: type: string enum: - webhooks attributes: type: object required: - topic - address properties: topic: type: string description: 'Event type, messages/incoming, messages/outgoing, subscribers/unsubscribe, subscribers/subscribe' example: messages/incoming address: type: string format: uri description: Destination URL for webhook delivery example: 'https://call.me' PostMessages: type: object required: - type - attributes properties: type: type: string enum: - messages attributes: type: object required: - phoneNumber - messages properties: phoneNumber: type: string description: Preferably E.164 format example: '+36301234567' messages: type: array items: type: object required: - type - body properties: type: type: string description: 'Type of the message, only promotional is supported' example: promotional body: type: string description: 'Content of the message, maximum 1024 characters' example: 'Hi, welcome to our store.' attachment: type: string format: uri description: 'URL of the attachment, extension must be .jpg, .jpeg, .png, or .gif' example: 'https://img.url.jpg' IncomingMessage: type: object required: - type - attributes properties: type: type: string enum: - messages attributes: type: object properties: id: type: string description: Id example: 65ba227ffa0ad3e1bef89449 body: type: string description: Content of the message example: What's the status of my order? hasAttachment: type: boolean description: Returns true if the message has an attachment example: false from: type: string description: from example: '+123456789' to: type: string description: to example: '+987654321' receivedAt: type: string description: UTC Date and time in ISO 8601 format example: '2021-08-10T14:00:00.000+02:00' AcceptedMessage: type: object description: A message accepted for delivery by `POST /messages`. required: - type - attributes properties: type: type: string enum: - messages attributes: type: object required: - id - message properties: id: type: string description: ID of the queued message. Use it with `GET /messages/{id}` to follow the delivery status. example: 65ba227ffa0ad3e1bef89449 message: type: string description: Content of the message, echoed back from the request example: 'Hi, welcome to our store.' OutgoingMessage: type: object required: - type - attributes properties: type: type: string enum: - messages attributes: type: object properties: id: type: string description: Id example: 65ba227ffa0ad3e1bef89449 status: type: string description: 'Status of the message. It can be processing, sent or error' example: sent body: type: string description: Content of the message example: Hey there! Your order is on the way. sentAt: type: string description: UTC Date and time in ISO 8601 format example: '2021-08-10T14:00:00.000+02:00' from: type: string description: Phone number of the sender in E.164 format example: '+36301234567' to: type: string description: Phone number of the recipient in E.164 format example: '+36301234567' SubscribersUnsubscribe: type: object required: - type - attributes properties: type: type: string enum: - subscriptions attributes: type: object properties: subscriberId: type: string description: Recart identifier of the subscriber example: 655637c97825e6ae655fe1b5 phoneNumber: type: string description: Preferably E.164 format example: '+36301234567' SubscribersSubscribe: type: object required: - type - attributes properties: type: type: string enum: - subscriptions attributes: type: object properties: subscriberId: type: string description: Recart identifier of the subscriber example: 655637c97825e6ae655fe1b5 phoneNumber: type: string description: Preferably E.164 format example: '+36301234567' source: type: string description: Source of the subscription example: welcome popup sourceId: type: string description: Recart identifier of the source example: 655637c97825e6ae655fe1b5 subscribedAt: type: string description: UTC Date and time in ISO 8601 format example: '2021-08-10T14:00:00.000+02:00' optinType: type: string description: Subscription optin level example: promotional CreateOrder: type: object required: - type - attributes properties: type: type: string example: orders attributes: type: object required: - orderStatusUrl - orderNumber - orderId - totalPrice - lineItems - createdAt properties: phoneNumber: type: string description: Preferably E.164 format example: '+36301234567' sessionId: type: string description: Recart identifier of the purchase session. Use `_recart.getSessionId()` on the merchant's store when Recart script is running. example: 655637bfaf3c6463c0f06d3e orderStatusUrl: type: string format: uri description: URL of the order status page example: 'https://example.com/order' orderNumber: type: string format: int64 description: Order number example: '9007199254740991' orderId: type: string format: int64 description: Order ID example: '9007199254740991' totalPrice: type: object required: - value - currency properties: value: type: number format: double description: Value of order example: 4.2 currency: type: string description: Currency of the order example: USD createdAt: type: string description: UTC Date and time in ISO 8601 format example: '2021-08-10T14:00:00.000+02:00' lineItems: type: array items: type: object required: - productId - name - quantity - price properties: productId: type: string format: int64 description: ID of the product example: '9007199254740991' variantId: type: string format: int64 description: ID of the product variant example: '9007199254740991' name: type: string description: Name of the product example: Product name quantity: type: integer format: int32 description: Quantity of the product example: 1 price: type: object required: - value - currency properties: value: type: number format: double description: Value of orderItem example: 4.2 currency: type: string description: Currency of the orderItem example: USD discountCodes: type: array items: type: object required: - code - amount properties: code: type: string description: Discount code example: DISCOUNT amount: type: number format: double description: Value of discount example: 4.2 UpdateOrder: type: object required: - type - attributes properties: type: type: string example: orders attributes: type: object required: - phoneNumber - orderStatusUrl - totalPrice - lineItems - updatedAt properties: phoneNumber: type: string description: Preferably E.164 format example: '+36301234567' orderStatusUrl: type: string format: uri description: URL of the order status page example: 'https://example.com/order' totalPrice: type: object required: - value - currency properties: value: type: number format: double description: Value of order example: 4.2 currency: type: string description: Currency of the order example: USD updatedAt: type: string description: UTC Date and time in ISO 8601 format example: '2021-08-10T14:00:00.000+02:00' lineItems: type: array items: type: object required: - productId - name - quantity - price properties: productId: type: string format: int64 description: ID of the product example: '9007199254740991' variantId: type: string format: int64 description: ID of the product variant example: '9007199254740991' name: type: string description: Name of the product example: Product name quantity: type: integer format: int32 description: Quantity of the product example: 1 price: type: object required: - value - currency properties: value: type: number format: double description: Value of orderItem example: 4.2 currency: type: string description: Currency of the orderItem example: USD discountCodes: type: array items: type: object required: - code - amount properties: code: type: string description: Discount code example: DISCOUNT amount: type: number format: double description: Value of discount example: 4.2 PostEvent: type: object required: - type - attributes properties: type: type: string enum: - events attributes: type: object required: - phoneNumber - source properties: phoneNumber: type: string description: Preferably E.164 format example: '+36301234567' source: type: object required: - category - name properties: category: type: string description: Source category example: payment name: type: string description: Source name example: billing attempt failed properties: type: object description: | Data of the event, as flat key/value pairs. At most 10 properties are allowed; more than that is rejected with `400`. Properties are not automatically available to the flow. Only properties that Recart already supports are delivered to messages, where the message inserts one from the flow editor's variable picker. Contact Support to find out which properties your account can use, or to request support for a new one. Any other property is accepted and then discarded. The request still returns `200` and the flow is still triggered, but the value never reaches the message, so a discarded property is indistinguishable from a delivered one. Do not design a message around a property you have not confirmed is supported. To personalise or target on your own data, store it on the subscriber with `PATCH /subscribers` and use it as a segment condition instead. example: yourVariableName: 'your value' PostEventSource: type: object required: - type - attributes properties: type: type: string enum: - events attributes: type: object required: - category - name - type properties: category: type: string description: Source category example: payment name: type: string description: Source name example: billing attempt failed type: type: string enum: - custom - optin description: Type of source example: optin ModifyListMembersRequest: type: object description: Add or remove phone numbers to a list required: - type - attributes properties: type: enum: - lists attributes: required: - phoneNumbers - operation type: object properties: phoneNumbers: type: array items: type: string example: '+36301234567' operation: enum: - add - remove example: add ModifyListMembersResponse: title: ModifyListMembers Response type: object required: - type - attributes properties: type: enum: - lists attributes: type: object required: - phoneNumber - status properties: phoneNumber: type: string example: '+36301234567' status: enum: - added - removed - not_found example: added