Skip to main content
Whop Ads runs paid ads on networks like Meta directly from your Whop account. You fund campaigns from your balance; Whop handles the ad account, review, launch, and billing. Two API calls take you from nothing to a live ad: generate a creative, then create the campaign, ad group, and ad in one request.

Resources

One-time setup

  • Scopes: media:generate, media:read, ad_campaign:create, ad_campaign:update, ad_campaign:basic:read, social_account:read.
  • Facebook page: GET /social_accounts must have a "platform": "facebook" entry. If not, link your Meta Business account with POST /social_accounts/connect {"platform": "meta_business", "scopes": ["advertise"], "redirect_url": "..."} → send the user to the returned authorize_url — or, if you don’t have a page at all, have Whop create one with POST /social_accounts {"platform": "facebook"}.
  • Ads payment method: connected in the dashboard (balance or card). Only launching needs it — drafts work without.
1

Generate a creative

Billed from your balance (amount_charged; not enough balance → 402 with a deposit_url). Poll GET /media/{id} until status is ready, then use file.id:
failed refunds the charge — tweak the prompt and retry. Video: "type": "video" plus optional duration_seconds (5/10/15), resolution (480p4k), and up to 4 reference_media file IDs (first one seeds the opening frame).
2

Create and launch the ad — one request

POST /ads with an inline ad_group and ad_campaign creates the whole tree in one transaction and launches it:
Not ready to spend? Add "status": "draft" to ad_campaign, then launch later with PATCH /ad_campaigns/{id} {"status": "active"}.To reuse existing containers, pass ad_group_id instead of ad_group, or ad_campaign_id instead of ad_campaign.
3

Monitor

Poll GET /ads/{id}: delivery_status is the live state (a brief in_review for content moderation is normal), and issues[] carries a human-readable message for anything Meta rejected asynchronously.Control delivery with pause / unpause on ads, ad groups, or campaigns. Edit copy or creatives with PATCH /ads/{id} — sending creatives replaces the whole set, so include the base entry.

Errors

Every gate is a 400 whose message says what to fix: