Bloss Docs

Campaign pairs (per-post rows)

Developers
GET
/campaign/pairs

One row per video pair — a creator's post, or the 1–3 cross-posted videos that share a single payout — for the given cycles. This is the layer underneath GET /campaign/summary and GET /campaign/tags: per-pair totalSpend and views sum to the campaign figures those endpoints report for the same cycles. Each row carries the creator, the pair's tag ids, its money (basePay + cpmBonus = totalSpend), and a videos array with the platform, post URL, posted-at, and engagement of every video in the pair.

Engagement comes from the latest snapshot inside the cycle window — the same rows the campaign totals count. A video with no in-cycle snapshot has snapshotDate: null and zeroed metrics, and is not counted by any campaign endpoint; countedVideos is how many of the pair's videos did count.

tagIds filters which pairs come back (pair tags carry the money); each returned pair still reports all of its own videos.

groupIds filters by the pair's creator instead — the creator groups from GET /groups. Filters compose as an AND (groupIds plus tagIds means both), while ids within one filter are ANY. Every row also carries creator.groupIds, so one unfiltered pass can be bucketed by group client-side.

Results are ordered by (updatedAt, pairId) ascending and paged with the opaque nextCursor. Pass updatedSince with the largest updatedAt you have already stored to pull only what changed since — updatedAt moves whenever the pair is re-paired, re-assigned, or its payout is recalculated (which is what a view refresh triggers).

Authorization

headerAuthorizationBearer <token>

Provide your API key as Authorization: Bearer <key>.

Query Parameters

cycleIds*string

Comma-separated cycle ids to include in the campaign.

tagIds?string

Comma-separated tag ids. Returns only pairs carrying at least one of these tags. Get tag ids from GET /campaign/tags.

groupIds?string

Comma-separated creator-group ids. Returns only pairs whose creator is in at least one of these groups. Get group ids from GET /groups. Pass the literal __ungrouped__ to include creators that are in no group at all; it may be combined with real group ids (the two populations are unioned). An id that is not one of your brand's groups is a 400, never a silently empty page.

creatorId?string

Return only this creator's pairs.

updatedSince?string

ISO-8601 timestamp. Returns only pairs whose updatedAt is strictly greater — the incremental-sync cursor.

Formatdate-time
limit?integer

Rows per page (1–500). Defaults to 100.

Range1 <= value <= 500
Default100
cursor?string

The nextCursor from the previous response. Omit for the first page.

Response Body

A page of pairs.

application/json
  1. response
currency?string
pairs?array<>
nextCursor?|

Pass as cursor for the next page; null on the last page.

hasMore?boolean
curl -X GET 'https://example.com/api/v0/campaign/pairs?cycleIds=cyc_abc%2Ccyc_def&groupIds=grp_abc%2Cgrp_def&updatedSince=2026-07-01T00%3A00%3A00Z'
{  "currency": "string",  "pairs": [    {      "pairId": "string",      "cycleId": "string",      "creator": {        "creatorId": "string",        "name": "string",        "handles": {          "instagram": "string",          "tiktok": "string",          "youtube": "string",          "facebook": "string"        },        "groupIds": [          "string"        ]      },      "firstVideoAt": "2019-08-24T14:15:22Z",      "videoCount": 0,      "countedVideos": 0,      "views": 0,      "likes": 0,      "comments": 0,      "shares": 0,      "saves": 0,      "basePay": 0,      "cpmBonus": 0,      "totalSpend": 0,      "excludedFromPayout": true,      "tagIds": [        "string"      ],      "updatedAt": "2019-08-24T14:15:22Z",      "videos": [        {          "videoId": "string",          "platform": "string",          "handle": "string",          "postUrl": "string",          "postedAt": "2019-08-24T14:15:22Z",          "snapshotDate": "2019-08-24",          "views": 0,          "likes": 0,          "comments": 0,          "shares": 0,          "saves": 0        }      ]    }  ],  "nextCursor": "string",  "hasMore": true}

Was this page helpful?