> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fluid.app/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> For new direct REST integrations, use the v2026-04 surfaces. The @fluid-app FairShare SDK continues to use its own published public-v2025-06 contract.
> Authenticate with the header Authorization: Bearer <token>; public storefront read endpoints require no auth.
> Lists use cursor pagination via the page[cursor] and page[limit] query params; follow meta.pagination.next_cursor until it is null.
> When the same operation exists on more than one surface, use the newest: dated API versions are newer than unversioned ones, and later dates win (v2026-04 > v2025-06 > unversioned v0/v1.1). Fall back to a legacy or unversioned operation only when no newer versioned equivalent exists — the company-v0 notes below list the known superseded operations. /api/company/v1 and /api/v1/... paths are documented in no spec here and must never be used (/api/v1.1/... is distinct and documented in company-v0). Use page/per_page offset pagination only where a spec documents it — in practice the unversioned company-v0 admin surface; every versioned surface uses cursor pagination.
> The OpenAPI specs under api-reference/ are the authoritative contracts; prefer them over prose when in doubt. api-reference/storefront-v2026-04.yaml covers the v2026-04 storefront surface (/api/v202604/... paths); api-reference/auth-v0.yaml covers the unversioned auth surface (/api/... paths — authentication, MFA, social auth, and token exchange); api-reference/checkout-v2026-04.yaml covers the v2026-04 checkout surface (/api/checkout/v2026-04/... paths — carts, cart auth, discounts, items, subscriptions, orders, enrollments, and store config); api-reference/public-v2025-06.yaml covers the Public SDK surface used by the @fluid-app FairShare SDK, including its parallel cart lifecycle, browser integrations, versioned payment callbacks, unversioned public utilities, and the cart price-override operation; api-reference/payment-v2026-04.yaml covers the v2026-04 payment gateway admin surface (/api/payment/v2026-04/... paths, bearer-authenticated — gateway CRUD, gateway purchase/authorize/$0-verify, transaction list/show and capture/void/credit, and merchant payment configuration); api-reference/payments-v2026-04.yaml covers the v2026-04 cart payment surface (/api/payments/v2026-04/carts/{cart_token}/... paths, authenticated by the cart token in the path with no bearer — payment-method selection, VGS card tokenization, 3D Secure verification, and PayPal/Braintree/Klarna/Apple Pay flows); api-reference/commerce-v2026-04.yaml covers the v2026-04 commerce order-editing surface (/api/v202604/orders/{order_id}/edits paths, bearer-authenticated — post-checkout order edits that atomically insert items and add adjustments/discounts, with an optional dry-run preview); api-reference/webhooks-v0.yaml covers the unversioned webhooks surface (/api/... paths — webhook registration, delivery payloads, callback registrations, company events, and webhook/callback schemas); api-reference/company-v0.yaml covers the legacy unversioned company admin surface (/api/... paths, bearer-authenticated — company settings and management, customers, users, roles, subscription plans, subscription bundles, subscriptions, media, pages, catch-ups, inventory levels, domains, agreements, and admin order actions). company-v0 caveats: it is the legacy v0 admin contract and its lists use flat page/per_page offset pagination, which is expected there despite the general cursor-pagination rule; where an operation exists in both company-v0 and a versioned spec, prefer the versioned spec — the subscriptions lifecycle (list/create/show/update, cancel, pause, reactivate, resume, retry, skip, failed-cycle-waiver, discounts) and subscription bundles are superseded by checkout-v2026-04, and company pages/media CRUD plus the public pages, categories, products, and media list endpoints are superseded by storefront-v2026-04. Subscription plan management (/api/subscription_plans, resource-wrapped {"subscription_plan": {...}} bodies) exists only in company-v0.
> Successful responses wrap the resource payload alongside a top-level integer status and a meta object.

# Get traffic by rep

> Returns the traffic a store's field of reps drove for a named reporting
period — the leaderboard behind the Reps tab and the two traffic tiles
above it.

