openapi: 3.0.3
info:
  title: b00st.com Campaign API
  version: "20261015"
  description: Create, update and report on b00st.com ad campaigns. Each API token is scoped to one
    organization; request one from developers@b00st.com.
  contact:
    name: b00st.com developers
    email: developers@b00st.com
servers:
  - url: https://app.b00st.com
    description: Production server
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  schemas:
    Campaign:
      type: object
      properties:
        id:
          type: integer
          example: 123
        pid:
          type: string
          example: abcdefgh
        adTitle:
          type: string
          example: My Campaign
        isActive:
          type: boolean
          example: true
        spend:
          type: number
          format: float
          example: 150.5
    CampaignCreateRequest:
      type: object
      required:
        - targetLink
      properties:
        targetLink:
          type: string
          maxLength: 500
          description: Destination URL. A link without a protocol gets https://.
        adTitle:
          type: string
          description: Campaign title
        budget:
          type: integer
          minimum: 0
          default: 0
          description: Ad budget in whole dollars, stored as sent (fees are not taken out)
        adDescription:
          type: string
          description: Primary ad copy text
        adCallToAction:
          type: string
          description: Call to action text
        adButtonText:
          type: string
          description: Button label
        adExtraDescription:
          type: string
          description: Extended description
        isFlat:
          allOf:
            - $ref: "#/components/schemas/FlexibleBoolean"
          description: Flat-rate pricing (fees included in the customer's total). Defaults to false.
        startDate:
          type: string
          format: date-time
          description: "Start date (default: now)"
        endDate:
          type: string
          format: date-time
          description: End date
        creativeUrls:
          oneOf:
            - type: string
            - type: array
              items:
                type: string
          description: URL(s) of ad creatives
    FlexibleBoolean:
      oneOf:
        - type: boolean
        - type: string
          enum:
            - "true"
            - "false"
        - type: integer
          enum:
            - 0
            - 1
    CampaignUpdateRequest:
      type: object
      description: One of pid or pids is required. Unknown fields, and fields sent with a value that can't
        be used, are rejected with 400. Empty strings, empty arrays and null (except where noted)
        count as not sent.
      additionalProperties: false
      properties:
        pid:
          type: string
          description: Target single campaign PID
        pids:
          type: array
          items:
            type: string
          description: Target multiple campaign PIDs
        adTitle:
          type: string
        adDescription:
          type: string
          nullable: true
          description: Primary copy (stored as copyOption1); null clears it
        copyOption2:
          type: string
          description: Second copy option
        adCallToAction:
          type: string
          description: Call to action (stored as callToAction)
        adButtonText:
          type: string
          description: Button text (stored as buttonText)
        adExtraDescription:
          type: string
        targetLink:
          type: string
          maxLength: 500
          description: Destination URL. Also repoints the campaign's Dub short link (the short link itself
            doesn't change). A link without a protocol gets https://.
        shortLink:
          type: string
          description: Short link URL stored on the campaign
        budget:
          type: number
        isFlat:
          type: boolean
        startDate:
          type: string
          format: date-time
        endDate:
          type: string
          format: date-time
          nullable: true
          description: null clears it
        platforms:
          type: array
          items:
            type: string
          description: Replaces platform list (e.g. ["google", "meta"])
        category:
          type: array
          items:
            type: string
          description: Replaces category list
        creativeUrls:
          type: array
          items:
            type: string
          description: Appends new creative URLs to the existing list
    CampaignUpdateResponse:
      type: object
      required:
        - message
        - updated
        - notFound
      properties:
        message:
          type: string
          example: Campaign(s) updated successfully
        updated:
          type: array
          items:
            type: string
          example:
            - abcdefgh
            - bcdefghi
        notFound:
          type: array
          items:
            type: string
          description: Requested PIDs that matched no campaign the caller can access
          example:
            - zzzzzzzz
        links:
          type: array
          description: Present only when targetLink was sent. "failed" means the campaign has the new
            targetLink but its short link still points to the old one; resend the same request to
            retry.
          items:
            type: object
            required:
              - pid
              - status
            properties:
              pid:
                type: string
              status:
                type: string
                enum:
                  - updated
                  - not_found
                  - failed
    InvalidPayloadError:
      type: object
      properties:
        error:
          type: string
          example: Invalid payload
        fields:
          type: array
          items:
            type: string
          example:
            - campaignCount
        details:
          type: object
          additionalProperties: true
    AnalyticsResponse:
      type: object
      additionalProperties:
        type: array
        items:
          type: object
          properties:
            clicks:
              type: integer
            impressions:
              type: integer
            spend:
              type: number
              format: float
            date:
              type: string
              format: date
            platform:
              type: string
      example:
        meta:
          - clicks: 100
            impressions: 5000
        google: []
security:
  - bearerAuth: []
paths:
  /api/20261015/campaigns:
    get:
      summary: Retrieve a paginated list of campaigns
      parameters:
        - name: length
          in: query
          schema:
            type: integer
            default: 20
          description: Number of records to return
        - name: cursor
          in: query
          schema:
            oneOf:
              - type: integer
              - type: string
          description: Pointer for pagination (last seen ID)
        - name: pid
          in: query
          schema:
            type: array
            items:
              type: string
          style: form
          explode: true
          description: Filter by one or more Campaign PIDs
        - name: orgId
          in: query
          schema:
            type: array
            items:
              type: string
          style: form
          explode: true
          description: Filter by Organization ID
      responses:
        "200":
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Campaign"
                  cursor:
                    oneOf:
                      - type: integer
                      - type: string
    post:
      summary: Create a new campaign
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CampaignCreateRequest"
      responses:
        "200":
          description: Campaign created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: Campaign created successfully
                  pid:
                    type: string
                    example: abcdefgh
        "400":
          description: Invalid payload (e.g. missing targetLink)
        "401":
          description: Unauthorized
        "500":
          description: Failed to create campaign
    put:
      summary: Update one or more campaigns
      description: Applies the same changes to every listed campaign. Changing targetLink also repoints
        each campaign's short link. Tokens can only update campaigns in their own organization.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CampaignUpdateRequest"
      responses:
        "200":
          description: Campaign(s) updated successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CampaignUpdateResponse"
        "400":
          description: Missing pid(s), or unknown, invalid or unusable fields
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InvalidPayloadError"
        "401":
          description: Unauthorized
        "403":
          description: The request included a field your token can't change; nothing was changed
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: Forbidden
                  fields:
                    type: array
                    items:
                      type: string
                    example:
                      - organizationId
        "404":
          description: None of the PIDs matched a campaign the caller can access
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: No matching campaigns
                  notFound:
                    type: array
                    items:
                      type: string
        "500":
          description: Failed to update campaign(s)
    delete:
      summary: Delete one or more campaigns
      parameters:
        - name: pid
          in: query
          required: true
          schema:
            type: array
            items:
              type: string
          style: form
          explode: true
          description: Campaign PID(s) to delete
      responses:
        "200":
          description: Successful deletion
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: string
                    example:
                      - abcdefgh
  /api/20261015/campaigns/data:
    get:
      summary: Retrieve aggregated summary stats for all supported platforms
      description: API-key-authenticated callers are rate limited and receive HTTP 429 with a Retry-After
        header when they exceed the configured limit.
      parameters:
        - name: pid
          in: query
          required: true
          schema:
            type: array
            items:
              type: string
          style: form
          explode: true
          description: Campaign PID(s) to fetch data for
      responses:
        "200":
          description: Aggregated stats
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AnalyticsResponse"
        "429":
          description: Too many requests for an API key caller
    post:
      summary: Retrieve aggregated summary stats (body PIDs)
      description: API-key-authenticated callers are rate limited and receive HTTP 429 with a Retry-After
        header when they exceed the configured limit.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - pids
              properties:
                pids:
                  type: array
                  items:
                    type: string
                  description: Array of Campaign PIDs
      responses:
        "200":
          description: Aggregated stats
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AnalyticsResponse"
        "429":
          description: Too many requests for an API key caller
  /api/20261015/campaigns/data/{platform}:
    parameters:
      - name: platform
        in: path
        required: true
        schema:
          type: string
          enum:
            - google
            - meta
            - tiktok
            - reddit
            - snap
            - dooh
            - dub
        description: The platform identifier
    get:
      summary: Retrieve aggregated summary stats for a single platform
      description: API-key-authenticated callers are rate limited and receive HTTP 429 with a Retry-After
        header when they exceed the configured limit.
      parameters:
        - name: pid
          in: query
          required: true
          schema:
            type: array
            items:
              type: string
          style: form
          explode: true
          description: Campaign PID(s) to fetch data for
      responses:
        "200":
          description: Stats for single platform
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
        "429":
          description: Too many requests for an API key caller
    post:
      summary: Retrieve detailed timeseries or platform-specific analytics
      description: For non-Dub platforms, this returns timeseries-compatible data. API-key-authenticated
        callers are rate limited and receive HTTP 429 with a Retry-After header when they exceed the
        configured limit.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - pids
              properties:
                pids:
                  type: array
                  items:
                    type: string
                  description: Array of Campaign PIDs
      responses:
        "200":
          description: Detailed analytics data
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        date:
                          type: string
                          format: date
                        clicks:
                          type: integer
                        impressions:
                          type: integer
                      additionalProperties: true
        "429":
          description: Too many requests for an API key caller
