> ## 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.

# CPL Campaigns

> CPL campaigns placed by clients against your offers. `quantity_delivered` and `total_earned` grow in real time as fans subscribe.

For `completed` and `rejected` campaigns `onlyfans_account.demo_content` is always empty: you no longer have the right to display the model's content.

## Filters

| Filter            | Description                                                                            |
| ----------------- | -------------------------------------------------------------------------------------- |
| `offer_id`        | Campaigns placed on your partner offer                                                 |
| `client_offer_id` | Campaigns placed on a client offer                                                     |
| `search`          | Searches the campaign public ID, campaign number and OnlyFans username                 |
| `of_account_id`   | One specific OnlyFans account                                                          |
| `status`          | Campaign status: `waiting`, `accepted`, `rejected`, `completed`, `cancelled`, `paused` |

## Partner offers vs client offers

Every campaign is placed either on your partner offer or on a client offer:

* **Partner offer**: `is_client_offer` is `false`, `offer_id` holds your offer ID and `client_offer_id` is `null`.
* **Client offer**: `is_client_offer` is `true`, `client_offer_id` holds the client offer ID and `offer_id` is `0`.

## Auto-renewal

The `auto_renewal` block shows what happens when the campaign renews:

* `next_price`: your payout per subscriber for the next cycle.
* `can_renew`: whether the renewal will actually go through. This requires the client account to be active, the offer to be available, the price to be within the cap, and enough balance for the next cycle.


## OpenAPI

````yaml api/openapi-partners.json GET /api/marketer/cpl/campaigns
openapi: 3.0.2
info:
  title: OnlyTraffic Marketer API
  version: 2.1.0
  description: >-
    Partner (marketer) API for OnlyTraffic.


    **Authentication:** pass your API key in the `Authorization` header
    (`Authorization: your-api-key` or `Authorization: Bearer your-api-key`).
    Create keys in the partner cabinet: Tools -> API
    (https://partners.onlytraffic.com/tools/api). Up to 5 named keys per
    account, each **Full** or **Read-only**, with an optional expiry. Keys start
    with `ot_partners_` and are shown once, at creation. Read-only keys cannot
    call the `POST` endpoints (`error_code` 403, message `This API key is
    read-only`). An older legacy key keeps working with full access until you
    delete it on the same page.


    **Pagination:** all list endpoints accept `offset` (default 0) and `limit`
    (default 50, max 1000) as query parameters or JSON body fields.


    **Dates:** every timestamp field has two variants — an ISO 8601 string
    (`*_at`) and a Unix timestamp integer (`*_at_ts` / `*_ts`).


    **Writes:** a Full-access key reads and writes. Write endpoints are `POST`
    with a JSON body, accept public ids only (`revc_…`, `cplo_…`) and answer
    with the updated object in `data`. Rate limit: 120 requests per minute for
    reads, 30 per minute for writes, per account (shared by all its keys).
servers:
  - url: https://partners.onlytraffic.com
security: []
tags:
  - name: RevShare
    description: RevShare campaigns and financial data
  - name: CPL
    description: Cost-Per-Lead orders placed against your offers
  - name: CPC
    description: Cost-Per-Click orders and the category catalog
  - name: Subscribers
    description: Fans acquired through your campaigns
  - name: Stats
    description: Dashboard-style statistics widgets (fans, income, conversion)
  - name: Write
    description: >-
      Write API: start / stop / update campaigns and accept / reject / stop CPL
      campaigns (same key, same rules as the cabinet)
paths:
  /api/marketer/cpl/campaigns:
    get:
      tags:
        - CPL
      summary: List CPL campaigns
      description: >-
        CPL campaigns placed by clients against your offers.
        `quantity_delivered` and `total_earned` grow in real time as fans
        subscribe.


        For `completed` and `rejected` campaigns `onlyfans_account.demo_content`
        is always empty: you no longer have the right to display the model's
        content.
      parameters:
        - $ref: '#/components/parameters/offset'
        - $ref: '#/components/parameters/limit'
        - name: of_account_id
          in: query
          schema:
            type: integer
          description: Filter by OnlyFans account numeric id.
        - name: offer_id
          in: query
          schema:
            type: integer
          description: Filter by your partner offer id.
        - name: client_offer_id
          in: query
          schema:
            type: integer
          description: Filter by client offer id.
        - name: status
          in: query
          schema:
            type: string
            enum:
              - waiting
              - accepted
              - rejected
              - completed
              - cancelled
              - paused
          description: Filter by campaign status.
        - name: search
          in: query
          schema:
            type: string
          description: >-
            Free-text search across campaign public id, campaign number and
            OnlyFans username.
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                oneOf:
                  - title: Success
                    type: object
                    properties:
                      status:
                        type: string
                        enum:
                          - success
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/CplCampaign'
                  - $ref: '#/components/schemas/ErrorResponse'
              example:
                status: success
                data:
                  - order_id: cplo_abc123
                    offer_id: 5
                    client_offer_id: null
                    is_client_offer: false
                    of_account_id: 456789
                    of_username: modelname
                    url: https://onlyfans.com/modelname/c1
                    source: Telegram
                    quantity_ordered: 100
                    quantity_delivered: 67
                    price_per_subscriber: 2.5
                    total_earned: 167.5
                    status: accepted
                    onlyfans_account:
                      name: Model Name
                      username: modelname
                      about: About text
                      tags:
                        - brunette
                      avatar:
                        original: https://cdn.example.com/avatar.jpg
                        thumbnail: https://cdn.example.com/avatar_thumb.jpg
                        thumbnail_640: https://cdn.example.com/avatar_640.jpg
                      demo_content: []
                      regular_price: 9.99
                      promotions: []
                      blocked_countries: []
                      subscribers_count: 3400
                      likes_count: 87000
                      posts_count: 560
                      photos_count: 420
                      videos_count: 140
                      performer_top: 5
                    auto_renewal:
                      enabled: true
                      quantity: 100
                      max_price: 3
                      next_price: 2.5
                      can_renew: false
                    created_at: '2024-01-15T08:00:00+00:00'
                    created_at_ts: 1705305600
                    changed_at: '2024-06-01T12:00:00+00:00'
                    changed_at_ts: 1717243200
                    completed_at: null
                    completed_at_ts: null
      security:
        - api_key: []
components:
  parameters:
    offset:
      name: offset
      in: query
      schema:
        type: integer
        default: 0
        minimum: 0
      description: Number of records to skip.
    limit:
      name: limit
      in: query
      schema:
        type: integer
        default: 50
        minimum: 1
        maximum: 1000
      description: Number of records to return.
  schemas:
    CplCampaign:
      type: object
      properties:
        order_id:
          type: string
          description: CPL campaign public id (prefix `cplo_`).
        offer_id:
          type: integer
          description: Partner offer id. `0` for client-offer campaigns.
        client_offer_id:
          type: integer
          nullable: true
          description: >-
            Client offer id for client-offer campaigns; `null` for partner-offer
            campaigns.
        is_client_offer:
          type: boolean
          description: '`true` when the campaign was placed against a client offer.'
        of_account_id:
          type: integer
        of_username:
          type: string
        url:
          type: string
          format: uri
          nullable: true
          description: >-
            Promotion URL (OnlyFans campaign/trial link). Available once the
            campaign has been accepted; `null` otherwise.
        source:
          type: string
          nullable: true
          description: >-
            Traffic source (from the running campaign, falling back to the
            offer). `null` until the campaign is accepted.
        quantity_ordered:
          type: integer
        quantity_delivered:
          type: integer
          description: >-
            Delivered actions counted against the campaign's target action
            (subscriptions, messages, purchases, or paid subscriptions).
        price_per_subscriber:
          type: number
        total_earned:
          type: number
          description: >-
            billable × price_per_subscriber, where billable = min(ordered,
            delivered), or all delivered actions when the campaign is open-ended
            (quantity = 0).
        status:
          type: string
          enum:
            - waiting
            - accepted
            - rejected
            - completed
            - cancelled
            - paused
        onlyfans_account:
          $ref: '#/components/schemas/OnlyfansAccount'
        auto_renewal:
          type: object
          properties:
            enabled:
              type: boolean
            quantity:
              type: integer
              description: Repeat quantity when the campaign completes.
            max_price:
              type: number
              description: Maximum payout per subscriber you may charge on a renewal.
            next_price:
              type: number
              description: >-
                Your payout per subscriber for the next cycle, resolved from the
                offer price steps for the repeat quantity.
            can_renew:
              type: boolean
              description: >-
                Whether the renewal will actually go through: client account
                active, offer available, price within the cap and enough balance
                for the next cycle.
        created_at:
          type: string
          format: date-time
        created_at_ts:
          type: integer
        changed_at:
          type: string
          format: date-time
        changed_at_ts:
          type: integer
        completed_at:
          type: string
          format: date-time
          nullable: true
        completed_at_ts:
          type: integer
          nullable: true
    ErrorResponse:
      title: Error
      type: object
      properties:
        status:
          type: string
          enum:
            - error
        message:
          type: string
          description: Human-readable error description.
        error_code:
          type: integer
          description: >-
            403: access denied (missing / unknown / expired / revoked key, or
            the account is not an active partner: `Error! Access denied`; a
            Read-only key calling a write endpoint: `This API key is
            read-only`). 404: not found. 422: bad request params (message says
            what is wrong). 429: rate limit exceeded (a `Retry-After` header is
            set) or another campaign start is still running. 500: server error.
            503: the platform did not answer a write in time, retry later.
    OnlyfansAccount:
      type: object
      description: Cached snapshot of the OnlyFans model profile.
      properties:
        name:
          type: string
        username:
          type: string
        about:
          type: string
        tags:
          type: array
          items:
            type: string
        avatar:
          type: object
          properties:
            original:
              type: string
              format: uri
            thumbnail:
              type: string
              format: uri
            thumbnail_640:
              type: string
              format: uri
        demo_content:
          type: array
          description: >-
            Model's demo photos/videos. Empty for finished campaigns and for
            completed/rejected CPL campaigns.
          items:
            type: object
            properties:
              type:
                type: string
                enum:
                  - photo
                  - video
              url:
                type: string
                format: uri
              thumbnail:
                type: string
                format: uri
        regular_price:
          type: number
        promotions:
          type: array
        blocked_countries:
          type: array
          items:
            type: string
        subscribers_count:
          type: integer
        likes_count:
          type: integer
        posts_count:
          type: integer
        photos_count:
          type: integer
        videos_count:
          type: integer
        performer_top:
          type: number
          description: Top percentage among all performers (e.g. 5 = top 5%).
  securitySchemes:
    api_key:
      type: apiKey
      name: Authorization
      in: header
      description: >-
        API key from the partner cabinet, Tools -> API
        (https://partners.onlytraffic.com/tools/api): up to 5 named keys per
        account, each Full or Read-only, `ot_partners_` prefix, shown once at
        creation. Raw value or `Bearer` form. Read-only keys cannot call the
        `POST` endpoints (403 `This API key is read-only`); expired or revoked
        keys get 403 `Error! Access denied`.

````