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

# Create a campaign

> Creates a campaign for one of your brands. The campaign starts as `pending_payment`. Fund it and launch it in the dashboard. The API key must have write access. The campaign runs the same checks as the dashboard. A name that the brand already uses returns 409, so a retry of a request that succeeded does not make a second campaign.



## OpenAPI

````yaml /agency-api/openapi.json post /campaigns
openapi: 3.1.0
info:
  title: Clipstake Agency API
  description: >-
    Read your agency's brands, campaigns and clips, and create campaigns with an
    API key that has write access.
  version: 0.1.0
servers:
  - url: https://app.clipstake.com/api/v1/agency
security: []
paths:
  /campaigns:
    post:
      tags:
        - Campaigns
      summary: Create a campaign
      description: >-
        Creates a campaign for one of your brands. The campaign starts as
        `pending_payment`. Fund it and launch it in the dashboard. The API key
        must have write access. The campaign runs the same checks as the
        dashboard. A name that the brand already uses returns 409, so a retry of
        a request that succeeded does not make a second campaign.
      operationId: campaigns-create
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                brand_id:
                  type: string
                  description: >-
                    The brand that owns the campaign. A brand ID that your API
                    key cannot read returns 404.
                  example: brd_3f9c0a1b2c3d4e5f60718293a4b5c6d7
                name:
                  type: string
                  minLength: 1
                  maxLength: 256
                  description: >-
                    The campaign name. It must be different from the names of
                    the brand's other campaigns.
                  example: Autumn Roast Launch
                instructions:
                  type: string
                  minLength: 1
                  description: >-
                    What creators must do in their clips. Creators see this
                    text.
                  example: >-
                    Post a 15 to 45 second clip that shows the new autumn roast.
                    Tag @northwind.
                content_type:
                  type: string
                  enum:
                    - logo
                    - clipping
                    - music
                    - ugc
                    - reposting
                  description: >-
                    The kind of clip: `clipping`, `logo`, `music`, `ugc` or
                    `reposting`.
                  example: clipping
                budget_cents:
                  type: integer
                  minimum: 100
                  maximum: 9007199254740991
                  description: >-
                    The budget for clips, in cents. It does not include the
                    ClipStake fee, which you pay when you fund the campaign.
                  example: 500000
                platforms:
                  minItems: 1
                  maxItems: 2
                  type: array
                  items:
                    type: object
                    properties:
                      platform:
                        type: string
                        enum:
                          - instagram
                          - x
                        description: >-
                          The platform: `instagram` or `x`. Geo targeting works
                          with `instagram` only.
                        example: instagram
                      cpm_cents:
                        anyOf:
                          - type: integer
                            exclusiveMinimum: 0
                            maximum: 9007199254740991
                          - type: 'null'
                        description: >-
                          The amount the campaign pays for 1,000 views on this
                          platform, in cents. Required without geo targeting.
                          With geo targeting, send null: the country rates apply
                          instead.
                        example: 200
                    required:
                      - platform
                      - cpm_cents
                    description: A platform and its rate.
                  description: >-
                    The platforms the campaign accepts clips from, each with its
                    rate.
                max_payout_per_clip_cents:
                  type: integer
                  exclusiveMinimum: 0
                  maximum: 9007199254740991
                  description: The most that one clip can earn from the campaign, in cents.
                  example: 50000
                min_views:
                  type: integer
                  exclusiveMinimum: 0
                  maximum: 9007199254740991
                  description: The views a clip must get before it can earn.
                  example: 1000
                max_clips_per_creator:
                  description: >-
                    The most clips one creator can submit to the campaign. Leave
                    it out for no limit.
                  example: 10
                  type: integer
                  exclusiveMinimum: 0
                  maximum: 9007199254740991
                eligibility:
                  default: open
                  description: >-
                    `open`: every creator can find the campaign and submit.
                    `private`: only creators that you invite in the dashboard
                    can submit. The default is `open`.
                  example: open
                  type: string
                  enum:
                    - open
                    - private
                end_date:
                  description: >-
                    When the campaign ends. Omit it for a campaign with no end
                    date.
                  example: '2026-12-31T00:00:00.000Z'
                  type: string
                  format: date-time
                  pattern: >-
                    ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
                thumbnail_url:
                  description: >-
                    The campaign image that creators see. Use an `https` link to
                    a JPEG, PNG or WebP image.
                  example: https://cdn.northwind.example/campaigns/autumn-roast.jpg
                  type: string
                  format: uri
                geo_targeting:
                  default: []
                  description: >-
                    Pay by the country of the viewers. Send `include` rules or
                    one `exclude` rule, never both. Needs `instagram` in
                    `platforms`, and cannot be used with `x`. Leave it out or
                    send an empty list to pay the platform rates for every view.
                  example: []
                  type: array
                  items:
                    type: object
                    properties:
                      kind:
                        type: string
                        enum:
                          - include
                          - exclude
                        description: >-
                          `include`: the campaign pays `cpm_cents` for views
                          from these countries, and nothing for views from other
                          countries. `exclude`: the campaign pays nothing for
                          views from these countries, and `cpm_cents` for views
                          from every other country.
                        example: include
                      cpm_cents:
                        type: integer
                        exclusiveMinimum: 0
                        maximum: 9007199254740991
                        description: >-
                          The amount for 1,000 views, in cents. For `include`,
                          the rate for these countries. For `exclude`, the rate
                          for every country that is not in the list.
                        example: 350
                      countries:
                        minItems: 1
                        type: array
                        items:
                          type: string
                          pattern: ^[A-Z]{2}$
                          example: US
                        description: Two-letter ISO 3166-1 country codes, in upper case.
                        example:
                          - US
                          - CA
                          - GB
                    required:
                      - kind
                      - cpm_cents
                      - countries
                    description: One group of countries and its rate.
                agency_cpm_cents:
                  description: >-
                    Your agency's share of each 1,000 views, in cents. Creators
                    earn every rate less this amount, and the difference goes to
                    your wallet when payouts are released. It must be less than
                    every rate in the campaign. Leave it out to keep no share.
                  example: 20
                  type: integer
                  exclusiveMinimum: 0
                  maximum: 9007199254740991
                resources:
                  default: []
                  description: Files and folders for creators.
                  maxItems: 20
                  type: array
                  items:
                    type: object
                    properties:
                      type:
                        type: string
                        minLength: 1
                        maxLength: 64
                        description: >-
                          What the link is, for example `drive`, `brief` or
                          `audio`.
                        example: drive
                      url:
                        type: string
                        format: uri
                        description: The link to the file or folder.
                        example: https://drive.example.com/northwind-assets
                    required:
                      - type
                      - url
                    description: A file or folder for creators.
              required:
                - brand_id
                - name
                - instructions
                - content_type
                - budget_cents
                - platforms
                - max_payout_per_clip_cents
                - min_views
              description: The campaign to create.
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    pattern: ^cmp_[0-9a-f]{32}$
                    description: Campaign ID.
                    example: cmp_8a1d4e2f6b7c4d9e8f0a1b2c3d4e5f60
                  brand_id:
                    type: string
                    pattern: ^brd_[0-9a-f]{32}$
                    description: Brand ID.
                    example: brd_3f9c0a1b2c3d4e5f60718293a4b5c6d7
                  name:
                    type: string
                    description: The campaign name.
                    example: Autumn Roast Launch
                  slug:
                    type: string
                    description: The short name of the campaign in ClipStake web addresses.
                    example: autumn-roast-launch
                  status:
                    type: string
                    enum:
                      - pending_payment
                      - ready_to_launch
                      - active
                      - paused
                      - ended
                    description: >-
                      `pending_payment`: the budget is not paid yet.
                      `ready_to_launch`: the budget is paid and the campaign is
                      not live yet. `active`: the campaign is live and clips
                      earn. `paused`: the campaign stopped paying for new views.
                      `ended`: the campaign is over.
                    example: active
                  budget_cents:
                    type: integer
                    minimum: -9007199254740991
                    maximum: 9007199254740991
                    description: >-
                      The campaign budget for clips, in cents. It does not
                      include the ClipStake fee.
                    example: 500000
                  platforms:
                    type: array
                    items:
                      type: object
                      properties:
                        platform:
                          type: string
                          description: >-
                            The platform: `instagram`, `x`, `tiktok` or
                            `youtube`. More values can be added. Accept values
                            that you do not know.
                          example: instagram
                        cpm_cents:
                          anyOf:
                            - type: integer
                              minimum: -9007199254740991
                              maximum: 9007199254740991
                            - type: 'null'
                          description: >-
                            The amount the campaign pays for 1,000 views on this
                            platform, in cents. Null when no rate is set. When
                            geo targeting is on, the country rates in
                            `geo_targeting` apply instead.
                          example: 200
                      required:
                        - platform
                        - cpm_cents
                      additionalProperties: false
                      description: A platform that the campaign accepts clips from.
                    description: >-
                      The platforms that the campaign accepts clips from, each
                      with its rate.
                  geo_enabled:
                    type: boolean
                    description: True when the campaign pays by the country of the viewers.
                    example: false
                  geo_targeting:
                    type: array
                    items:
                      type: object
                      properties:
                        kind:
                          type: string
                          enum:
                            - include
                            - exclude
                          description: >-
                            `include`: the campaign pays `cpm_cents` for views
                            from these countries. `exclude`: the campaign does
                            not pay for views from these countries.
                          example: include
                        cpm_cents:
                          anyOf:
                            - type: integer
                              minimum: -9007199254740991
                              maximum: 9007199254740991
                            - type: 'null'
                          description: >-
                            The amount the campaign pays for 1,000 views from
                            these countries, in cents. For an `exclude` rule,
                            this is the rate for views from every country that
                            is not in the list, or null when there is no such
                            rate.
                          example: 350
                        countries:
                          type: array
                          items:
                            type: string
                          description: Two-letter ISO 3166-1 country codes, in upper case.
                          example:
                            - US
                            - CA
                            - GB
                      required:
                        - kind
                        - cpm_cents
                        - countries
                      additionalProperties: false
                      description: One group of countries and its rate.
                    description: >-
                      The country rules of the campaign, `include` rules first,
                      in the order the campaign shows them. A campaign has
                      `include` rules or one `exclude` rule, never both. With
                      `include` rules, views from other countries earn nothing.
                      Empty when geo targeting is off.
                    example: []
                  max_payout_per_clip_cents:
                    type: integer
                    minimum: -9007199254740991
                    maximum: 9007199254740991
                    description: >-
                      The most that one clip can earn from the campaign, in
                      cents.
                    example: 50000
                  pause_threshold_percent:
                    type: integer
                    minimum: -9007199254740991
                    maximum: 9007199254740991
                    description: >-
                      The campaign pauses when its clips have earned this
                      percentage of the budget.
                    example: 90
                  start_date:
                    type: string
                    format: date-time
                    pattern: >-
                      ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
                    description: When the campaign starts.
                    example: '2026-09-15T00:00:00.000Z'
                  end_date:
                    anyOf:
                      - type: string
                        format: date-time
                        pattern: >-
                          ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
                      - type: 'null'
                    description: >-
                      When the campaign ends. Null if the campaign has no end
                      date.
                    example: '2026-10-15T00:00:00.000Z'
                  launched_at:
                    anyOf:
                      - type: string
                        format: date-time
                        pattern: >-
                          ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
                      - type: 'null'
                    description: When the campaign went live. Null if it never went live.
                    example: '2026-09-15T09:00:00.000Z'
                  created_at:
                    type: string
                    format: date-time
                    pattern: >-
                      ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
                    description: When the campaign was created.
                    example: '2026-09-10T14:20:00.000Z'
                  balance:
                    type: object
                    properties:
                      available_cents:
                        type: integer
                        minimum: -9007199254740991
                        maximum: 9007199254740991
                        description: >-
                          The amount that the campaign holds now and has not
                          paid out, in cents.
                        example: 312500
                      paid_gross_cents:
                        type: integer
                        minimum: -9007199254740991
                        maximum: 9007199254740991
                        description: >-
                          The total amount paid out of the campaign for clips,
                          in cents. This is the gross amount that left the
                          campaign budget.
                        example: 187500
                    required:
                      - available_cents
                      - paid_gross_cents
                    additionalProperties: false
                    description: The money in the campaign.
                required:
                  - id
                  - brand_id
                  - name
                  - slug
                  - status
                  - budget_cents
                  - platforms
                  - geo_enabled
                  - geo_targeting
                  - max_payout_per_clip_cents
                  - pause_threshold_percent
                  - start_date
                  - end_date
                  - launched_at
                  - created_at
                  - balance
                additionalProperties: false
                description: A campaign that your agency can read.
              example:
                id: cmp_8a1d4e2f6b7c4d9e8f0a1b2c3d4e5f60
                brand_id: brd_3f9c0a1b2c3d4e5f60718293a4b5c6d7
                name: Autumn Roast Launch
                slug: autumn-roast-launch
                status: pending_payment
                budget_cents: 500000
                platforms:
                  - platform: instagram
                    cpm_cents: 200
                  - platform: x
                    cpm_cents: 150
                geo_enabled: false
                geo_targeting: []
                max_payout_per_clip_cents: 50000
                pause_threshold_percent: 80
                start_date: '2026-10-31T09:12:00.000Z'
                end_date: '2026-11-30T09:12:00.000Z'
                launched_at: null
                created_at: '2026-10-31T09:12:00.000Z'
                balance:
                  available_cents: 0
                  paid_gross_cents: 0
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error.BAD_REQUEST'
              example:
                error:
                  code: invalid_request
                  message: >-
                    Set a CPM for instagram. Without it those submissions would
                    earn nothing.
                  request_id: 6f1c2a9e-4b7d-4c1a-9e2f-3a8b5c7d9e10
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error.UNAUTHORIZED'
              example:
                error:
                  code: unauthorized
                  message: >-
                    Provide a valid API key as `Authorization: Bearer
                    ck_live_...`.
                  request_id: 0b7e4d2c-9a1f-4e3b-8c6d-5f2a1b9c7e34
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error.FORBIDDEN'
              example:
                error:
                  code: forbidden
                  message: >-
                    This API key cannot create campaigns. Create a key with
                    write access in Settings, API keys.
                  request_id: 9e8d7c6b-5a4f-4e3d-8c2b-1a0f9e8d7c65
        '404':
          description: Not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error.NOT_FOUND'
              example:
                error:
                  code: not_found
                  message: No such brand.
                  request_id: 3c9a8b7d-2e1f-4a6b-9c8d-7e6f5a4b3c21
        '409':
          description: Conflict
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error.CONFLICT'
              example:
                error:
                  code: conflict
                  message: A campaign with this name already exists for your brand.
                  request_id: 2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error.INTERNAL_SERVER_ERROR'
              example:
                error:
                  code: internal_error
                  message: An unexpected error occurred.
                  request_id: 5a4b3c2d-1e0f-4a9b-8c7d-6e5f4a3b2c19
        '503':
          description: Service unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/error.SERVICE_UNAVAILABLE'
              example:
                error:
                  code: unavailable
                  message: >-
                    ClipStake is undergoing scheduled maintenance. Try again
                    shortly.
                  request_id: 7c6b5a4f-3e2d-4c1b-9a8f-7e6d5c4b3a29
      security:
        - Authorization: []
components:
  schemas:
    error.BAD_REQUEST:
      type: object
      title: Bad request error (400)
      description: The error envelope every failed request returns.
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - invalid_request
              description: A stable, machine-readable error code.
            message:
              type: string
              description: What went wrong, in words a person can act on.
            request_id:
              type: string
              description: The id of this request. Quote it when you contact support.
          required:
            - code
            - message
            - request_id
          additionalProperties: false
      required:
        - error
      additionalProperties: false
    error.UNAUTHORIZED:
      type: object
      title: Unauthorized error (401)
      description: The error envelope every failed request returns.
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - unauthorized
              description: A stable, machine-readable error code.
            message:
              type: string
              description: What went wrong, in words a person can act on.
            request_id:
              type: string
              description: The id of this request. Quote it when you contact support.
          required:
            - code
            - message
            - request_id
          additionalProperties: false
      required:
        - error
      additionalProperties: false
    error.FORBIDDEN:
      type: object
      title: Forbidden error (403)
      description: The error envelope every failed request returns.
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - forbidden
              description: A stable, machine-readable error code.
            message:
              type: string
              description: What went wrong, in words a person can act on.
            request_id:
              type: string
              description: The id of this request. Quote it when you contact support.
          required:
            - code
            - message
            - request_id
          additionalProperties: false
      required:
        - error
      additionalProperties: false
    error.NOT_FOUND:
      type: object
      title: Not found error (404)
      description: The error envelope every failed request returns.
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - not_found
              description: A stable, machine-readable error code.
            message:
              type: string
              description: What went wrong, in words a person can act on.
            request_id:
              type: string
              description: The id of this request. Quote it when you contact support.
          required:
            - code
            - message
            - request_id
          additionalProperties: false
      required:
        - error
      additionalProperties: false
    error.CONFLICT:
      type: object
      title: Conflict error (409)
      description: The error envelope every failed request returns.
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - conflict
              description: A stable, machine-readable error code.
            message:
              type: string
              description: What went wrong, in words a person can act on.
            request_id:
              type: string
              description: The id of this request. Quote it when you contact support.
          required:
            - code
            - message
            - request_id
          additionalProperties: false
      required:
        - error
      additionalProperties: false
    error.INTERNAL_SERVER_ERROR:
      type: object
      title: Internal server error error (500)
      description: The error envelope every failed request returns.
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - internal_error
              description: A stable, machine-readable error code.
            message:
              type: string
              description: What went wrong, in words a person can act on.
            request_id:
              type: string
              description: The id of this request. Quote it when you contact support.
          required:
            - code
            - message
            - request_id
          additionalProperties: false
      required:
        - error
      additionalProperties: false
    error.SERVICE_UNAVAILABLE:
      type: object
      title: Service unavailable error (503)
      description: The error envelope every failed request returns.
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - unavailable
              description: A stable, machine-readable error code.
            message:
              type: string
              description: What went wrong, in words a person can act on.
            request_id:
              type: string
              description: The id of this request. Quote it when you contact support.
          required:
            - code
            - message
            - request_id
          additionalProperties: false
      required:
        - error
      additionalProperties: false
  securitySchemes:
    Authorization:
      type: http
      scheme: bearer

````

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