---
openapi: 3.0.1
info:
  title: ConvertFlow API
  version: v1
  description: |
    ConvertFlow's public v1 API. Endpoints are grouped by namespace, listed in the tags below.

    ## Authentication
    ConvertFlow uses OAuth 2.1 (authorization code + PKCE). Obtain a token from ConvertFlow
    and send it as `Authorization: Bearer <token>`. Tokens are website-scoped, so a token
    authenticates only for the website(s) you selected when you authorized it. The
    `website_id` query param must be one of the token's websites. You can omit it for
    single-website tokens, and it's required when the token grants multiple websites
    (`GET /api/v1/reports/websites` lists them).
    (ConvertFlow also accepts the legacy `Authorization: api_key=<key>` scheme until a
    website generates its first OAuth token. That scheme is not scope-restricted.)

    ### Permissions (scopes)
    OAuth tokens carry resource + read/write scopes that you choose at creation, and
    ConvertFlow enforces them on every request: `reports` (read analytics),
    `contacts:read`/`contacts:write`, `ctas:read`/`ctas:write`, `areas:read`, and
    `websites:read`. A request whose token lacks the required scope returns `403`.

    ## Reports
    These read-only endpoints report on funnel performance: website totals, campaigns, A/B
    experiments, variant/step/element funnel breakdowns, and the pre-generated weekly
    insights snapshot. Most reports endpoints accept a `timeframe` enum
    (default `last_30_days`) plus optional `range_start`/`range_end` (ISO 8601, required when
    `timeframe=custom`). Account-wide endpoints under `/api/v1/reports/account` aggregate
    every website bound to the token and do not require `website_id`.

    ConvertFlow stores metrics per day, so any custom range is exact, down to a single day.
    The single-subject reports (website, campaign, variant, step, element) also accept
    `group_by` (`day`, `week`, `month`, `quarter`, `year`) and return a zero-filled
    `timeseries` block alongside the totals, so a daily breakdown takes one request.

    ## MCP Server
    ConvertFlow also exposes this API as a remote MCP server for AI agents
    (`https://mcp.convertflow.co/mcp`). For the setup guide and tool reference, see
    [developers.convertflow.com/developers/mcp](https://developers.convertflow.com/developers/mcp).
paths:
  "/api/v1/areas":
    get:
      summary: List areas
      tags:
      - Areas
      description: Returns the website's areas (newest first).
      responses:
        '200':
          description: areas returned
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                    name:
                      type: string
                    website_id:
                      type: integer
                    created_at:
                      type: string
                      format: date-time
                    updated_at:
                      type: string
                      format: date-time
              example:
              - id: 0
                name: string
                website_id: 0
                created_at: '2017-07-21T17:32:28Z'
                updated_at: '2017-07-21T17:32:28Z'
        '401':
          description: missing or invalid credentials
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  code:
                    type: integer
                  message:
                    type: string
              example:
                status: string
                code: 0
                message: string
  "/api/v1/contacts":
    get:
      summary: List contacts
      tags:
      - Contacts
      description: Returns the website's contacts (paginated, 25 per page). Authenticates
        with a website-bound Bearer token, or the legacy api_key until migrated.
      parameters:
      - name: email
        in: query
        required: false
        schema:
          type: string
        description: Filter by exact email
      - name: id
        in: query
        required: false
        schema:
          type: integer
        description: Filter by contact id
      responses:
        '200':
          description: contacts found
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                    created_at:
                      type: string
                      format: date-time
                    updated_at:
                      type: string
                      format: date-time
                    website_id:
                      type: integer
                    visitor_token:
                      type: string
                      format: uuid
                    email:
                      type: string
                    name:
                      type: string
                    last_name:
                      type: string
                    phone:
                      type: string
                    city:
                      type: string
                    avatar_url:
                      type: string
                    company_name:
                      type: string
                    company_title:
                      type: string
                    url:
                      type: string
                    state:
                      type: string
                    address:
                      type: string
                    zip_code:
                      type: string
                    country:
                      type: string
                    source_url:
                      type: string
                    bio:
                      type: string
                    utm_source:
                      type: string
                    utm_medium:
                      type: string
                    utm_campaign:
                      type: string
                    utm_term:
                      type: string
                    utm_content:
                      type: string
                    referral_source:
                      type: string
                    first_visit:
                      type: string
                    privacy_consent:
                      type: string
                    marketing_consent:
                      type: string
                    sms_consent:
                      type: string
                    ip_address:
                      type: string
                    latest_score:
                      type: string
                    extra:
                      type: object
                      properties: {}
                    data:
                      type: object
                      properties: {}
                    tags:
                      type: string
                    link:
                      type: string
              example:
              - id: 0
                created_at: '2017-07-21T17:32:28Z'
                updated_at: '2017-07-21T17:32:28Z'
                website_id: 0
                visitor_token: 550e8400-e29b-41d4-a716-446655440000
                email: string
                name: string
                last_name: string
                phone: string
                city: string
                avatar_url: string
                company_name: string
                company_title: string
                url: string
                state: string
                address: string
                zip_code: string
                country: string
                source_url: string
                bio: string
                utm_source: string
                utm_medium: string
                utm_campaign: string
                utm_term: string
                utm_content: string
                referral_source: string
                first_visit: string
                privacy_consent: string
                marketing_consent: string
                sms_consent: string
                ip_address: string
                latest_score: string
                extra: {}
                data: {}
                tags: string
                link: string
        '404':
          description: no contacts match
          content:
            application/json:
              schema:
                type: object
                properties: {}
              example: {}
        '401':
          description: missing or invalid credentials
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  code:
                    type: integer
                  message:
                    type: string
              example:
                status: string
                code: 0
                message: string
    post:
      summary: Create or update a contact
      tags:
      - Contacts
      description: Upserts a contact by email/phone. At least one of email or phone
        is required; additional custom fields are accepted and stored on the contact.
      parameters: []
      responses:
        '200':
          description: contact created or synced
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  created_at:
                    type: string
                    format: date-time
                  updated_at:
                    type: string
                    format: date-time
                  website_id:
                    type: integer
                  visitor_token:
                    type: string
                  email:
                    type: string
                  name:
                    type: string
                  last_name:
                    type: string
                  phone:
                    type: string
                  city:
                    type: string
                  avatar_url:
                    type: string
                  company_name:
                    type: string
                  company_title:
                    type: string
                  url:
                    type: string
                  state:
                    type: string
                  address:
                    type: string
                  zip_code:
                    type: string
                  country:
                    type: string
                  source_url:
                    type: string
                  bio:
                    type: string
                  utm_source:
                    type: string
                  utm_medium:
                    type: string
                  utm_campaign:
                    type: string
                  utm_term:
                    type: string
                  utm_content:
                    type: string
                  referral_source:
                    type: string
                  first_visit:
                    type: string
                  privacy_consent:
                    type: string
                  marketing_consent:
                    type: string
                  sms_consent:
                    type: string
                  ip_address:
                    type: string
                  latest_score:
                    type: string
                  extra:
                    type: object
                    properties: {}
                  data:
                    type: object
                    properties: {}
                  tags:
                    type: string
                  link:
                    type: string
              example:
                id: 0
                created_at: '2017-07-21T17:32:28Z'
                updated_at: '2017-07-21T17:32:28Z'
                website_id: 0
                visitor_token: string
                email: string
                name: string
                last_name: string
                phone: string
                city: string
                avatar_url: string
                company_name: string
                company_title: string
                url: string
                state: string
                address: string
                zip_code: string
                country: string
                source_url: string
                bio: string
                utm_source: string
                utm_medium: string
                utm_campaign: string
                utm_term: string
                utm_content: string
                referral_source: string
                first_visit: string
                privacy_consent: string
                marketing_consent: string
                sms_consent: string
                ip_address: string
                latest_score: string
                extra: {}
                data: {}
                tags: string
                link: string
        '400':
          description: neither email nor phone provided
          content:
            application/json:
              schema:
                type: object
                properties: {}
              example: {}
        '401':
          description: missing or invalid credentials
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  code:
                    type: integer
                  message:
                    type: string
              example:
                status: string
                code: 0
                message: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                phone:
                  type: string
                first_name:
                  type: string
                last_name:
                  type: string
    delete:
      summary: Delete a contact by email
      tags:
      - Contacts
      parameters:
      - name: email
        in: query
        required: true
        schema:
          type: string
      responses:
        '200':
          description: contact deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
              example:
                message: string
        '401':
          description: missing or invalid credentials
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  code:
                    type: integer
                  message:
                    type: string
              example:
                status: string
                code: 0
                message: string
        '422':
          description: no matching contact for this website
          content:
            application/json:
              schema:
                type: object
                properties: {}
              example: {}
  "/api/v1/cta":
    get:
      summary: List campaigns
      tags:
      - Campaigns
      description: Returns the website's non-archived campaigns (newest first), each
        with its variants.
      responses:
        '200':
          description: campaigns returned
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                    website_id:
                      type: integer
                    name:
                      type: string
                    views:
                      type: integer
                    conversions:
                      type: integer
                    completions:
                      type: integer
                    conversion_rate:
                      type: string
                    completion_rate:
                      type: string
                    page_path:
                      type: string
                    cta_type:
                      type: string
                      description: Campaign format
                    test_type:
                      type: string
                    created_at:
                      type: string
                      format: date-time
                    updated_at:
                      type: string
                      format: date-time
                    variants:
                      type: array
                      items:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          variation:
                            type: string
                          percentage:
                            type: integer
                          created_at:
                            type: string
                            format: date-time
                          updated_at:
                            type: string
                            format: date-time
                          screenshot:
                            nullable: true
                          website_id:
                            type: integer
                          views:
                            type: integer
                          conversions:
                            type: integer
                          completions:
                            type: integer
                          conversion_rate:
                            type: string
                          completion_rate:
                            type: string
              example:
              - id: 0
                website_id: 0
                name: string
                views: 0
                conversions: 0
                completions: 0
                conversion_rate: string
                completion_rate: string
                page_path: string
                cta_type: string
                test_type: string
                created_at: '2017-07-21T17:32:28Z'
                updated_at: '2017-07-21T17:32:28Z'
                variants:
                - id: 0
                  name: string
                  variation: string
                  percentage: 0
                  created_at: '2017-07-21T17:32:28Z'
                  updated_at: '2017-07-21T17:32:28Z'
                  screenshot:
                  website_id: 0
                  views: 0
                  conversions: 0
                  completions: 0
                  conversion_rate: string
                  completion_rate: string
        '401':
          description: missing or invalid credentials
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  code:
                    type: integer
                  message:
                    type: string
              example:
                status: string
                code: 0
                message: string
  "/api/v1/reports/account/performance":
    get:
      summary: Account-wide website performance
      tags:
      - Reports
      description: Aggregate and per-website funnel metrics for every website bound
        to the token. Omit website_id to include all bound sites; pass website_id
        or website_ids to subset. Does not require website_id on multi-website tokens.
      parameters:
      - name: website_id
        in: query
        required: false
        schema:
          type: integer
        description: Optional. When set, limits the report to this bound website.
          Omit to aggregate every website bound to the token. Unbound ids return 404.
          Non-positive or non-numeric ids return 422 invalid_website_id.
      - name: timeframe
        in: query
        required: false
        schema:
          type: string
          enum:
          - today
          - this_week
          - this_month
          - this_quarter
          - this_year
          - last_24_hours
          - last_7_days
          - last_30_days
          - last_90_days
          - last_365_days
          - all_time
          - insights_week
          - custom
          default: last_30_days
      - name: range_start
        in: query
        required: false
        schema:
          type: string
          format: date
        description: Required when timeframe=custom (ISO 8601)
      - name: range_end
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: website_ids
        in: query
        required: false
        style: form
        explode: true
        schema:
          type: array
          items:
            type: integer
        description: Optional subset of bound website ids. Any id outside the token
          binding returns 404. Non-positive or non-numeric ids return 422 invalid_website_id.
      responses:
        '200':
          description: performance across bound websites
          content:
            application/json:
              schema:
                type: object
                properties:
                  report:
                    type: string
                  timeframe:
                    type: object
                    properties:
                      selected:
                        type: string
                      label:
                        type: string
                      range_start:
                        type: string
                        format: date-time
                      range_end:
                        type: string
                        format: date-time
                      previous_range_start:
                        type: string
                        format: date-time
                      previous_range_end:
                        type: string
                        format: date-time
                  data:
                    type: object
                    properties:
                      aggregate:
                        type: object
                        properties:
                          website_count:
                            type: integer
                          viewers:
                            type: number
                          conversions:
                            type: number
                          conversion_rate:
                            type: number
                          subscribes:
                            type: number
                          subscribe_rate:
                            type: number
                          orders:
                            type: number
                          order_rate:
                            type: number
                          revenue:
                            type: number
                          aov:
                            type: number
                      websites:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            viewers:
                              type: number
                            conversions:
                              type: number
                            conversion_rate:
                              type: number
                            conversions_change:
                              type: number
                            revenue_change:
                              type: number
                            subscribes:
                              type: number
                            orders:
                              type: number
                            revenue:
                              type: number
                            aov:
                              type: number
              example:
                report: string
                timeframe:
                  selected: string
                  label: string
                  range_start: '2017-07-21T17:32:28Z'
                  range_end: '2017-07-21T17:32:28Z'
                  previous_range_start: '2017-07-21T17:32:28Z'
                  previous_range_end: '2017-07-21T17:32:28Z'
                data:
                  aggregate:
                    website_count: 0
                    viewers: 0.0
                    conversions: 0.0
                    conversion_rate: 0.0
                    subscribes: 0.0
                    subscribe_rate: 0.0
                    orders: 0.0
                    order_rate: 0.0
                    revenue: 0.0
                    aov: 0.0
                  websites:
                  - id: 0
                    name: string
                    viewers: 0.0
                    conversions: 0.0
                    conversion_rate: 0.0
                    conversions_change: 0.0
                    revenue_change: 0.0
                    subscribes: 0.0
                    orders: 0.0
                    revenue: 0.0
                    aov: 0.0
        '404':
          description: website_ids includes an unbound website
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
              example:
                error: string
        '422':
          description: unknown timeframe
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
              example:
                error: string
                message: string
        '401':
          description: token not bound to any website
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  code:
                    type: integer
                  message:
                    type: string
              example:
                status: string
                code: 0
                message: string
        '403':
          description: token missing the reports scope
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  code:
                    type: integer
                  message:
                    type: string
              example:
                status: string
                code: 0
                message: string
  "/api/v1/reports/campaigns":
    get:
      summary: List campaigns with metrics
      tags:
      - Reports
      parameters:
      - name: website_id
        in: query
        required: false
        schema:
          type: integer
        description: Website id. Must be one of the token's websites. Optional for
          single-website tokens (derived from the binding); required when the token
          grants multiple websites (400 website_id_required otherwise).
      - name: timeframe
        in: query
        required: false
        schema:
          type: string
          enum:
          - today
          - this_week
          - this_month
          - this_quarter
          - this_year
          - last_24_hours
          - last_7_days
          - last_30_days
          - last_90_days
          - last_365_days
          - all_time
          - insights_week
          - custom
          default: last_30_days
      - name: range_start
        in: query
        required: false
        schema:
          type: string
          format: date
        description: Required when timeframe=custom (ISO 8601)
      - name: range_end
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: count_type
        in: query
        required: false
        schema:
          type: string
          enum:
          - distinct
          - total
          default: distinct
        description: Count mode for the funnel metrics (views, conversions, completions,
          subscribes, submissions). distinct = unique visitors via HyperLogLog (default);
          total = raw event count. Orders and revenue are always summed regardless.
          Ignored on timeframe=insights_week (the weekly snapshot stores distinct
          counts only). An unrecognized value returns 422 invalid_count_type.
      - name: previous_period
        in: query
        required: false
        schema:
          type: boolean
          default: false
        description: When true, each metrics block gains a nested `previous` object
          (same shape, for the immediately preceding period of equal length) and a
          `changes` object with the percent change per metric (null when the prior
          value is unavailable). The compared window is echoed as previous_range_start/previous_range_end
          in the timeframe block. No effect on timeframe=all_time (no prior period)
          or timeframe=insights_week.
      - name: page
        in: query
        required: false
        schema:
          type: integer
          default: 1
      - name: per_page
        in: query
        required: false
        schema:
          type: integer
          default: 25
          maximum: 50
      - name: sort
        in: query
        required: false
        schema:
          type: string
          enum:
          - created_at
          - published_at
          - views
          - conversions
          - completions
          - conversion_rate
          - completion_rate
          - revenue
          - aov
      - name: cta_type
        in: query
        required: false
        schema:
          type: string
        description: Filter by campaign format.
      - name: status
        in: query
        required: false
        schema:
          type: string
          enum:
          - live
          - archived
      responses:
        '200':
          description: count_type=total sums raw views
          content:
            application/json:
              schema:
                type: object
                properties:
                  report:
                    type: string
                  website:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      currency:
                        type: string
                  timeframe:
                    type: object
                    properties:
                      selected:
                        type: string
                      range_start:
                        type: string
                        format: date-time
                      range_end:
                        type: string
                        format: date-time
                      timezone:
                        type: string
                  data:
                    type: object
                    properties:
                      campaigns:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            cta_type:
                              type: string
                              description: Campaign format
                            status:
                              type: string
                            metrics:
                              type: object
                              properties:
                                views:
                                  type: integer
                                conversions:
                                  type: integer
                                completions:
                                  type: integer
                                submissions:
                                  type: integer
                                subscribes:
                                  type: integer
                                orders:
                                  type: integer
                                revenue:
                                  type: number
                                conversion_rate:
                                  type: number
                                completion_rate:
                                  type: number
                                subscribe_rate:
                                  type: number
                                order_rate:
                                  type: number
                                aov:
                                  type: number
                      pagination:
                        type: object
                        properties:
                          page:
                            type: integer
                          per_page:
                            type: integer
                          total_entries:
                            type: integer
                          total_pages:
                            type: integer
              example:
                report: string
                website:
                  id: 0
                  name: string
                  currency: string
                timeframe:
                  selected: string
                  range_start: '2017-07-21T17:32:28Z'
                  range_end: '2017-07-21T17:32:28Z'
                  timezone: string
                data:
                  campaigns:
                  - id: 0
                    name: string
                    cta_type: string
                    status: string
                    metrics:
                      views: 0
                      conversions: 0
                      completions: 0
                      submissions: 0
                      subscribes: 0
                      orders: 0
                      revenue: 0.0
                      conversion_rate: 0.0
                      completion_rate: 0.0
                      subscribe_rate: 0.0
                      order_rate: 0.0
                      aov: 0.0
                  pagination:
                    page: 0
                    per_page: 0
                    total_entries: 0
                    total_pages: 0
  "/api/v1/reports/campaigns/{id}":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: integer
    get:
      summary: Campaign performance + variants
      tags:
      - Reports
      parameters:
      - name: website_id
        in: query
        required: false
        schema:
          type: integer
        description: Website id. Must be one of the token's websites. Optional for
          single-website tokens (derived from the binding); required when the token
          grants multiple websites (400 website_id_required otherwise).
      - name: timeframe
        in: query
        required: false
        schema:
          type: string
          enum:
          - today
          - this_week
          - this_month
          - this_quarter
          - this_year
          - last_24_hours
          - last_7_days
          - last_30_days
          - last_90_days
          - last_365_days
          - all_time
          - insights_week
          - custom
          default: last_30_days
      - name: range_start
        in: query
        required: false
        schema:
          type: string
          format: date
        description: Required when timeframe=custom (ISO 8601)
      - name: range_end
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: count_type
        in: query
        required: false
        schema:
          type: string
          enum:
          - distinct
          - total
          default: distinct
        description: Count mode for the funnel metrics (views, conversions, completions,
          subscribes, submissions). distinct = unique visitors via HyperLogLog (default);
          total = raw event count. Orders and revenue are always summed regardless.
          Ignored on timeframe=insights_week (the weekly snapshot stores distinct
          counts only). An unrecognized value returns 422 invalid_count_type.
      - name: previous_period
        in: query
        required: false
        schema:
          type: boolean
          default: false
        description: When true, each metrics block gains a nested `previous` object
          (same shape, for the immediately preceding period of equal length) and a
          `changes` object with the percent change per metric (null when the prior
          value is unavailable). The compared window is echoed as previous_range_start/previous_range_end
          in the timeframe block. No effect on timeframe=all_time (no prior period)
          or timeframe=insights_week.
      - name: group_by
        in: query
        required: false
        schema:
          type: string
          enum:
          - day
          - week
          - month
          - quarter
          - year
        description: 'When set, the response gains a `timeseries` object alongside
          `metrics`: one point per bucket over the same window, each with date, views,
          conversions, completions, subscribes, submissions, orders and revenue (points
          carry submissions even where the metrics block does not). Buckets with no
          activity are returned as zeroes. Under the default count_type=distinct each
          bucket counts unique visitors within that bucket, so the points do not sum
          to the headline total (a visitor active on three days counts once overall
          and three times across the daily points); use count_type=total when the
          buckets must reconcile. An unrecognized value returns 422 invalid_group_by.
          On the website report the window may cover at most 92 days (campaign, variant,
          step and element reports take any range); a range that would exceed 400
          points is rejected too. Both return 422 range_too_wide.'
      responses:
        '200':
          description: campaign with variant breakdown
          content:
            application/json:
              schema:
                type: object
                properties:
                  report:
                    type: string
                  website:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      currency:
                        type: string
                  timeframe:
                    type: object
                    properties:
                      selected:
                        type: string
                      range_start:
                        type: string
                        format: date-time
                      range_end:
                        type: string
                        format: date-time
                      timezone:
                        type: string
                      previous_range_start:
                        type: string
                        format: date-time
                      previous_range_end:
                        type: string
                        format: date-time
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      cta_type:
                        type: string
                        description: Campaign format
                      status:
                        type: string
                      metrics:
                        type: object
                        properties:
                          views:
                            type: integer
                          conversions:
                            type: integer
                          completions:
                            type: integer
                          submissions:
                            type: integer
                          subscribes:
                            type: integer
                          orders:
                            type: integer
                          revenue:
                            type: number
                          conversion_rate:
                            type: number
                          completion_rate:
                            type: number
                          subscribe_rate:
                            type: number
                          order_rate:
                            type: number
                          aov:
                            type: number
                          previous:
                            type: object
                            properties:
                              views:
                                type: integer
                              conversions:
                                type: integer
                              completions:
                                type: integer
                              submissions:
                                type: integer
                              subscribes:
                                type: integer
                              orders:
                                type: integer
                              revenue:
                                type: number
                              conversion_rate:
                                type: number
                              completion_rate:
                                type: number
                              subscribe_rate:
                                type: number
                              order_rate:
                                type: number
                              aov:
                                type: number
                          changes:
                            type: object
                            properties:
                              views:
                                type: number
                              conversions:
                                type: number
                              completions:
                                nullable: true
                              submissions:
                                nullable: true
                              subscribes:
                                nullable: true
                              orders:
                                nullable: true
                              revenue:
                                nullable: true
                              conversion_rate:
                                type: number
                              completion_rate:
                                nullable: true
                              subscribe_rate:
                                nullable: true
                              order_rate:
                                nullable: true
                              aov:
                                nullable: true
                      timeseries:
                        type: object
                        properties:
                          group_by:
                            type: string
                          points:
                            type: array
                            items:
                              type: object
                              properties:
                                date:
                                  type: string
                                  format: date
                                views:
                                  type: integer
                                conversions:
                                  type: integer
                                completions:
                                  type: integer
                                subscribes:
                                  type: integer
                                submissions:
                                  type: integer
                                orders:
                                  type: integer
                                revenue:
                                  type: number
                      variants:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              nullable: true
                            variation:
                              type: string
                            traffic_percentage:
                              type: integer
                            metrics:
                              type: object
                              properties:
                                views:
                                  type: integer
                                conversions:
                                  type: integer
                                completions:
                                  type: integer
                                submissions:
                                  type: integer
                                subscribes:
                                  type: integer
                                orders:
                                  type: integer
                                revenue:
                                  type: number
                                conversion_rate:
                                  type: number
                                completion_rate:
                                  type: number
                                subscribe_rate:
                                  type: number
                                order_rate:
                                  type: number
                                aov:
                                  type: number
                                previous:
                                  type: object
                                  properties:
                                    views:
                                      type: integer
                                    conversions:
                                      type: integer
                                    completions:
                                      type: integer
                                    submissions:
                                      type: integer
                                    subscribes:
                                      type: integer
                                    orders:
                                      type: integer
                                    revenue:
                                      type: number
                                    conversion_rate:
                                      type: number
                                    completion_rate:
                                      type: number
                                    subscribe_rate:
                                      type: number
                                    order_rate:
                                      type: number
                                    aov:
                                      type: number
                                changes:
                                  type: object
                                  properties:
                                    views:
                                      type: number
                                    conversions:
                                      type: number
                                    completions:
                                      nullable: true
                                    submissions:
                                      nullable: true
                                    subscribes:
                                      nullable: true
                                    orders:
                                      nullable: true
                                    revenue:
                                      nullable: true
                                    conversion_rate:
                                      type: number
                                    completion_rate:
                                      nullable: true
                                    subscribe_rate:
                                      nullable: true
                                    order_rate:
                                      nullable: true
                                    aov:
                                      nullable: true
              example:
                report: string
                website:
                  id: 0
                  name: string
                  currency: string
                timeframe:
                  selected: string
                  range_start: '2017-07-21T17:32:28Z'
                  range_end: '2017-07-21T17:32:28Z'
                  timezone: string
                  previous_range_start: '2017-07-21T17:32:28Z'
                  previous_range_end: '2017-07-21T17:32:28Z'
                data:
                  id: 0
                  name: string
                  cta_type: string
                  status: string
                  metrics:
                    views: 0
                    conversions: 0
                    completions: 0
                    submissions: 0
                    subscribes: 0
                    orders: 0
                    revenue: 0.0
                    conversion_rate: 0.0
                    completion_rate: 0.0
                    subscribe_rate: 0.0
                    order_rate: 0.0
                    aov: 0.0
                    previous:
                      views: 0
                      conversions: 0
                      completions: 0
                      submissions: 0
                      subscribes: 0
                      orders: 0
                      revenue: 0.0
                      conversion_rate: 0.0
                      completion_rate: 0.0
                      subscribe_rate: 0.0
                      order_rate: 0.0
                      aov: 0.0
                    changes:
                      views: 0.0
                      conversions: 0.0
                      completions:
                      submissions:
                      subscribes:
                      orders:
                      revenue:
                      conversion_rate: 0.0
                      completion_rate:
                      subscribe_rate:
                      order_rate:
                      aov:
                  timeseries:
                    group_by: string
                    points:
                    - date: '2017-07-21'
                      views: 0
                      conversions: 0
                      completions: 0
                      subscribes: 0
                      submissions: 0
                      orders: 0
                      revenue: 0.0
                  variants:
                  - id: 0
                    name:
                    variation: string
                    traffic_percentage: 0
                    metrics:
                      views: 0
                      conversions: 0
                      completions: 0
                      submissions: 0
                      subscribes: 0
                      orders: 0
                      revenue: 0.0
                      conversion_rate: 0.0
                      completion_rate: 0.0
                      subscribe_rate: 0.0
                      order_rate: 0.0
                      aov: 0.0
        '422':
          description: 'validation error: invalid_timeframe, invalid_count_type, invalid_group_by
            or range_too_wide'
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
              example:
                error: string
                message: string
        '404':
          description: campaign not found on this website
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
              example:
                error: string
  "/api/v1/reports/elements/{id}":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: integer
    get:
      summary: Element performance + field/product breakdown
      tags:
      - Reports
      parameters:
      - name: website_id
        in: query
        required: false
        schema:
          type: integer
        description: Website id. Must be one of the token's websites. Optional for
          single-website tokens (derived from the binding); required when the token
          grants multiple websites (400 website_id_required otherwise).
      - name: timeframe
        in: query
        required: false
        schema:
          type: string
          enum:
          - today
          - this_week
          - this_month
          - this_quarter
          - this_year
          - last_24_hours
          - last_7_days
          - last_30_days
          - last_90_days
          - last_365_days
          - all_time
          - insights_week
          - custom
          default: last_30_days
      - name: range_start
        in: query
        required: false
        schema:
          type: string
          format: date
        description: Required when timeframe=custom (ISO 8601)
      - name: range_end
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: count_type
        in: query
        required: false
        schema:
          type: string
          enum:
          - distinct
          - total
          default: distinct
        description: Count mode for the funnel metrics (views, conversions, completions,
          subscribes, submissions). distinct = unique visitors via HyperLogLog (default);
          total = raw event count. Orders and revenue are always summed regardless.
          Ignored on timeframe=insights_week (the weekly snapshot stores distinct
          counts only). An unrecognized value returns 422 invalid_count_type.
      - name: previous_period
        in: query
        required: false
        schema:
          type: boolean
          default: false
        description: When true, each metrics block gains a nested `previous` object
          (same shape, for the immediately preceding period of equal length) and a
          `changes` object with the percent change per metric (null when the prior
          value is unavailable). The compared window is echoed as previous_range_start/previous_range_end
          in the timeframe block. No effect on timeframe=all_time (no prior period)
          or timeframe=insights_week.
      - name: group_by
        in: query
        required: false
        schema:
          type: string
          enum:
          - day
          - week
          - month
          - quarter
          - year
        description: 'When set, the response gains a `timeseries` object alongside
          `metrics`: one point per bucket over the same window, each with date, views,
          conversions, completions, subscribes, submissions, orders and revenue (points
          carry submissions even where the metrics block does not). Buckets with no
          activity are returned as zeroes. Under the default count_type=distinct each
          bucket counts unique visitors within that bucket, so the points do not sum
          to the headline total (a visitor active on three days counts once overall
          and three times across the daily points); use count_type=total when the
          buckets must reconcile. An unrecognized value returns 422 invalid_group_by.
          On the website report the window may cover at most 92 days (campaign, variant,
          step and element reports take any range); a range that would exceed 400
          points is rejected too. Both return 422 range_too_wide.'
      responses:
        '200':
          description: count_type=total sums raw views
          content:
            application/json:
              schema:
                type: object
                properties:
                  report:
                    type: string
                  website:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      currency:
                        type: string
                  timeframe:
                    type: object
                    properties:
                      selected:
                        type: string
                      range_start:
                        type: string
                        format: date-time
                      range_end:
                        type: string
                        format: date-time
                      timezone:
                        type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      element_type:
                        type: string
                      position:
                        type: integer
                      metrics:
                        type: object
                        properties:
                          views:
                            type: integer
                          conversions:
                            type: integer
                          completions:
                            type: integer
                          submissions:
                            type: integer
                          subscribes:
                            type: integer
                          orders:
                            type: integer
                          revenue:
                            type: number
                          conversion_rate:
                            type: number
                          completion_rate:
                            type: number
                          subscribe_rate:
                            type: number
                          order_rate:
                            type: number
                          aov:
                            type: number
                      timeseries:
                        type: object
                        properties:
                          group_by:
                            type: string
                          points:
                            type: array
                            items:
                              type: object
                              properties:
                                date:
                                  type: string
                                  format: date
                                views:
                                  type: integer
                                conversions:
                                  type: integer
                                completions:
                                  type: integer
                                subscribes:
                                  type: integer
                                submissions:
                                  type: integer
                                orders:
                                  type: integer
                                revenue:
                                  type: number
                      fields:
                        type: array
                        items: {}
                      products:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              nullable: true
                            selections:
                              type: integer
                            orders:
                              type: integer
                            revenue:
                              type: number
              example:
                report: string
                website:
                  id: 0
                  name: string
                  currency: string
                timeframe:
                  selected: string
                  range_start: '2017-07-21T17:32:28Z'
                  range_end: '2017-07-21T17:32:28Z'
                  timezone: string
                data:
                  id: 0
                  element_type: string
                  position: 0
                  metrics:
                    views: 0
                    conversions: 0
                    completions: 0
                    submissions: 0
                    subscribes: 0
                    orders: 0
                    revenue: 0.0
                    conversion_rate: 0.0
                    completion_rate: 0.0
                    subscribe_rate: 0.0
                    order_rate: 0.0
                    aov: 0.0
                  timeseries:
                    group_by: string
                    points:
                    - date: '2017-07-21'
                      views: 0
                      conversions: 0
                      completions: 0
                      subscribes: 0
                      submissions: 0
                      orders: 0
                      revenue: 0.0
                  fields: []
                  products:
                  - value:
                    selections: 0
                    orders: 0
                    revenue: 0.0
        '422':
          description: 'validation error: invalid_timeframe, invalid_count_type, invalid_group_by
            or range_too_wide'
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
              example:
                error: string
                message: string
  "/api/v1/reports/experiments":
    get:
      summary: Active experiments (live traffic-split variants)
      tags:
      - Reports
      parameters:
      - name: website_id
        in: query
        required: false
        schema:
          type: integer
        description: Website id. Must be one of the token's websites. Optional for
          single-website tokens (derived from the binding); required when the token
          grants multiple websites (400 website_id_required otherwise).
      - name: timeframe
        in: query
        required: false
        schema:
          type: string
          enum:
          - today
          - this_week
          - this_month
          - this_quarter
          - this_year
          - last_24_hours
          - last_7_days
          - last_30_days
          - last_90_days
          - last_365_days
          - all_time
          - insights_week
          - custom
          default: last_30_days
      - name: range_start
        in: query
        required: false
        schema:
          type: string
          format: date
        description: Required when timeframe=custom (ISO 8601)
      - name: range_end
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: count_type
        in: query
        required: false
        schema:
          type: string
          enum:
          - distinct
          - total
          default: distinct
        description: Count mode for the funnel metrics (views, conversions, completions,
          subscribes, submissions). distinct = unique visitors via HyperLogLog (default);
          total = raw event count. Orders and revenue are always summed regardless.
          Ignored on timeframe=insights_week (the weekly snapshot stores distinct
          counts only). An unrecognized value returns 422 invalid_count_type.
      - name: previous_period
        in: query
        required: false
        schema:
          type: boolean
          default: false
        description: When true, each metrics block gains a nested `previous` object
          (same shape, for the immediately preceding period of equal length) and a
          `changes` object with the percent change per metric (null when the prior
          value is unavailable). The compared window is echoed as previous_range_start/previous_range_end
          in the timeframe block. No effect on timeframe=all_time (no prior period)
          or timeframe=insights_week.
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          default: 25
          maximum: 50
      responses:
        '200':
          description: count_type=total sums raw variant views
          content:
            application/json:
              schema:
                type: object
                properties:
                  report:
                    type: string
                  website:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      currency:
                        type: string
                  timeframe:
                    type: object
                    properties:
                      selected:
                        type: string
                      range_start:
                        type: string
                        format: date-time
                      range_end:
                        type: string
                        format: date-time
                      timezone:
                        type: string
                  data:
                    type: object
                    properties:
                      experiments:
                        type: array
                        items:
                          type: object
                          properties:
                            campaign_id:
                              type: integer
                            campaign_name:
                              type: string
                            cta_type:
                              type: string
                              description: Campaign format
                            variants:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  name:
                                    nullable: true
                                  variation:
                                    type: string
                                  traffic_percentage:
                                    type: integer
                                  metrics:
                                    type: object
                                    properties:
                                      views:
                                        type: integer
                                      conversions:
                                        type: integer
                                      completions:
                                        type: integer
                                      submissions:
                                        type: integer
                                      subscribes:
                                        type: integer
                                      orders:
                                        type: integer
                                      revenue:
                                        type: number
                                      conversion_rate:
                                        type: number
                                      completion_rate:
                                        type: number
                                      subscribe_rate:
                                        type: number
                                      order_rate:
                                        type: number
                                      aov:
                                        type: number
              example:
                report: string
                website:
                  id: 0
                  name: string
                  currency: string
                timeframe:
                  selected: string
                  range_start: '2017-07-21T17:32:28Z'
                  range_end: '2017-07-21T17:32:28Z'
                  timezone: string
                data:
                  experiments:
                  - campaign_id: 0
                    campaign_name: string
                    cta_type: string
                    variants:
                    - id: 0
                      name:
                      variation: string
                      traffic_percentage: 0
                      metrics:
                        views: 0
                        conversions: 0
                        completions: 0
                        submissions: 0
                        subscribes: 0
                        orders: 0
                        revenue: 0.0
                        conversion_rate: 0.0
                        completion_rate: 0.0
                        subscribe_rate: 0.0
                        order_rate: 0.0
                        aov: 0.0
  "/api/v1/reports/steps/{id}":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: integer
    get:
      summary: Step funnel + elements
      tags:
      - Reports
      parameters:
      - name: website_id
        in: query
        required: false
        schema:
          type: integer
        description: Website id. Must be one of the token's websites. Optional for
          single-website tokens (derived from the binding); required when the token
          grants multiple websites (400 website_id_required otherwise).
      - name: timeframe
        in: query
        required: false
        schema:
          type: string
          enum:
          - today
          - this_week
          - this_month
          - this_quarter
          - this_year
          - last_24_hours
          - last_7_days
          - last_30_days
          - last_90_days
          - last_365_days
          - all_time
          - insights_week
          - custom
          default: last_30_days
      - name: range_start
        in: query
        required: false
        schema:
          type: string
          format: date
        description: Required when timeframe=custom (ISO 8601)
      - name: range_end
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: count_type
        in: query
        required: false
        schema:
          type: string
          enum:
          - distinct
          - total
          default: distinct
        description: Count mode for the funnel metrics (views, conversions, completions,
          subscribes, submissions). distinct = unique visitors via HyperLogLog (default);
          total = raw event count. Orders and revenue are always summed regardless.
          Ignored on timeframe=insights_week (the weekly snapshot stores distinct
          counts only). An unrecognized value returns 422 invalid_count_type.
      - name: previous_period
        in: query
        required: false
        schema:
          type: boolean
          default: false
        description: When true, each metrics block gains a nested `previous` object
          (same shape, for the immediately preceding period of equal length) and a
          `changes` object with the percent change per metric (null when the prior
          value is unavailable). The compared window is echoed as previous_range_start/previous_range_end
          in the timeframe block. No effect on timeframe=all_time (no prior period)
          or timeframe=insights_week.
      - name: group_by
        in: query
        required: false
        schema:
          type: string
          enum:
          - day
          - week
          - month
          - quarter
          - year
        description: 'When set, the response gains a `timeseries` object alongside
          `metrics`: one point per bucket over the same window, each with date, views,
          conversions, completions, subscribes, submissions, orders and revenue (points
          carry submissions even where the metrics block does not). Buckets with no
          activity are returned as zeroes. Under the default count_type=distinct each
          bucket counts unique visitors within that bucket, so the points do not sum
          to the headline total (a visitor active on three days counts once overall
          and three times across the daily points); use count_type=total when the
          buckets must reconcile. An unrecognized value returns 422 invalid_group_by.
          On the website report the window may cover at most 92 days (campaign, variant,
          step and element reports take any range); a range that would exceed 400
          points is rejected too. Both return 422 range_too_wide.'
      responses:
        '200':
          description: count_type=total sums raw views
          content:
            application/json:
              schema:
                type: object
                properties:
                  report:
                    type: string
                  website:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      currency:
                        type: string
                  timeframe:
                    type: object
                    properties:
                      selected:
                        type: string
                      range_start:
                        type: string
                        format: date-time
                      range_end:
                        type: string
                        format: date-time
                      timezone:
                        type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      position:
                        type: integer
                      metrics:
                        type: object
                        properties:
                          views:
                            type: integer
                          conversions:
                            type: integer
                          completions:
                            type: integer
                          submissions:
                            type: integer
                          subscribes:
                            type: integer
                          orders:
                            type: integer
                          revenue:
                            type: number
                          conversion_rate:
                            type: number
                          completion_rate:
                            type: number
                          subscribe_rate:
                            type: number
                          order_rate:
                            type: number
                          aov:
                            type: number
                      timeseries:
                        type: object
                        properties:
                          group_by:
                            type: string
                          points:
                            type: array
                            items:
                              type: object
                              properties:
                                date:
                                  type: string
                                  format: date
                                views:
                                  type: integer
                                conversions:
                                  type: integer
                                completions:
                                  type: integer
                                subscribes:
                                  type: integer
                                submissions:
                                  type: integer
                                orders:
                                  type: integer
                                revenue:
                                  type: number
                      elements:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            element_type:
                              type: string
                            position:
                              type: integer
                            metrics:
                              type: object
                              properties:
                                views:
                                  type: integer
                                conversions:
                                  type: integer
                                completions:
                                  type: integer
                                submissions:
                                  type: integer
                                subscribes:
                                  type: integer
                                orders:
                                  type: integer
                                revenue:
                                  type: number
                                conversion_rate:
                                  type: number
                                completion_rate:
                                  type: number
                                subscribe_rate:
                                  type: number
                                order_rate:
                                  type: number
                                aov:
                                  type: number
              example:
                report: string
                website:
                  id: 0
                  name: string
                  currency: string
                timeframe:
                  selected: string
                  range_start: '2017-07-21T17:32:28Z'
                  range_end: '2017-07-21T17:32:28Z'
                  timezone: string
                data:
                  id: 0
                  position: 0
                  metrics:
                    views: 0
                    conversions: 0
                    completions: 0
                    submissions: 0
                    subscribes: 0
                    orders: 0
                    revenue: 0.0
                    conversion_rate: 0.0
                    completion_rate: 0.0
                    subscribe_rate: 0.0
                    order_rate: 0.0
                    aov: 0.0
                  timeseries:
                    group_by: string
                    points:
                    - date: '2017-07-21'
                      views: 0
                      conversions: 0
                      completions: 0
                      subscribes: 0
                      submissions: 0
                      orders: 0
                      revenue: 0.0
                  elements:
                  - id: 0
                    element_type: string
                    position: 0
                    metrics:
                      views: 0
                      conversions: 0
                      completions: 0
                      submissions: 0
                      subscribes: 0
                      orders: 0
                      revenue: 0.0
                      conversion_rate: 0.0
                      completion_rate: 0.0
                      subscribe_rate: 0.0
                      order_rate: 0.0
                      aov: 0.0
        '422':
          description: 'validation error: invalid_timeframe, invalid_count_type, invalid_group_by
            or range_too_wide'
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
              example:
                error: string
                message: string
  "/api/v1/reports/variants/{id}":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: integer
    get:
      summary: Variant funnel + steps
      tags:
      - Reports
      parameters:
      - name: website_id
        in: query
        required: false
        schema:
          type: integer
        description: Website id. Must be one of the token's websites. Optional for
          single-website tokens (derived from the binding); required when the token
          grants multiple websites (400 website_id_required otherwise).
      - name: timeframe
        in: query
        required: false
        schema:
          type: string
          enum:
          - today
          - this_week
          - this_month
          - this_quarter
          - this_year
          - last_24_hours
          - last_7_days
          - last_30_days
          - last_90_days
          - last_365_days
          - all_time
          - insights_week
          - custom
          default: last_30_days
      - name: range_start
        in: query
        required: false
        schema:
          type: string
          format: date
        description: Required when timeframe=custom (ISO 8601)
      - name: range_end
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: count_type
        in: query
        required: false
        schema:
          type: string
          enum:
          - distinct
          - total
          default: distinct
        description: Count mode for the funnel metrics (views, conversions, completions,
          subscribes, submissions). distinct = unique visitors via HyperLogLog (default);
          total = raw event count. Orders and revenue are always summed regardless.
          Ignored on timeframe=insights_week (the weekly snapshot stores distinct
          counts only). An unrecognized value returns 422 invalid_count_type.
      - name: previous_period
        in: query
        required: false
        schema:
          type: boolean
          default: false
        description: When true, each metrics block gains a nested `previous` object
          (same shape, for the immediately preceding period of equal length) and a
          `changes` object with the percent change per metric (null when the prior
          value is unavailable). The compared window is echoed as previous_range_start/previous_range_end
          in the timeframe block. No effect on timeframe=all_time (no prior period)
          or timeframe=insights_week.
      - name: group_by
        in: query
        required: false
        schema:
          type: string
          enum:
          - day
          - week
          - month
          - quarter
          - year
        description: 'When set, the response gains a `timeseries` object alongside
          `metrics`: one point per bucket over the same window, each with date, views,
          conversions, completions, subscribes, submissions, orders and revenue (points
          carry submissions even where the metrics block does not). Buckets with no
          activity are returned as zeroes. Under the default count_type=distinct each
          bucket counts unique visitors within that bucket, so the points do not sum
          to the headline total (a visitor active on three days counts once overall
          and three times across the daily points); use count_type=total when the
          buckets must reconcile. An unrecognized value returns 422 invalid_group_by.
          On the website report the window may cover at most 92 days (campaign, variant,
          step and element reports take any range); a range that would exceed 400
          points is rejected too. Both return 422 range_too_wide.'
      responses:
        '200':
          description: count_type=total sums raw events
          content:
            application/json:
              schema:
                type: object
                properties:
                  report:
                    type: string
                  website:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      currency:
                        type: string
                  timeframe:
                    type: object
                    properties:
                      selected:
                        type: string
                      range_start:
                        type: string
                        format: date-time
                      range_end:
                        type: string
                        format: date-time
                      timezone:
                        type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        nullable: true
                      variation:
                        type: string
                      traffic_percentage:
                        type: integer
                      metrics:
                        type: object
                        properties:
                          views:
                            type: integer
                          conversions:
                            type: integer
                          completions:
                            type: integer
                          submissions:
                            type: integer
                          subscribes:
                            type: integer
                          orders:
                            type: integer
                          revenue:
                            type: number
                          conversion_rate:
                            type: number
                          completion_rate:
                            type: number
                          subscribe_rate:
                            type: number
                          order_rate:
                            type: number
                          aov:
                            type: number
                      timeseries:
                        type: object
                        properties:
                          group_by:
                            type: string
                          points:
                            type: array
                            items:
                              type: object
                              properties:
                                date:
                                  type: string
                                  format: date
                                views:
                                  type: integer
                                conversions:
                                  type: integer
                                completions:
                                  type: integer
                                subscribes:
                                  type: integer
                                submissions:
                                  type: integer
                                orders:
                                  type: integer
                                revenue:
                                  type: number
                      funnel_steps:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            position:
                              type: integer
                            metrics:
                              type: object
                              properties:
                                views:
                                  type: integer
                                conversions:
                                  type: integer
                                completions:
                                  type: integer
                                submissions:
                                  type: integer
                                subscribes:
                                  type: integer
                                orders:
                                  type: integer
                                revenue:
                                  type: number
                                conversion_rate:
                                  type: number
                                completion_rate:
                                  type: number
                                subscribe_rate:
                                  type: number
                                order_rate:
                                  type: number
                                aov:
                                  type: number
              example:
                report: string
                website:
                  id: 0
                  name: string
                  currency: string
                timeframe:
                  selected: string
                  range_start: '2017-07-21T17:32:28Z'
                  range_end: '2017-07-21T17:32:28Z'
                  timezone: string
                data:
                  id: 0
                  name:
                  variation: string
                  traffic_percentage: 0
                  metrics:
                    views: 0
                    conversions: 0
                    completions: 0
                    submissions: 0
                    subscribes: 0
                    orders: 0
                    revenue: 0.0
                    conversion_rate: 0.0
                    completion_rate: 0.0
                    subscribe_rate: 0.0
                    order_rate: 0.0
                    aov: 0.0
                  timeseries:
                    group_by: string
                    points:
                    - date: '2017-07-21'
                      views: 0
                      conversions: 0
                      completions: 0
                      subscribes: 0
                      submissions: 0
                      orders: 0
                      revenue: 0.0
                  funnel_steps:
                  - id: 0
                    position: 0
                    metrics:
                      views: 0
                      conversions: 0
                      completions: 0
                      submissions: 0
                      subscribes: 0
                      orders: 0
                      revenue: 0.0
                      conversion_rate: 0.0
                      completion_rate: 0.0
                      subscribe_rate: 0.0
                      order_rate: 0.0
                      aov: 0.0
        '422':
          description: 'validation error: invalid_timeframe, invalid_count_type, invalid_group_by
            or range_too_wide'
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
              example:
                error: string
                message: string
        '404':
          description: variant not found on this website
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
              example:
                error: string
  "/api/v1/reports/website":
    get:
      summary: Website performance
      tags:
      - Reports
      parameters:
      - name: website_id
        in: query
        required: false
        schema:
          type: integer
        description: Website id. Must be one of the token's websites. Optional for
          single-website tokens (derived from the binding); required when the token
          grants multiple websites (400 website_id_required otherwise).
      - name: timeframe
        in: query
        required: false
        schema:
          type: string
          enum:
          - today
          - this_week
          - this_month
          - this_quarter
          - this_year
          - last_24_hours
          - last_7_days
          - last_30_days
          - last_90_days
          - last_365_days
          - all_time
          - insights_week
          - custom
          default: last_30_days
      - name: range_start
        in: query
        required: false
        schema:
          type: string
          format: date
        description: Required when timeframe=custom (ISO 8601)
      - name: range_end
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: count_type
        in: query
        required: false
        schema:
          type: string
          enum:
          - distinct
          - total
          default: distinct
        description: Count mode for the funnel metrics (views, conversions, completions,
          subscribes, submissions). distinct = unique visitors via HyperLogLog (default);
          total = raw event count. Orders and revenue are always summed regardless.
          Ignored on timeframe=insights_week (the weekly snapshot stores distinct
          counts only). An unrecognized value returns 422 invalid_count_type.
      - name: previous_period
        in: query
        required: false
        schema:
          type: boolean
          default: false
        description: When true, each metrics block gains a nested `previous` object
          (same shape, for the immediately preceding period of equal length) and a
          `changes` object with the percent change per metric (null when the prior
          value is unavailable). The compared window is echoed as previous_range_start/previous_range_end
          in the timeframe block. No effect on timeframe=all_time (no prior period)
          or timeframe=insights_week.
      - name: group_by
        in: query
        required: false
        schema:
          type: string
          enum:
          - day
          - week
          - month
          - quarter
          - year
        description: 'When set, the response gains a `timeseries` object alongside
          `metrics`: one point per bucket over the same window, each with date, views,
          conversions, completions, subscribes, submissions, orders and revenue (points
          carry submissions even where the metrics block does not). Buckets with no
          activity are returned as zeroes. Under the default count_type=distinct each
          bucket counts unique visitors within that bucket, so the points do not sum
          to the headline total (a visitor active on three days counts once overall
          and three times across the daily points); use count_type=total when the
          buckets must reconcile. An unrecognized value returns 422 invalid_group_by.
          On the website report the window may cover at most 92 days (campaign, variant,
          step and element reports take any range); a range that would exceed 400
          points is rejected too. Both return 422 range_too_wide.'
      responses:
        '200':
          description: count_type=total sums raw views
          content:
            application/json:
              schema:
                type: object
                properties:
                  report:
                    type: string
                  website:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      currency:
                        type: string
                  timeframe:
                    type: object
                    properties:
                      selected:
                        type: string
                      range_start:
                        type: string
                        format: date-time
                      range_end:
                        type: string
                        format: date-time
                      timezone:
                        type: string
                      previous_range_start:
                        type: string
                        format: date-time
                      previous_range_end:
                        type: string
                        format: date-time
                  data:
                    type: object
                    properties:
                      metrics:
                        type: object
                        properties:
                          views:
                            type: integer
                          conversions:
                            type: integer
                          completions:
                            type: integer
                          subscribes:
                            type: integer
                          orders:
                            type: integer
                          revenue:
                            type: number
                          conversion_rate:
                            type: number
                          completion_rate:
                            type: number
                          subscribe_rate:
                            type: number
                          order_rate:
                            type: number
                          aov:
                            type: number
                          previous:
                            type: object
                            properties:
                              views:
                                type: integer
                              conversions:
                                type: integer
                              completions:
                                type: integer
                              subscribes:
                                type: integer
                              orders:
                                type: integer
                              revenue:
                                type: number
                              conversion_rate:
                                type: number
                              completion_rate:
                                type: number
                              subscribe_rate:
                                type: number
                              order_rate:
                                type: number
                              aov:
                                type: number
                          changes:
                            type: object
                            properties:
                              views:
                                type: number
                              conversions:
                                nullable: true
                              completions:
                                nullable: true
                              subscribes:
                                nullable: true
                              orders:
                                nullable: true
                              revenue:
                                nullable: true
                              conversion_rate:
                                nullable: true
                              completion_rate:
                                nullable: true
                              subscribe_rate:
                                nullable: true
                              order_rate:
                                nullable: true
                              aov:
                                nullable: true
                      timeseries:
                        type: object
                        properties:
                          group_by:
                            type: string
                          points:
                            type: array
                            items:
                              type: object
                              properties:
                                date:
                                  type: string
                                  format: date
                                views:
                                  type: integer
                                conversions:
                                  type: integer
                                completions:
                                  type: integer
                                subscribes:
                                  type: integer
                                submissions:
                                  type: integer
                                orders:
                                  type: integer
                                revenue:
                                  type: number
              example:
                report: string
                website:
                  id: 0
                  name: string
                  currency: string
                timeframe:
                  selected: string
                  range_start: '2017-07-21T17:32:28Z'
                  range_end: '2017-07-21T17:32:28Z'
                  timezone: string
                  previous_range_start: '2017-07-21T17:32:28Z'
                  previous_range_end: '2017-07-21T17:32:28Z'
                data:
                  metrics:
                    views: 0
                    conversions: 0
                    completions: 0
                    subscribes: 0
                    orders: 0
                    revenue: 0.0
                    conversion_rate: 0.0
                    completion_rate: 0.0
                    subscribe_rate: 0.0
                    order_rate: 0.0
                    aov: 0.0
                    previous:
                      views: 0
                      conversions: 0
                      completions: 0
                      subscribes: 0
                      orders: 0
                      revenue: 0.0
                      conversion_rate: 0.0
                      completion_rate: 0.0
                      subscribe_rate: 0.0
                      order_rate: 0.0
                      aov: 0.0
                    changes:
                      views: 0.0
                      conversions:
                      completions:
                      subscribes:
                      orders:
                      revenue:
                      conversion_rate:
                      completion_rate:
                      subscribe_rate:
                      order_rate:
                      aov:
                  timeseries:
                    group_by: string
                    points:
                    - date: '2017-07-21'
                      views: 0
                      conversions: 0
                      completions: 0
                      subscribes: 0
                      submissions: 0
                      orders: 0
                      revenue: 0.0
        '422':
          description: 'validation error: invalid_timeframe, invalid_count_type, invalid_group_by
            or range_too_wide'
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
              example:
                error: string
                message: string
        '401':
          description: token not bound to a website (client must reauthorize and pick
            one)
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  code:
                    type: integer
                  message:
                    type: string
              example:
                status: string
                code: 0
                message: string
        '403':
          description: token missing the reports scope
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  code:
                    type: integer
                  message:
                    type: string
              example:
                status: string
                code: 0
                message: string
        '404':
          description: website_id outside the bound list
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
              example:
                error: string
        '400':
          description: website_id omitted on a multi-website token
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
              example:
                error: string
                message: string
  "/api/v1/reports/website/insights":
    get:
      summary: Latest weekly insights snapshot
      tags:
      - Reports
      parameters:
      - name: website_id
        in: query
        required: false
        schema:
          type: integer
        description: Website id. Must be one of the token's websites. Optional for
          single-website tokens (derived from the binding); required when the token
          grants multiple websites (400 website_id_required otherwise).
      responses:
        '200':
          description: pre-generated weekly snapshot
          content:
            application/json:
              schema:
                type: object
                properties:
                  report:
                    type: string
                  website:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      currency:
                        type: string
                  data:
                    type: object
                    properties:
                      week:
                        type: string
                        format: date
                      performance_snapshot:
                        type: object
                        properties:
                          performance:
                            type: object
                            properties:
                              revenue:
                                type: number
                              viewers:
                                type: integer
                      ai_recommendations:
                        type: object
                        properties:
                          items:
                            type: array
                            items:
                              type: string
              example:
                report: string
                website:
                  id: 0
                  name: string
                  currency: string
                data:
                  week: '2017-07-21'
                  performance_snapshot:
                    performance:
                      revenue: 0.0
                      viewers: 0
                  ai_recommendations:
                    items:
                    - string
        '401':
          description: missing or invalid bearer token
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  code:
                    type: integer
                  message:
                    type: string
              example:
                status: string
                code: 0
                message: string
        '403':
          description: token missing the reports scope
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  code:
                    type: integer
                  message:
                    type: string
              example:
                status: string
                code: 0
                message: string
        '400':
          description: website_id omitted on a multi-website token
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
              example:
                error: string
                message: string
        '404':
          description: no generated snapshot yet (generation enqueued for a later
            retry), or website_id outside the token binding
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
              example:
                error: string
  "/api/v1/reports/websites":
    get:
      summary: Websites the token grants access to
      tags:
      - Reports
      description: Lists the websites bound to the access token. Use the returned
        ids as the website_id query param on the other reports endpoints.
      responses:
        '200':
          description: the websites bound to the token
          content:
            application/json:
              schema:
                type: object
                properties:
                  websites:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        account_id:
                          type: integer
                        account_name:
                          type: string
                        created_at:
                          type: string
                          format: date-time
              example:
                websites:
                - id: 0
                  name: string
                  account_id: 0
                  account_name: string
                  created_at: '2017-07-21T17:32:28Z'
        '401':
          description: token not bound to any website
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  code:
                    type: integer
                  message:
                    type: string
              example:
                status: string
                code: 0
                message: string
        '403':
          description: token missing the reports scope
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  code:
                    type: integer
                  message:
                    type: string
              example:
                status: string
                code: 0
                message: string
  "/api/v1/websites":
    get:
      summary: Get the authenticated website
      tags:
      - Website
      description: Returns the website the credential is bound to. The `name` field
        is the website root domain name (e.g. example.com).
      responses:
        '200':
          description: website returned
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  name:
                    type: string
                    description: Root domain name for the website (e.g. example.com).
                  user_id:
                    nullable: true
                  created_at:
                    type: string
                    format: date-time
                  updated_at:
                    type: string
                    format: date-time
                  url:
                    nullable: true
                  listener:
                    type: boolean
                  published:
                    nullable: true
                  visitors_count:
                    nullable: true
                  active:
                    type: boolean
                  account_id:
                    type: integer
                  screenshot:
                    nullable: true
                  data:
                    type: object
                    properties:
                      form-tracking:
                        type: string
                      last_published:
                        type: string
                      url-identification:
                        type: string
                      google-analytics-track:
                        type: string
                  script_type:
                    type: string
                  test:
                    type: boolean
                  blacklisted:
                    type: boolean
                  brand:
                    type: string
                  api_key:
                    type: string
                  powered_by:
                    type: boolean
                  sub_domain:
                    type: string
                  archived:
                    type: boolean
                  premium:
                    type: boolean
                  conversions:
                    type: integer
                  completions:
                    type: integer
                  plan_type:
                    type: string
                  support:
                    type: boolean
                  context:
                    nullable: true
                  research:
                    nullable: true
                  context_last_updated:
                    nullable: true
              example:
                id: 0
                name: string
                user_id:
                created_at: '2017-07-21T17:32:28Z'
                updated_at: '2017-07-21T17:32:28Z'
                url:
                listener: true
                published:
                visitors_count:
                active: true
                account_id: 0
                screenshot:
                data:
                  form-tracking: string
                  last_published: string
                  url-identification: string
                  google-analytics-track: string
                script_type: string
                test: true
                blacklisted: true
                brand: string
                api_key: string
                powered_by: true
                sub_domain: string
                archived: true
                premium: true
                conversions: 0
                completions: 0
                plan_type: string
                support: true
                context:
                research:
                context_last_updated:
        '401':
          description: missing or invalid credentials
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  code:
                    type: integer
                  message:
                    type: string
              example:
                status: string
                code: 0
                message: string
servers:
- url: https://app.convertflow.co
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: opaque
      description: 'Paste a Personal Access Token (from a website''s API tokens page)
        or any ConvertFlow-issued OAuth token. Sent as `Authorization: Bearer <token>`.'
security:
- bearerAuth: []
