DOCUMENTATION / API REFERENCE

Campaign lifecycle

Immutable plans, bounded budgets, and explicit provider reconciliation.

Markdown

Create a plan

POST /api/v1/campaigns requires campaigns:write and Idempotency-Key. The key contains 8–128 letters, digits, dots, colons, underscores, or hyphens. Reusing it with identical normalized input returns the existing campaign; different input returns idempotency_conflict. Keep the key across timeouts.

A live plan requires a ready creative assigned to this owner, the assigned Facebook Page, and a destination within the approved HTTPS origin.

{
  "name": "Bookkeeping launch",
  "url": "https://example.com/pricing",
  "objective": "purchase",
  "budget_cents": 50000,
  "currency": "USD",
  "geo": ["US"],
  "target_cac_cents": 4000,
  "mode": "live",
  "meta": {
    "starts_at": "2030-01-02T12:00:00Z",
    "ends_at": "2030-01-09T12:00:00Z",
    "headline": "Bookkeeping that keeps up",
    "primary_text": "See how it works for your business.",
    "creative_file_id": "file_REPLACE",
    "facebook_social_account_id": "sacc_REPLACE"
  }
}

Replace the example dates and resource IDs. Start at least five minutes in the future; duration must be 24 hours to 30 days. Budget bounds are 100–10000000 cents. Geography uses 1–20 uppercase ISO country codes. A supplied conversion_event must match the objective: purchase→purchase, signup→signup, traffic→page_view. target_cac_cents is a planning target, not an enforced acquisition guarantee.

Plans are immutable. A changed destination, creative, copy, schedule, geography, or budget requires a new campaign and approval. The response contains plan_hash, approval_url, mode, status, and provider resource IDs once prepared.

Prepare, approve, observe

Local stateMeaning / next action
awaiting_approvalStored locally. Live: call prepare. Sandbox: request owner approval.
preparingProvider draft submission in progress or outcome uncertain. Retry the same prepare operation within its retry window.
draftNon-delivering Whop hierarchy exists; owner can inspect the exact plan.
launchingOwner approved and budget reserved; activation is in progress or uncertain. Reconcile.
activeConfigured active or in review. Check delivery_status for actual network delivery.
pausingPause request in progress or uncertain. Reconcile.
pausedWhop confirmed pause. Accrued costs remain payable.
attention_requiredProvider rejection, mismatch, or another issue requires review.
completedProvider reports completed delivery.

POST /api/v1/campaigns/{id}/prepare creates one Whop draft, ad group, and ad. It does not enable spending. Owner approval uses a separate endpoint. POST /api/v1/campaigns/{id}/reconcile retrieves current provider state and metrics. GET endpoints return persisted snapshots and do not poll Whop implicitly.

Pause and retry

POST /api/v1/campaigns/{id}/pause requires campaigns:write. It waits for provider confirmation. A timeout is not a successful pause. Reconcile and retain the original campaign; do not make a duplicate launch. Provider mutations use durable operation keys and no automatic network retries. After 23 hours an ambiguous POST needs operator reconciliation rather than a new idempotency key.

There is no resume or edit operation in this release. A new campaign needs a new plan and owner approval. Reserved budget is not automatically released on pause: provider spend can arrive late.

Read and paginate

GET /api/v1/campaigns?limit=20 returns data.items and data.next_cursor. Pass the returned cursor with the same limit for the next page. Limits are 1–100; order is descending campaign UUID, not chronological. GET /api/v1/campaigns/{id} returns one owner-scoped record; foreign IDs return 404.