A visit is credited to a rep by identity rather than by channel: it
carries the rep's attribution_member_id, or a share_id whose share
belongs to them, or both. Where both are present and disagree, the
stamped member wins. Identity has been recorded since long before the
channel column existed, so this reaches back further than the
channel-keyed figures on the Sources tab, and the two will not agree
over a long window.

visitor_share and the ranked rows come from that one filter, so the tile
and the leaderboard beneath it cannot disagree. Its denominator is every
visitor the store saw over the requested window and is deliberately not
narrowed to the first rep-driven visit: months before the field drove
anything held no rep traffic, and dilution is the answer rather than a
distortion.

Rows are ranked by distinct visitors descending, ties broken on the
rep's name, and cut to a top N. Because one visitor can be sent by two
reps, the rows' visitors need not sum to total_visitors and must not be
rendered as a share of a whole. Reps the merchant hid from leaderboards
are omitted from the rows while their traffic still counts toward
active_reps and visitor_share, and a rep whose member record has since
been deleted still ranks and is still named.

Each row also names the resource that drew the most of that rep's
traffic, or null when none did. That column is read from the
per-resource rollups rather than from the events, so it answers only for
traffic that landed on a tracked resource — about half of rep traffic,
and a different half per store. A null there is a rep whose traffic
never touched one, not a gap in their numbers.

unattributed is not a rep. It folds the rep-classified traffic that
names nobody — an admin-owned share has no member — so the rows plus the
remainder reconcile with visitor_share. It carries no member_id and no
name, and is served beside the rows rather than among them.




## OpenAPI

````yaml /api-reference/company-v0.yaml get /api/analytics/traffic/reps
openapi: 3.1.0
info:
  title: Fluid Company API
  version: v0
  contact:
    email: support@fluid.app
  license:
    name: Proprietary
    identifier: LicenseRef-Proprietary
servers:
  - url: https://api.fluid.app
  - url: https://{company}.fluid.app
    description: Production server with company subdomain
    variables:
      company:
        default: myco
        description: Company subdomain
security: []
paths:
  /api/analytics/traffic/reps:
    get:
      tags:
        - analytics
      summary: Get traffic by rep
      description: |
        Returns the traffic a store's field of reps drove for a named reporting
        period — the leaderboard behind the Reps tab and the two traffic tiles
        above it.

        A visit is credited to a rep by identity rather than by channel: it
        carries the rep's attribution_member_id, or a share_id whose share
        belongs to them, or both. Where both are present and disagree, the
        stamped member wins. Identity has been recorded since long before the
        channel column existed, so this reaches back further than the
        channel-keyed figures on the Sources tab, and the two will not agree
        over a long window.

        visitor_share and the ranked rows come from that one filter, so the tile
        and the leaderboard beneath it cannot disagree. Its denominator is every
        visitor the store saw over the requested window and is deliberately not
        narrowed to the first rep-driven visit: months before the field drove
        anything held no rep traffic, and dilution is the answer rather than a
        distortion.

        Rows are ranked by distinct visitors descending, ties broken on the
        rep's name, and cut to a top N. Because one visitor can be sent by two
        reps, the rows' visitors need not sum to total_visitors and must not be
        rendered as a share of a whole. Reps the merchant hid from leaderboards
        are omitted from the rows while their traffic still counts toward
        active_reps and visitor_share, and a rep whose member record has since
        been deleted still ranks and is still named.

        Each row also names the resource that drew the most of that rep's
        traffic, or null when none did. That column is read from the
        per-resource rollups rather than from the events, so it answers only for
        traffic that landed on a tracked resource — about half of rep traffic,
        and a different half per store. A null there is a rep whose traffic
        never touched one, not a gap in their numbers.

        unattributed is not a rep. It folds the rep-classified traffic that
        names nobody — an admin-owned share has no member — so the rows plus the
        remainder reconcile with visitor_share. It carries no member_id and no
        name, and is served beside the rows rather than among them.
      operationId: company_v0_get_analytics_traffic_reps
      parameters:
        - name: period
          in: query
          required: false
          description: |
            Named reporting period (default last_30_days). Supported names:
            today, last_7_days, last_30_days, last_90_days, last_12_months,
            this_month, last_month. An unsupported name returns 422.
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CompanyTrafficRepsResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedResponse'
        '422':
          description: Unsupported period
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StandardErrorResponse'
      security:
        - bearer_auth: []
