Campaigns

Create a campaign

Create a Retainer / Challenge / Leaderboard / Live GMV Challenge campaign. X-Dry-Run: true validates the body and echoes what would be submitted without writing any rows. Image fields take HTTPS URL strings — host the image yourself and pass the URL.

The 201 response includes an invite_link field — the public URL the caller can share with creators to bring them into the campaign. Subdomain is picked by creator_source: legacy social_army campaigns use https://soco.reacherapp.com; everything else (my_community, etc.) uses https://creator.reacherapp.com. Full pattern: {base}/campaigns/{shop_id}/{uuid_id}. Every campaign endpoint that returns a campaign payload carries the same field — POST, GET list, GET single, GET detail — so callers can lift it directly without constructing the URL themselves.

post/campaigns

Headers

Idempotency-Keystring nullable
X-Dry-Runstring nullable

Request body

campaign_namestring required
campaign_type'retainer' | 'challenge' | 'leaderboard' | 'live_gmv_challenge' | 'race' | 'bingo' | 'sweepstakes' required

Supported campaign types.

creator_source'my_community' | 'social_army' required

How creators are sourced for a campaign.

start_datestring required
end_datestring nullable

YYYY-MM-DD. REQUIRED for challenge / leaderboard / live_gmv_challenge campaigns (the portal launch form requires an end date for these); optional only for retainer campaigns, which may run open-ended.

descriptionstring nullable

REQUIRED for launch. Rich-text (HTML) campaign description shown to creators. Must contain visible text — an empty string or HTML-only value like '<p></p>' is rejected, matching the portal launch form.

status'published' | 'draft' | 'deleted' | 'archived'

DB-level campaign status. The frontend filter param 'active'/'past' are UI aliases — 'active' maps to published, 'past' maps to != published.

creatorsobject[] nullable

Optional list of creators to seed into the campaign. Mirrors the portal's contract exactly (see community.schemas.campaign.CampaignCreate.creators) so the public API doesn't fork from /api/marketplace/v2. Each dict is opaque to validation but is typically {"creator_id": int, "tier": str | None, "payout_override": int | None}. Pass null or omit for the common case of "no seeded creators" (production fixtures all do this; creators are added later via the accept/reject flow).

window_urlstring nullable

HTTPS URL — public landing/preview page for this campaign.

is_available_to_allboolean
requires_approvalboolean
exclusive_participationboolean

While on, a creator active in another overlapping campaign of this shop cannot be activated here (and vice versa).

support_emailstring nullable
short_header_messagestring nullable

REQUIRED for launch. Short headline shown on the campaign card. Must be a non-empty string — the portal launch form rejects a blank value.

content_guidelinesobject nullable
inspiration_linksstring[] nullable

List of HTTPS URLs (inspiration videos, mood-boards, etc.).

has_tiered_payoutboolean
payout_structureobject nullable
grace_periodinteger nullable

Response

Dry-run echo (no campaign created).

Changes

No recorded changes to this endpoint across all 1 revision of this API.