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

# Subscribers

> List fans acquired through campaigns attached to your linked OF accounts.



## OpenAPI

````yaml GET /subscribers
openapi: 3.0.3
info:
  title: OnlyTraffic Studio API
  version: 1.0.0
  description: >-
    External API for OnlyTraffic Studio. Manage and retrieve data about your
    subscribers, CPL orders, and CPC orders.
servers:
  - url: https://studio-api.onlytraffic.com/api/external/v1
security:
  - ApiKeyAuth: []
tags:
  - name: Account
    description: API key holder's wallet, profile, and aggregate state.
  - name: Accounts
    description: OnlyFans accounts attached to the API key holder.
  - name: Agencies
    description: Agency CRUD and image management. All edits stage in moderation.
  - name: CPL
    description: >-
      Cost-per-lead orders: place, list, cancel, manage settings, browse partner
      offers.
  - name: CPC
    description: Cost-per-click orders and creative management.
  - name: RevShare
    description: Revenue-share campaigns and invoices.
  - name: Swaps
    description: Two-sided traffic swap orders and offers.
  - name: Subscribers
    description: Per-fan delivery feed (cursor-paginated).
  - name: Transactions
    description: Per-transaction OF revenue feed (cursor-paginated).
paths:
  /subscribers:
    get:
      tags:
        - Subscribers
      summary: Subscribers
      description: >-
        List fans acquired through campaigns attached to your linked OF
        accounts.
      operationId: getSubscribers
      parameters:
        - name: after
          in: query
          schema:
            type: string
          description: >-
            Cursor from a previous response's `pagination.next_cursor`. Omit to
            fetch the first page.
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
          description: Page size. Default 50, max 100.
        - name: sort
          in: query
          schema:
            type: string
            enum:
              - subscribed_at_desc
              - subscribed_at_asc
            default: subscribed_at_desc
          description: >-
            Sort order. The cursor is bound to the direction it was issued for;
            switching mid-pagination restarts pagination.
        - name: of_account_id
          in: query
          schema:
            type: integer
          description: Filter by OnlyFans account id (must be one of yours).
        - name: campaign_id
          in: query
          schema:
            type: string
          description: >-
            Filter by campaign public id. Works for CPL orders (`cplo_…`), CPC
            orders (`cpco_…`), revshare campaigns (`revc_…`), and swap orders.
        - name: campaign_type
          in: query
          schema:
            type: string
            enum:
              - all
              - cpl
              - cpc
              - revshare
              - gg_swap
          description: Filter by campaign kind.
        - $ref: '#/components/parameters/FromDate'
        - $ref: '#/components/parameters/ToDate'
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Subscriber'
                  pagination:
                    $ref: '#/components/schemas/CursorPagination'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: >-
            Server error. Body always reads `{success:false,
            error:"server_error", message:"Server error"}` (no internal details
            leak).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  parameters:
    FromDate:
      name: from
      in: query
      schema:
        type: string
        format: date
      description: Lower bound on the resource date (`YYYY-MM-DD`, UTC, inclusive).
      example: '2026-01-01'
    ToDate:
      name: to
      in: query
      schema:
        type: string
        format: date
      description: Upper bound on the resource date (`YYYY-MM-DD`, UTC, inclusive).
      example: '2026-01-31'
  schemas:
    Subscriber:
      type: object
      description: >-
        A fan acquired through a campaign attached to one of your linked OF
        accounts. Direct OnlyFans subscribers (not tied to one of our
        marketings) are not returned. The same person subscribing to two of your
        models appears as two rows, one per (model, fan) pair.
      properties:
        of_user_id:
          type: integer
          description: OnlyFans-side numeric id of the fan.
          example: 789
        name:
          type: string
          nullable: true
          description: Display name of the fan as seen on OnlyFans.
          example: John
        of_account_id:
          type: integer
          description: Your OnlyFans account id (the model the fan subscribed to).
          example: 123456
        campaign:
          type: object
          nullable: true
          description: The campaign that brought this fan in.
          properties:
            public_id:
              type: string
              description: >-
                Public id of the linked CPL order, CPC order, revshare campaign,
                or swap order.
              example: cplo_xxxxxxx
            type:
              type: string
              enum:
                - cpl
                - cpc
                - revshare
                - gg_swap
              example: cpl
        amount_spent:
          type: number
          format: float
          description: >-
            Total USD this fan has spent so far (sum of valid transactions;
            refunds excluded).
          example: 23.45
        subscribed_at:
          type: string
          format: date-time
          description: When the fan subscribed (ISO 8601, UTC).
          example: '2026-01-15T12:00:00+00:00'
        subscribed_at_ts:
          type: integer
          description: Subscription time as a Unix timestamp.
          example: 1736942400
        badges:
          type: array
          description: >-
            Promotion-ladder markers a fan has hit. Only the highest purchase
            tier is reported (`5_purchases` > `2_purchases` > `1_purchase`).
          items:
            type: string
            enum:
              - 1_purchase
              - 2_purchases
              - 5_purchases
              - 500_purchases
              - 3_messages
              - pay_subscribe
              - pay_resubscribe
          example:
            - 1_purchase
            - 3_messages
    CursorPagination:
      type: object
      description: >-
        Cursor-based pagination (used by high-volume feeds: `subscribers`,
        `transactions`).
      properties:
        next_cursor:
          type: string
          nullable: true
          description: >-
            Opaque token. Pass it as `?after=...` to get the next page. `null`
            when there are no more rows.
          example: eyJ0cyI6MTc0NjQ1MzI5NiwiaWQiOjk4NzY1fQ==
        has_next:
          type: boolean
          description: '`true` if more rows remain after this page.'
          example: true
        limit:
          type: integer
          description: How many rows were requested for this page.
          example: 50
    ErrorResponse:
      type: object
      description: Standard error envelope for all 4xx/5xx responses.
      required:
        - success
        - error
        - message
      properties:
        success:
          type: boolean
          enum:
            - false
          description: Always false on error responses.
        error:
          type: string
          description: Stable snake_case machine-readable error code. Branch on this.
          example: validation_failed
        message:
          type: string
          description: >-
            Human-friendly text. For 5xx this is always the literal `Server
            error`. For 4xx an actionable validation/auth message is returned.
        details:
          type: object
          nullable: true
          description: >-
            Optional per-field diagnostic information. On 422 carries `{<field>:
            ["error_code", ...]}`. On 402 (`insufficient_balance`) carries
            `{required, current}`. On 426 (`unpaid_invoices`) carries `{count,
            total, oldest_date_ts}`. Absent on most other errors.
          additionalProperties: true
        retry_after:
          type: integer
          nullable: true
          description: >-
            Seconds until the next request will succeed. Present only on 429
            responses (rate limit). Mirrors the `Retry-After` HTTP header.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: Your API key from the Studio Dashboard

````