components:
  schemas:
    CompanyTrafficRepsResponse:
      description: >-
        The traffic a store's field of reps drove over a period — the resolved
        window, how many reps were active, the field's share of every visitor,
        the ranked leaderboard, and the remainder that names nobody, wrapped in
        the standard API response envelope.
      type: object
      additionalProperties: false
      required:
        - period
        - active_reps
        - visitor_share
        - total_visitors
        - reps
        - unattributed
        - status
        - meta
      properties:
        period:
          type: object
          additionalProperties: false
          required:
            - name
            - starts_on
            - ends_on
            - bucket
          properties:
            name:
              type: string
              description: The resolved period name (e.g. last_30_days).
            starts_on:
              type: string
              format: date
              description: Inclusive first day of the window (YYYY-MM-DD, UTC).
            ends_on:
              type: string
              format: date
              description: Inclusive last day of the window (YYYY-MM-DD, UTC).
            bucket:
              type: string
              description: >-
                The bucket granularity of the period window (always "day"), so a
                twelve-month period is 365 series points per rep.
        active_reps:
          type: object
          description: >-
            How many reps drove traffic, with the comparison every other
            headline figure carries.
          additionalProperties: false
          required:
            - current
            - previous
            - change_pct
          properties:
            current:
              type: integer
              description: >-
                Distinct reps with at least one qualifying visit in the window,
                including reps hidden from the leaderboard.
            previous:
              type: integer
              description: The same count over the equal-length window before it.
            change_pct:
              type:
                - number
                - 'null'
              description: >-
                Percentage change versus the previous window, or null when that
                window had no active reps.
        visitor_share:
          type: number
          minimum: 0
          maximum: 1
          description: >-
            Distinct visitors who arrived on a rep-carrying visit over every
            distinct visitor in the window, rounded to four decimals, and 0 when
            the store saw none. Computed from the same identity filter as the
            rows, and its denominator is not narrowed to the first rep-driven
            visit.
        total_visitors:
          type: integer
          description: >-
            Total distinct bot-free visitors over the window — the denominator
            visitor_share is taken against.
        reps:
          type: array
          description: >-
            Reps ranked by distinct visitors descending, ties broken on name,
            cut to a top N. Reps hidden from leaderboards are absent.
          items:
            type: object
            additionalProperties: false
            required:
              - member_id
              - name
              - visitors
              - visits
              - series
              - top_asset
            properties:
              member_id:
                type: string
                description: The rep's member id.
              name:
                type: string
                description: >-
                  The rep's display name, resolved even for a member the
                  merchant has since deleted.
              visitors:
                type: integer
                description: >-
                  Distinct bot-free visitors this rep sent over the window. Rows
                  need not sum to total_visitors, because one visitor can be
                  sent by two reps.
              visits:
                type: integer
                description: Bot-free visits this rep sent over the window.
              series:
                type: array
                description: >-
                  Distinct visitors per day over the window, oldest first,
                  gap-filled with zeros. Distinct-per-day does not sum to
                  distinct-over-window, so this normally totals more than
                  visitors.
                items:
                  type: integer
              top_asset:
                type:
                  - object
                  - 'null'
                additionalProperties: false
                description: |
                  The resource that drew the most of this rep's traffic over the
                  window, or null when none did.

                  Null is a real reading rather than missing data, and a client
                  must render an explicit empty cell for it. This column is read
                  from the per-resource rollups, which observe only tracked
                  resource types — rep traffic lands on one about half the time
                  — so a rep whose traffic never touched one genuinely has no
                  top asset. The traffic figures beside it come from the events
                  and are unaffected: a null here never means the row's
                  visitors, visits, or series are short.

                  Ties break on the kind and then on the resource's own id, so
                  the same window returns the same answer every time.

                  The three keys match the top_asset the Home > Field
                  leaderboard serves, so one card component renders both. The
                  resource's id is not among them: the card names an asset, it
                  does not link to one.
                required:
                  - title
                  - kind
                  - thumbnail_url
                properties:
                  title:
                    type:
                      - string
                      - 'null'
                    description: >-
                      The resource's title, or null when it has none. A resource
                      the merchant has since deleted still names the row it
                      earned.
                  kind:
                    type: string
                    enum:
                      - product
                      - page
                      - media
                      - blog
                      - collection
                      - enrollment
                    description: |
                      What kind of thing the asset is, as the card's own content
                      vocabulary names it.

                      Three of these do not read like the resource behind them:
                      a blog post is `blog`, a library is `collection`, and an
                      enrollment pack is `enrollment`. The Home > Field
                      leaderboard's top_asset spells the same three differently
                      — `post`, `library`, `enrollment_pack` — because it feeds
                      a different card. Promotions never appear: that rollup
                      holds no rows and is not read.
                  thumbnail_url:
                    type:
                      - string
                      - 'null'
                    description: |
                      The resource's own image, or null when it has none.

                      Null is a real reading — the client renders a typed
                      placeholder. It is never an empty string and never a
                      server-chosen fallback.
        unattributed:
          type: object
          description: >-
            The rep-classified traffic that names nobody, folded into one
            remainder — chiefly visits arriving through an admin-owned share,
            which carries no member. It is not a rep row, and carries neither a
            member_id nor a name.
          additionalProperties: false
          required:
            - visitors
            - visits
          properties:
            visitors:
              type: integer
              description: >-
                Distinct bot-free visitors whose rep-carrying visit resolved to
                no member.
            visits:
              type: integer
              description: Bot-free visits that resolved to no member.
        status:
          type: integer
          description: The HTTP status code echoed in the response envelope.
        meta:
          type: object
          additionalProperties: false
          required:
            - request_uuid
            - timestamp
          properties:
            request_uuid:
              type:
                - string
                - 'null'
              description: The request correlation id, or null when unset.
            timestamp:
              type: string
              format: date-time
              description: ISO 8601 timestamp when the response was built.
    UnauthorizedResponse:
      type: object
      properties:
        message:
          type: string
      required:
        - message
    StandardErrorResponse:
      description: >-
        Common legacy error response envelope. Older endpoints may return one or
        more of these fields depending on the controller path.
      type: object
      properties:
        message:
          type: string
        error:
          $ref: '#/components/schemas/ErrorMessage'
        error_message:
          $ref: '#/components/schemas/ErrorMessage'
        errors:
          $ref: '#/components/schemas/ErrorBag'
        meta:
          $ref: '#/components/schemas/Meta'
      additionalProperties:
        $ref: '#/components/schemas/JsonValue'
    ErrorMessage:
      description: An API error message represented as text or structured JSON.
      anyOf:
        - type: string
        - $ref: '#/components/schemas/ErrorBag'
        - type: 'null'
    ErrorBag:
      description: >-
        Validation errors keyed by field, a list of errors, a single error
        message, or null when no structured error details are available.
      anyOf:
        - type: string
        - type: array
          items:
            $ref: '#/components/schemas/ErrorValue'
        - type: object
          additionalProperties:
            $ref: '#/components/schemas/ErrorValue'
        - type: 'null'
    Meta:
      type:
        - object
        - 'null'
      properties:
        request_id:
          type:
            - string
            - number
            - integer
            - 'null'
        timestamp:
          type:
            - string
            - number
            - integer
            - 'null'
          format: date-time
    JsonValue:
      description: >-
        Any valid JSON value for provider, integration, theme, metadata, or
        other dynamic payloads whose keys are not fixed by the API contract.
      anyOf:
        - type: string
        - type: number
        - type: boolean
        - type: 'null'
        - type: array
          items:
            $ref: '#/components/schemas/JsonValue'
        - type: object
          additionalProperties:
            $ref: '#/components/schemas/JsonValue'
    ErrorValue:
      description: A validation or API error value.
      anyOf:
        - type: string
        - type: array
          items:
            type: string
        - type: object
          additionalProperties:
            $ref: '#/components/schemas/JsonValue'
  securitySchemes:
    bearer_auth:
      type: http
      scheme: bearer
      description: Bearer token authentication

````