Skip to main content
Crosspost groups connect versions of the same content posted to different platforms by one campaign creator. These endpoints group existing tracked posts; they do not publish content to social networks. Use the campaignCreatorRecordId returned by the campaign creator list. Every request requires X-Application-Id and X-Api-Key. The record, target group, and all supplied posts must belong to your agency and the same campaign creator.

Automatic grouping and caption matching

Automatic detection normally uses your agency’s detection settings, such as the upload window and duration tolerance in UPLOAD_WINDOW mode. A contract’s caption grouping rule changes how matching posts are grouped. Set contract.crosspostRequirements.captionContains when creating a contract version. In the complete terms snapshot, the equivalent field is crosspost.captionFilter. The contract version governing each post’s upload business date supplies this rule. For example, "captionContains": "#launch" groups matching posts for the same campaign creator and the same configured filter by local calendar day. Grade determines that day from the post’s upload timestamp using:
  1. The campaign’s timeZone, when set.
  2. The agency’s timezone, when the campaign has no override.
  3. UTC, when neither is set.
Set the campaign override through the campaign endpoints. This is a midnight-to-midnight calendar day, including daylight-saving changes. It is not a rolling 24-hour window. For example, with America/Los_Angeles, uploads at 2026-09-17T23:30:00Z and 2026-09-18T01:00:00Z both belong to September 17 locally. Uploads on opposite sides of local midnight belong to different caption groups, even when they are only minutes apart.
Caption grouping overrides the normal upload-window and duration-tolerance checks for matching posts. With a six-hour window configured, two matching posts 20 hours apart can still join the same group if they share the local calendar day. This rule also allows multiple posts from the same platform. Reusing a campaign-wide hashtag for several distinct videos in one day can therefore combine those videos and affect payments configured per group.
Matching is case-insensitive, and a leading # or @ in a token is ignored. Comma-separated tokens match any listed token; they do not create separate groups for each token. Posts that do not match continue through normal automatic detection. Set captionContains to null to disable this override in a contract version. If you only want to choose which posts to track from an account, use media[].captionFilter when adding that account. That tracking filter does not enable caption-based grouping. To correct an existing group, use the manual membership and split operations below.

Reads

The base path for the five endpoints below is:

GET /

List groups ordered by group ID. Query parameters are page (default 1, maximum 1000000) and limit (default 50, maximum 100). Both must be positive whole numbers. Unknown parameters are rejected.
source is AUTO, MANUAL, MIXED, or null for legacy groups without a recorded source. MIXED means members have different sources. Names are generated display labels; use the opaque group ID to reference a group. Automatic groups and names can change after detection runs. The existing creator media endpoint still supports includeGroups=true and returns richer media/performance summaries. This direct list provides independent group pagination and a version for safe edits.

GET /:crosspostGroupId/posts

Read a group’s members ordered by media ID, with the same page and limit parameters. Both directly tracked posts and posts discovered from tracked accounts are included. Account rows, deleted posts, and retired posts are excluded.
Each item in data includes: The response also includes pagination and membershipVersion, as in the group list. Missing or out-of-scope groups return 404. A valid group with an out-of-range page returns an empty data array.

Writes and retries

All three writes require X-Idempotency-Key (1–255 characters). Generate a key once for each logical operation and reuse it with the same body after a timeout or retryable error. Completed responses are retained for 24 hours, scoped to your application, agency, campaign creator, and operation. A replay returns the original status/body and X-Idempotent-Replay: true; a changed payload with the same key returns 409 IDEMPOTENCY_CONFLICT. Optionally send expectedMembershipVersion from a read or the previous write. A stale version returns 409 MEMBERSHIP_CONFLICT without changing any posts. Read again and submit your revised operation with a new key. The version covers the creator’s active membership; it is separate from scrape freshness. Each batch is atomic. If any post or target group is invalid, no membership changes are committed. Writes reject account rows, deleted/retired posts, and completed campaigns. Each write supports creators with up to 5,000 active posts; create and membership batches accept at most 500 distinct media IDs.

POST /

Create a populated group from a non-empty campaignCreatorMediaIds array. A post may move from an existing group. A one-post manual group is allowed; its existence does not establish payout eligibility.
Returns 201 with a server-assigned group ID. Creation and all assignments happen together; no separate request is needed to attach the posts.

PATCH /memberships

Send a non-empty assignments array. Every media ID must appear once. Choose one of these states for each post:
Automatic detection runs after the assignments. A manual exclusion survives future recomputes. Resetting to AUTO removes that override and evaluates the post immediately; it may remain ungrouped if there is no match or insufficient metadata. An ungrouped automatic candidate can have a null source. To dissolve a group, manually ungroup all its members. This keeps the tracked content. To split a group, create a new group from the selected members.

POST /recompute

Rerun automatic grouping for this campaign creator. Send {} or an object containing expectedMembershipVersion. Uses the agency’s current detection settings and applicable contract caption rules. Caption grouping uses the current campaign → agency → UTC timezone fallback described above, so changing the timezone can change automatic membership on the next recompute. Manual assignments and exclusions are preserved. This operation does not scrape fresh post metadata or reset manual overrides.

Write response

All writes complete membership changes before responding. Creation also includes crosspostGroupId; membership updates and recompute return 200.
memberships contains the posts supplied to create/update, in media-ID order. For recompute it is empty: use the reads to fetch current groups and members. recompute.updated counts automatic changes, not the supplied manual assignments. The operation may also change other automatic groups in this creator record. Calculated dashboard summaries refresh through a durable background queue. For monetary results, use the existing line items or payout preview endpoints. Group membership changes preserve established payment ownership. A merge of posts with different established payment-group owners returns 409 PAYMENT_GROUP_CONFLICT and rolls back. Safe splits and manual exclusions preserve their original payment history. Configure payment rules through contract versions.

Error responses

Errors use { "success": false, "code": "...", "message": "..." }. Authentication failures use the standard SDK authentication response.