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

# List AI referrals

> Returns paginated AI-referral landing pages, overview and the complete selected-provider engine breakdown for the same fixed reporting dates. Sessions are not people; conversion events use the selected provider and conversion definitions. Nullable provider measurements remain unavailable. Known counts can be partial: overview.referralCoverage reports current and previous coverage for sessions and conversion events. Compare a metric across periods only when both of its coverage flags are true. visitorShare gives the share of all sessions that AI answers sent over the same window, from the selected analytics provider and the same database snapshot as the referrals, with the sessions it could not trace; it is absent when that read fails, so the rest of the response is still returned. conversionDefinitions lists each selected PostHog conversion that occurred in the same window, with its occurrences with and without a site visit.



## OpenAPI

````yaml /openapi.json get /projects/{projectId}/traffic/referrals
openapi: 3.1.0
info:
  title: DevTune API
  version: 2.0.0
  description: >-
    API for programmatic access to your AI visibility data, webhook
    subscriptions, and automation workflows. Use this API to integrate DevTune
    data into CI/CD pipelines, BI tools, AI agents, and operational systems.
servers:
  - url: https://devtune.ai/api/v2
    description: Production
security:
  - bearerAuth: []
paths:
  /projects/{projectId}/traffic/referrals:
    get:
      summary: List AI referrals
      description: >-
        Returns paginated AI-referral landing pages, overview and the complete
        selected-provider engine breakdown for the same fixed reporting dates.
        Sessions are not people; conversion events use the selected provider and
        conversion definitions. Nullable provider measurements remain
        unavailable. Known counts can be partial: overview.referralCoverage
        reports current and previous coverage for sessions and conversion
        events. Compare a metric across periods only when both of its coverage
        flags are true. visitorShare gives the share of all sessions that AI
        answers sent over the same window, from the selected analytics provider
        and the same database snapshot as the referrals, with the sessions it
        could not trace; it is absent when that read fails, so the rest of the
        response is still returned. conversionDefinitions lists each selected
        PostHog conversion that occurred in the same window, with its
        occurrences with and without a site visit.
      operationId: listAiReferrals
      parameters:
        - name: projectId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: windowDays
          in: query
          schema:
            type: integer
            default: 30
            enum:
              - 7
              - 30
              - 90
          description: >-
            Fixed rolling window in days. Supported values are 7, 30, and 90.
            Defaults to 30.
        - name: cursor
          in: query
          schema:
            type: string
          description: >-
            Opaque cursor from the previous response; cursors expire after ~48
            hours.
        - name: pageSize
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 25
          description: Results per page. Capped at 100.
      responses:
        '200':
          description: AI referral demand
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/AiReferralsData'
                  meta:
                    $ref: '#/components/schemas/Meta'
                required:
                  - data
                  - meta
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '429':
          $ref: '#/components/responses/RateLimitExceededError'
components:
  schemas:
    AiReferralsData:
      type: object
      properties:
        comparisonCoverage:
          $ref: '#/components/schemas/ScopedAnalyticsCoverage'
        analyticsReportingContext:
          $ref: '#/components/schemas/AnalyticsReportingContext'
        engines:
          type: object
          description: >-
            Complete selected-provider engine breakdown, independent of
            landing-page pagination. Nullable values preserve provider coverage.
            Event/session ratios are not converted-person rates.
          properties:
            items:
              type: array
              items:
                $ref: '#/components/schemas/ConversionAttributionEngine'
            hasConversionSource:
              type: boolean
            hasEngagementSource:
              type: boolean
            totals:
              $ref: '#/components/schemas/FlexibleRollupItem'
          required:
            - items
            - hasConversionSource
            - hasEngagementSource
            - totals
        window:
          type: object
          properties:
            dateFrom:
              type: string
              format: date
            dateTo:
              type: string
              format: date
          required:
            - dateFrom
            - dateTo
        items:
          type: array
          items:
            $ref: '#/components/schemas/FlexibleRollupItem'
          description: >-
            Landing pages ordered by current sessions descending, then domain
            and path. Includes nullable currentEngagementSeconds,
            priorEngagementSeconds, engagementRate and pageValue alongside the
            existing session and conversion-event fields. Page value uses
            complete-population conversion totals.
        overview:
          type: object
          additionalProperties: true
          properties:
            referralCoverage:
              $ref: '#/components/schemas/ReferralWindowCoverage'
          required:
            - referralCoverage
        pagination:
          $ref: '#/components/schemas/RollupCursorPagination'
        conversionDefinitions:
          type: array
          description: >-
            Per selected PostHog event or action that occurred in the same fixed
            window (a selected definition with no occurrences is omitted):
            occurrences with no site visit (no linked session and no page host,
            such as server-sent events) and occurrences tied to a site visit (a
            linked session). A definition with no-site-visit occurrences and no
            site-visit occurrences in a complete window cannot be credited to an
            AI referral; choose a browser-side event. GA4 key events are always
            session-scoped, so they are omitted. Absent when the read fails; the
            rest of the response is still returned.
          items:
            type: object
            properties:
              provider:
                type: string
                enum:
                  - posthog
              domainCanonical:
                type: string
                description: Tracked site of the PostHog connection.
              definition:
                type: string
                description: 'Selected conversion definition: event:<name> or action:<id>.'
              noSiteVisitOccurrences:
                type: integer
                minimum: 0
              siteVisitOccurrences:
                type: integer
                minimum: 0
              windowComplete:
                type: boolean
                description: >-
                  Every day of the window is published for the connection. When
                  false, the counts are partial.
            required:
              - provider
              - domainCanonical
              - definition
              - noSiteVisitOccurrences
              - siteVisitOccurrences
              - windowComplete
        visitorShare:
          $ref: '#/components/schemas/AiVisitorShare'
        windowDays:
          type: integer
          enum:
            - 7
            - 30
            - 90
      required:
        - engines
        - items
        - overview
        - pagination
        - window
        - windowDays
    Meta:
      type: object
      properties:
        timestamp:
          type: string
          format: date-time
        projectId:
          type: string
          format: uuid
    ScopedAnalyticsCoverage:
      type: object
      properties:
        project:
          $ref: '#/components/schemas/ReferralWindowCoverage'
        engines:
          type: array
          items:
            type: object
            properties:
              platform:
                type: string
              coverage:
                $ref: '#/components/schemas/ReferralWindowCoverage'
            required:
              - platform
              - coverage
        pages:
          type: array
          items:
            type: object
            properties:
              domain:
                type: string
              path:
                type: string
              coverage:
                $ref: '#/components/schemas/ReferralWindowCoverage'
            required:
              - domain
              - path
              - coverage
      required:
        - project
        - engines
        - pages
    AnalyticsReportingContext:
      type: object
      description: >-
        Selected analytics provider provenance, full-window coverage, explicit
        daily gaps and AI-referred session metrics. PostHog duration and bounce
        are native metrics, not GA4 engagement.
      properties:
        comparisonCoverage:
          $ref: '#/components/schemas/ReferralWindowCoverage'
        quality:
          type: array
          items:
            type: object
            properties:
              connectionId:
                type: string
              domainCanonical:
                type: string
              day:
                type: string
                format: date
              sessions:
                $ref: '#/components/schemas/AnalyticsQuality'
              conversions:
                $ref: '#/components/schemas/AnalyticsQuality'
            required:
              - connectionId
              - domainCanonical
              - day
              - sessions
              - conversions
        comparisonQuality:
          type: array
          items:
            type: object
            properties:
              connectionId:
                type: string
              domainCanonical:
                type: string
              day:
                type: string
                format: date
              sessions:
                $ref: '#/components/schemas/AnalyticsQuality'
              conversions:
                $ref: '#/components/schemas/AnalyticsQuality'
            required:
              - connectionId
              - domainCanonical
              - day
              - sessions
              - conversions
        window:
          type: object
          properties:
            dateFrom:
              type: string
              format: date
            dateTo:
              type: string
              format: date
            previousDateFrom:
              type: string
              format: date
            previousDateTo:
              type: string
              format: date
          required:
            - dateFrom
            - dateTo
            - previousDateFrom
            - previousDateTo
        providers:
          type: array
          items:
            type: object
            properties:
              provider:
                type: string
                enum:
                  - ga4
                  - posthog
              domainCanonical:
                type: string
              connectionId:
                type: string
              definitionHash:
                type:
                  - string
                  - 'null'
              generation:
                type: integer
              status:
                type: string
              reportingTimezone:
                type: string
              reportSnapshot:
                type:
                  - object
                  - 'null'
                description: >-
                  Published report freshness and replacement state. While
                  replacing, definitionHash and generation identify the retained
                  report; pending fields identify collection work. Publication
                  waits for both supported 90-day windows. Older history can
                  still have explicit coverage gaps.
                properties:
                  state:
                    type: string
                    enum:
                      - collecting
                      - replacing
                      - current
                  syncedAt:
                    type:
                      - string
                      - 'null'
                  throughDate:
                    type:
                      - string
                      - 'null'
                  replacementWindowEnd:
                    type:
                      - string
                      - 'null'
                  pendingDefinitionHash:
                    type:
                      - string
                      - 'null'
                  pendingGeneration:
                    type: integer
                required:
                  - state
                  - syncedAt
                  - throughDate
                  - replacementWindowEnd
                  - pendingDefinitionHash
                  - pendingGeneration
            required:
              - provider
              - domainCanonical
              - connectionId
              - definitionHash
              - generation
              - status
              - reportingTimezone
        coverage:
          $ref: '#/components/schemas/ReferralWindowCoverage'
        gaps:
          type: array
          items:
            type: object
            properties:
              domainCanonical:
                type: string
              day:
                type: string
                format: date
              reason:
                type: string
            required:
              - domainCanonical
              - day
              - reason
        nativeMetrics:
          type: array
          items:
            type: object
            properties:
              provider:
                type: string
                enum:
                  - ga4
                  - posthog
              domainCanonical:
                type: string
              averageSessionDurationSeconds:
                type:
                  - number
                  - 'null'
              bounceRate:
                type:
                  - number
                  - 'null'
              engagementRate:
                type:
                  - number
                  - 'null'
              averageEngagementSeconds:
                type:
                  - number
                  - 'null'
            required:
              - provider
              - domainCanonical
              - averageSessionDurationSeconds
              - bounceRate
              - engagementRate
              - averageEngagementSeconds
      required:
        - window
        - providers
        - coverage
        - gaps
        - nativeMetrics
    ConversionAttributionEngine:
      type: object
      additionalProperties: false
      properties:
        coverage:
          $ref: '#/components/schemas/ReferralWindowCoverage'
        conversionRate:
          type:
            - number
            - 'null'
        conversions:
          $ref: '#/components/schemas/ConversionAttributionMeasure'
        engagementSeconds:
          $ref: '#/components/schemas/ConversionAttributionMeasure'
        platform:
          type: string
        sessions:
          $ref: '#/components/schemas/ConversionAttributionMeasure'
      required:
        - conversionRate
        - conversions
        - engagementSeconds
        - platform
        - sessions
    FlexibleRollupItem:
      type: object
      additionalProperties: true
      description: >-
        A projected row from the same bounded rollup used by the corresponding
        DevTune application surface.
    ReferralWindowCoverage:
      type: object
      additionalProperties: false
      description: >-
        Coverage of session and conversion-event counts across the current and
        previous reporting windows. False means observed counts may be partial
        or unavailable. Compare periods only when both flags for that metric are
        true; these flags apply to overview, engine and landing-page counts.
      properties:
        sessionsCurrent:
          type: boolean
        sessionsPrevious:
          type: boolean
        conversionsCurrent:
          type: boolean
        conversionsPrevious:
          type: boolean
      required:
        - sessionsCurrent
        - sessionsPrevious
        - conversionsCurrent
        - conversionsPrevious
    RollupCursorPagination:
      type: object
      properties:
        hasMore:
          type: boolean
        nextCursor:
          type:
            - string
            - 'null'
        pageSize:
          type: integer
          minimum: 1
          maximum: 100
        totalCount:
          type: integer
          minimum: 0
      required:
        - hasMore
        - nextCursor
        - pageSize
        - totalCount
    AiVisitorShare:
      type: object
      description: >-
        Share of visitors sent by AI answers for the fixed window: AI-referral
        sessions over all sessions from the selected analytics provider (GA4 or
        PostHog), read in the same database snapshot as the referrals. Reported
        whenever the provider imported every day of the window and recorded
        sessions in it. Sessions that may have come from an AI answer but could
        not be traced, because their source or site is unknown, are not counted
        as AI; unattributedSessions counts them and partial is true when there
        are any. Otherwise share is null with coverage.reason no_source (no
        provider connected), coverage_incomplete (a day not imported yet),
        no_visits, or only_untraced (sessions were recorded but none could be
        traced, so there is no share to report; unattributedSessions counts
        them). It is never reported as zero for an unmeasured window.
      additionalProperties: false
      properties:
        share:
          type:
            - number
            - 'null'
          description: >-
            AI-referral sessions over all sessions, as a fraction from 0 to 1.
            Null when the window is not measured or had no sessions;
            coverage.reason says why.
        priorShare:
          type:
            - number
            - 'null'
          description: >-
            The same ratio for the previous window of equal length. Null unless
            both windows have a share; priorPartial says whether it leaves out
            untraced sessions.
        partial:
          type: boolean
          description: >-
            True when sessions that may have come from an AI answer could not be
            traced in the window; unattributedSessions gives how many.
        priorPartial:
          type: boolean
          description: The same for the previous window.
        unattributedSessions:
          type:
            - integer
            - 'null'
          description: >-
            Sessions in the window that may have come from an AI answer but
            could not be traced, because their source or site is unknown. The
            share does not count them as AI. Null when the window is not
            measured.
        priorUnattributedSessions:
          type:
            - integer
            - 'null'
          description: >-
            The same count for the previous window. Null when that window is not
            measured.
        source:
          type:
            - string
            - 'null'
          enum:
            - analytics
            - null
          description: analytics when a provider is connected; null when none is.
        providers:
          type: array
          items:
            type: string
            enum:
              - ga4
              - posthog
          description: >-
            Selected analytics providers behind the share. Empty when none is
            connected.
        window:
          type: object
          additionalProperties: false
          properties:
            windowDays:
              type: integer
              enum:
                - 7
                - 30
                - 90
            dateFrom:
              type: string
              format: date
            dateTo:
              type: string
              format: date
            priorDateFrom:
              type: string
              format: date
            priorDateTo:
              type: string
              format: date
          required:
            - windowDays
            - dateFrom
            - dateTo
            - priorDateFrom
            - priorDateTo
        coverage:
          type: object
          additionalProperties: false
          properties:
            current:
              type: string
              enum:
                - complete
                - partial
                - unavailable
              description: >-
                complete: every day imported and every session traced. partial:
                every day imported, with untraced sessions. unavailable: no
                provider, or a day not imported yet.
            prior:
              type: string
              enum:
                - complete
                - partial
                - unavailable
              description: The same coverage for the previous window.
            reason:
              type:
                - string
                - 'null'
              enum:
                - no_source
                - coverage_incomplete
                - no_visits
                - only_untraced
                - null
          required:
            - current
            - prior
            - reason
      required:
        - share
        - priorShare
        - partial
        - priorPartial
        - unattributedSessions
        - priorUnattributedSessions
        - source
        - providers
        - window
        - coverage
    Error:
      type: object
      properties:
        error:
          type: string
        message:
          type: string
        status:
          type: integer
      required:
        - error
        - message
        - status
    AnalyticsQuality:
      type: object
      description: >-
        Import continuity, observed tracking and attribution completeness are
        independent. Attributed partial counts are lower bounds; complete is
        required for comparisons and inferred zero.
      properties:
        configured:
          type: boolean
        importedDays:
          type: integer
        expectedDays:
          type: integer
        importsComplete:
          type: boolean
        trackingObserved:
          type: boolean
        attributionGapOccurrences:
          type: number
        noSiteVisitOccurrences:
          type: number
          description: >-
            Selected conversion events with no site visit, such as events sent
            from a server. They cannot be attributed to a landing page or AI
            referral, so they are not counted in attributionGapOccurrences and
            do not make conversions incomplete. Always 0 for sessions.
        attributionComplete:
          type: boolean
        complete:
          type: boolean
        reasons:
          type: array
          items:
            type: string
      required:
        - configured
        - importedDays
        - expectedDays
        - importsComplete
        - trackingObserved
        - attributionGapOccurrences
        - attributionComplete
        - complete
        - reasons
    ConversionAttributionMeasure:
      type: object
      additionalProperties: false
      properties:
        current:
          type:
            - number
            - 'null'
        previous:
          type:
            - number
            - 'null'
        comparisonAvailable:
          type: boolean
          description: >-
            Whether both reporting windows have complete coverage for this
            measure. Observed current and previous values may remain numeric
            when false.
      required:
        - current
        - previous
  responses:
    BadRequestError:
      description: Bad request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    UnauthorizedError:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    ForbiddenError:
      description: Forbidden
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFoundError:
      description: Not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimitExceededError:
      description: Rate limit exceeded
      headers:
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  headers:
    X-RateLimit-Limit:
      description: Maximum requests per window
      schema:
        type: integer
    X-RateLimit-Remaining:
      description: Requests remaining in current window
      schema:
        type: integer
    X-RateLimit-Reset:
      description: Unix timestamp when the window resets
      schema:
        type: integer
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        API key with dtk_live_ prefix. Obtain it from API Keys in the account
        sidebar. New keys start with all supported scopes selected for the
        chosen project, and you can narrow them to specific read/write scopes as
        needed.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.