Resources
Billing and payment recovery
Spend is collected at account level across campaigns. A failed payment blocks delivery withdelivery_status: "payment_failed" while preserving each campaign’s configured active/paused status. Fix the account’s payment method, then call Retry Failed Ads Payments once for the account. The response queues a background attempt; it does not confirm payment. After settlement, active campaigns can resume and paused campaigns stay paused, subject to other delivery requirements.
See Paying for ads for the dashboard flow, request example, duplicate-request behavior, and legacy campaign handling.
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_accountsmust have a"platform": "facebook"entry. If not, link your Meta Business account withPOST /social_accounts/connect{"platform": "meta_business", "scopes": ["advertise"], "redirect_url": "..."}→ send the user to the returnedauthorize_url— or, if you don’t have a page at all, have Whop create one withPOST /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
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 (480p–4k), 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:"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 a400 whose message says what to fix:

