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: