Skip to main content
POST
/
ads
Create an Ad
curl --request POST \
  --url https://api.whop.com/api/v1/ads \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "ad_group": {},
  "ad_group_id": "<string>",
  "creatives": [
    {
      "crop": {
        "height": 123,
        "width": 123,
        "x": 123,
        "y": 123
      },
      "id": "<string>"
    }
  ],
  "descriptions": [
    "<string>"
  ],
  "headlines": [
    "<string>"
  ],
  "lead_form": {
    "completion": {
      "button_text": "<string>",
      "description": "<string>",
      "headline": "<string>",
      "url": "<string>"
    },
    "disclaimer": {
      "body": "<string>",
      "checkboxes": [
        {
          "checked_by_default": true,
          "key": "<string>",
          "required": true,
          "text": "<string>"
        }
      ],
      "title": "<string>"
    },
    "intro": {
      "description": "<string>",
      "headline": "<string>"
    },
    "name": "<string>",
    "phone_verification": true,
    "privacy_policy": {
      "link_text": "<string>",
      "url": "<string>"
    },
    "questions": [
      {
        "label": "<string>",
        "options": [
          {
            "key": "<string>",
            "logic": {
              "target_end_page_index": 123,
              "target_question_index": 123
            },
            "value": "<string>"
          }
        ]
      }
    ]
  },
  "lead_form_id": "<string>",
  "messaging_config": {
    "keyword": "<string>",
    "message": "<string>"
  },
  "multi_advertiser_ads": true,
  "post_id": "<string>",
  "primary_texts": [
    "<string>"
  ],
  "social_accounts": [
    {
      "id": "<string>"
    }
  ],
  "title": "<string>",
  "url": "<string>",
  "url_parameters": {}
}
'
import requests

url = "https://api.whop.com/api/v1/ads"

payload = {
"ad_group": {},
"ad_group_id": "<string>",
"creatives": [
{
"crop": {
"height": 123,
"width": 123,
"x": 123,
"y": 123
},
"id": "<string>"
}
],
"descriptions": ["<string>"],
"headlines": ["<string>"],
"lead_form": {
"completion": {
"button_text": "<string>",
"description": "<string>",
"headline": "<string>",
"url": "<string>"
},
"disclaimer": {
"body": "<string>",
"checkboxes": [
{
"checked_by_default": True,
"key": "<string>",
"required": True,
"text": "<string>"
}
],
"title": "<string>"
},
"intro": {
"description": "<string>",
"headline": "<string>"
},
"name": "<string>",
"phone_verification": True,
"privacy_policy": {
"link_text": "<string>",
"url": "<string>"
},
"questions": [
{
"label": "<string>",
"options": [
{
"key": "<string>",
"logic": {
"target_end_page_index": 123,
"target_question_index": 123
},
"value": "<string>"
}
]
}
]
},
"lead_form_id": "<string>",
"messaging_config": {
"keyword": "<string>",
"message": "<string>"
},
"multi_advertiser_ads": True,
"post_id": "<string>",
"primary_texts": ["<string>"],
"social_accounts": [{ "id": "<string>" }],
"title": "<string>",
"url": "<string>",
"url_parameters": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
ad_group: {},
ad_group_id: '<string>',
creatives: [{crop: {height: 123, width: 123, x: 123, y: 123}, id: '<string>'}],
descriptions: ['<string>'],
headlines: ['<string>'],
lead_form: {
completion: {
button_text: '<string>',
description: '<string>',
headline: '<string>',
url: '<string>'
},
disclaimer: {
body: JSON.stringify('<string>'),
checkboxes: [{checked_by_default: true, key: '<string>', required: true, text: '<string>'}],
title: '<string>'
},
intro: {description: '<string>', headline: '<string>'},
name: '<string>',
phone_verification: true,
privacy_policy: {link_text: '<string>', url: '<string>'},
questions: [
{
label: '<string>',
options: [
{
key: '<string>',
logic: {target_end_page_index: 123, target_question_index: 123},
value: '<string>'
}
]
}
]
},
lead_form_id: '<string>',
messaging_config: {keyword: '<string>', message: '<string>'},
multi_advertiser_ads: true,
post_id: '<string>',
primary_texts: ['<string>'],
social_accounts: [{id: '<string>'}],
title: '<string>',
url: '<string>',
url_parameters: {}
})
};

fetch('https://api.whop.com/api/v1/ads', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://api.whop.com/api/v1/ads",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'ad_group' => [

],
'ad_group_id' => '<string>',
'creatives' => [
[
'crop' => [
'height' => 123,
'width' => 123,
'x' => 123,
'y' => 123
],
'id' => '<string>'
]
],
'descriptions' => [
'<string>'
],
'headlines' => [
'<string>'
],
'lead_form' => [
'completion' => [
'button_text' => '<string>',
'description' => '<string>',
'headline' => '<string>',
'url' => '<string>'
],
'disclaimer' => [
'body' => '<string>',
'checkboxes' => [
[
'checked_by_default' => true,
'key' => '<string>',
'required' => true,
'text' => '<string>'
]
],
'title' => '<string>'
],
'intro' => [
'description' => '<string>',
'headline' => '<string>'
],
'name' => '<string>',
'phone_verification' => true,
'privacy_policy' => [
'link_text' => '<string>',
'url' => '<string>'
],
'questions' => [
[
'label' => '<string>',
'options' => [
[
'key' => '<string>',
'logic' => [
'target_end_page_index' => 123,
'target_question_index' => 123
],
'value' => '<string>'
]
]
]
]
],
'lead_form_id' => '<string>',
'messaging_config' => [
'keyword' => '<string>',
'message' => '<string>'
],
'multi_advertiser_ads' => true,
'post_id' => '<string>',
'primary_texts' => [
'<string>'
],
'social_accounts' => [
[
'id' => '<string>'
]
],
'title' => '<string>',
'url' => '<string>',
'url_parameters' => [

]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
"fmt"
"strings"
"net/http"
"io"
)

func main() {

url := "https://api.whop.com/api/v1/ads"

payload := strings.NewReader("{\n \"ad_group\": {},\n \"ad_group_id\": \"<string>\",\n \"creatives\": [\n {\n \"crop\": {\n \"height\": 123,\n \"width\": 123,\n \"x\": 123,\n \"y\": 123\n },\n \"id\": \"<string>\"\n }\n ],\n \"descriptions\": [\n \"<string>\"\n ],\n \"headlines\": [\n \"<string>\"\n ],\n \"lead_form\": {\n \"completion\": {\n \"button_text\": \"<string>\",\n \"description\": \"<string>\",\n \"headline\": \"<string>\",\n \"url\": \"<string>\"\n },\n \"disclaimer\": {\n \"body\": \"<string>\",\n \"checkboxes\": [\n {\n \"checked_by_default\": true,\n \"key\": \"<string>\",\n \"required\": true,\n \"text\": \"<string>\"\n }\n ],\n \"title\": \"<string>\"\n },\n \"intro\": {\n \"description\": \"<string>\",\n \"headline\": \"<string>\"\n },\n \"name\": \"<string>\",\n \"phone_verification\": true,\n \"privacy_policy\": {\n \"link_text\": \"<string>\",\n \"url\": \"<string>\"\n },\n \"questions\": [\n {\n \"label\": \"<string>\",\n \"options\": [\n {\n \"key\": \"<string>\",\n \"logic\": {\n \"target_end_page_index\": 123,\n \"target_question_index\": 123\n },\n \"value\": \"<string>\"\n }\n ]\n }\n ]\n },\n \"lead_form_id\": \"<string>\",\n \"messaging_config\": {\n \"keyword\": \"<string>\",\n \"message\": \"<string>\"\n },\n \"multi_advertiser_ads\": true,\n \"post_id\": \"<string>\",\n \"primary_texts\": [\n \"<string>\"\n ],\n \"social_accounts\": [\n {\n \"id\": \"<string>\"\n }\n ],\n \"title\": \"<string>\",\n \"url\": \"<string>\",\n \"url_parameters\": {}\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://api.whop.com/api/v1/ads")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"ad_group\": {},\n \"ad_group_id\": \"<string>\",\n \"creatives\": [\n {\n \"crop\": {\n \"height\": 123,\n \"width\": 123,\n \"x\": 123,\n \"y\": 123\n },\n \"id\": \"<string>\"\n }\n ],\n \"descriptions\": [\n \"<string>\"\n ],\n \"headlines\": [\n \"<string>\"\n ],\n \"lead_form\": {\n \"completion\": {\n \"button_text\": \"<string>\",\n \"description\": \"<string>\",\n \"headline\": \"<string>\",\n \"url\": \"<string>\"\n },\n \"disclaimer\": {\n \"body\": \"<string>\",\n \"checkboxes\": [\n {\n \"checked_by_default\": true,\n \"key\": \"<string>\",\n \"required\": true,\n \"text\": \"<string>\"\n }\n ],\n \"title\": \"<string>\"\n },\n \"intro\": {\n \"description\": \"<string>\",\n \"headline\": \"<string>\"\n },\n \"name\": \"<string>\",\n \"phone_verification\": true,\n \"privacy_policy\": {\n \"link_text\": \"<string>\",\n \"url\": \"<string>\"\n },\n \"questions\": [\n {\n \"label\": \"<string>\",\n \"options\": [\n {\n \"key\": \"<string>\",\n \"logic\": {\n \"target_end_page_index\": 123,\n \"target_question_index\": 123\n },\n \"value\": \"<string>\"\n }\n ]\n }\n ]\n },\n \"lead_form_id\": \"<string>\",\n \"messaging_config\": {\n \"keyword\": \"<string>\",\n \"message\": \"<string>\"\n },\n \"multi_advertiser_ads\": true,\n \"post_id\": \"<string>\",\n \"primary_texts\": [\n \"<string>\"\n ],\n \"social_accounts\": [\n {\n \"id\": \"<string>\"\n }\n ],\n \"title\": \"<string>\",\n \"url\": \"<string>\",\n \"url_parameters\": {}\n}")
.asString();
require 'uri'
require 'net/http'

url = URI("https://api.whop.com/api/v1/ads")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"ad_group\": {},\n \"ad_group_id\": \"<string>\",\n \"creatives\": [\n {\n \"crop\": {\n \"height\": 123,\n \"width\": 123,\n \"x\": 123,\n \"y\": 123\n },\n \"id\": \"<string>\"\n }\n ],\n \"descriptions\": [\n \"<string>\"\n ],\n \"headlines\": [\n \"<string>\"\n ],\n \"lead_form\": {\n \"completion\": {\n \"button_text\": \"<string>\",\n \"description\": \"<string>\",\n \"headline\": \"<string>\",\n \"url\": \"<string>\"\n },\n \"disclaimer\": {\n \"body\": \"<string>\",\n \"checkboxes\": [\n {\n \"checked_by_default\": true,\n \"key\": \"<string>\",\n \"required\": true,\n \"text\": \"<string>\"\n }\n ],\n \"title\": \"<string>\"\n },\n \"intro\": {\n \"description\": \"<string>\",\n \"headline\": \"<string>\"\n },\n \"name\": \"<string>\",\n \"phone_verification\": true,\n \"privacy_policy\": {\n \"link_text\": \"<string>\",\n \"url\": \"<string>\"\n },\n \"questions\": [\n {\n \"label\": \"<string>\",\n \"options\": [\n {\n \"key\": \"<string>\",\n \"logic\": {\n \"target_end_page_index\": 123,\n \"target_question_index\": 123\n },\n \"value\": \"<string>\"\n }\n ]\n }\n ]\n },\n \"lead_form_id\": \"<string>\",\n \"messaging_config\": {\n \"keyword\": \"<string>\",\n \"message\": \"<string>\"\n },\n \"multi_advertiser_ads\": true,\n \"post_id\": \"<string>\",\n \"primary_texts\": [\n \"<string>\"\n ],\n \"social_accounts\": [\n {\n \"id\": \"<string>\"\n }\n ],\n \"title\": \"<string>\",\n \"url\": \"<string>\",\n \"url_parameters\": {}\n}"

response = http.request(request)
puts response.read_body
{
  "ad_campaign": {
    "id": "<string>"
  },
  "ad_group": {
    "id": "<string>"
  },
  "added_to_carts": 123,
  "call_to_action": "learn_more",
  "click_through_rate": 123,
  "clicks": 123,
  "completed_registrations": 123,
  "contacts": 123,
  "cost_per_added_to_cart": 123,
  "cost_per_click": 123,
  "cost_per_completed_registration": 123,
  "cost_per_contact": 123,
  "cost_per_lead": 123,
  "cost_per_mille": 123,
  "cost_per_purchase": 123,
  "cost_per_result": 123,
  "cost_per_schedule": 123,
  "cost_per_submitted_application": 123,
  "cost_per_viewed_content": 123,
  "created_at": "<string>",
  "creatives": [
    {
      "crop": {
        "height": 123,
        "width": 123,
        "x": 123,
        "y": 123
      },
      "format": "square",
      "id": "<string>",
      "media_type": "<string>",
      "url": "<string>"
    }
  ],
  "custom_conversions": 123,
  "delivery_status": "rejected",
  "descriptions": [
    "<string>"
  ],
  "frequency": 123,
  "headlines": [
    "<string>"
  ],
  "id": "<string>",
  "impressions": 123,
  "issues": [
    {
      "id": "<string>",
      "message": "<string>",
      "resource_id": "<string>",
      "resource_type": "ad_campaign"
    }
  ],
  "lead_form": {},
  "lead_form_id": "<string>",
  "leads": 123,
  "messaging_config": {},
  "multi_advertiser_ads": true,
  "post_id": "<string>",
  "post_source": "facebook",
  "post_thumbnail_url": "<string>",
  "primary_texts": [
    "<string>"
  ],
  "purchase_value": 123,
  "purchases": 123,
  "reach": 123,
  "result_event": "purchase",
  "result_event_name": "<string>",
  "return_on_ad_spend": 123,
  "schedules": 123,
  "social_accounts": [
    {}
  ],
  "spend": 123,
  "spend_currency": "<string>",
  "status": "active",
  "submitted_applications": 123,
  "title": "<string>",
  "unique_click_through_rate": 123,
  "unique_clicks": 123,
  "updated_at": "<string>",
  "url": "<string>",
  "url_parameters": {},
  "viewed_contents": 123
}
{
"error": {
"message": "<string>",
"type": "<string>"
}
}
{
"error": {
"message": "<string>",
"type": "<string>"
}
}

Authorizations

Authorization
string
header
required

A company API key, company scoped JWT, app API key, or user OAuth token. You must prepend your key/token with the word 'Bearer', which will look like Bearer ***************************

Headers

Api-Version-Date
string

Pins the request to a dated API version.

Example:

"2026-07-08-1"

Body

application/json
ad_group
object

An inline ad group to create (same shape as POST /ad_groups, including ad_campaign_id). Creates the ad group and the ad together. Provide this OR ad_group_id.

ad_group_id
string

The existing ad group to create the ad in. Provide this OR ad_group, not both.

call_to_action
enum<string>

The call-to-action button shown on the ad.

Available options:
apply_now,
book_now,
call_now,
contact_us,
download,
get_directions,
get_offer,
get_quote,
learn_more,
listen_now,
message_page,
no_button,
open_link,
order_now,
request_time,
see_details,
see_menu,
send_updates,
shop_now,
sign_up,
subscribe,
watch_more
creatives
object[]

The ad's creative assets. Each entry is an uploaded file id with an optional format; omit format for the original asset.

descriptions
string[]

The description variants shown on the ad.

headlines
string[]

The headline variants shown on the ad.

lead_form
object

Instant lead form for the ad. Only allowed when the ad group's conversion_location is an instant-form destination (instant_forms, instant_forms_and_messenger, website_and_instant_forms). Mutually exclusive with lead_form_id.

lead_form_id
string

Use an existing Meta instant form instead of creating one — the form's Meta id, from a form already on the ad's Facebook page. Only allowed when the ad group's conversion_location is an instant-form destination. Mutually exclusive with lead_form.

messaging_config
object

Click-to-message welcome copy: the greeting (message) and the ice-breaker prompt (keyword).

multi_advertiser_ads
boolean

Whether the ad can appear alongside other advertisers' ads in the same unit. Defaults to true.

post_id
string

Promote an existing post instead of uploading creatives — a Facebook post or Instagram media id. Mutually exclusive with creatives. Pair with post_source.

post_source
enum<string>

Which network post_id refers to — facebook (a page post) or instagram (a media id). Authoritative; when omitted the source is inferred from the id shape.

Available options:
facebook,
instagram
primary_texts
string[]

The primary text variants shown in the ad body.

social_accounts
object[]

The social accounts (Facebook page, Instagram profile) the ad runs under.

title
string

The display name of the ad.

url
string

The URL the ad links to.

url_parameters
object

Query parameters appended to the destination URL, as a string-to-string map.

Response

ad created

ad_campaign
object
required

The ad campaign this ad belongs to, an object with an id.

ad_group
object
required

The ad group this ad belongs to, an object with an id.

added_to_carts
number
required

Whop pixel-attributed add-to-cart events, last-click.

call_to_action
enum<string> | null
required

The call-to-action button shown on the ad.

Available options:
learn_more,
shop_now,
sign_up,
subscribe,
get_started,
book_now,
apply_now,
contact_us,
download,
order_now,
buy_now,
get_quote,
message_page,
whatsapp_message,
instagram_message,
call_now,
get_directions,
send_updates,
get_offer,
watch_more,
listen_now,
play_game,
open_link,
no_button,
get_offer_view,
get_event_tickets,
see_menu,
request_time,
event_rsvp,
see_details,
view_instagram_profile,
null
Example:

"learn_more"

click_through_rate
number
required

Clicks divided by impressions, between 0 and 1.

clicks
number
required

The number of clicks.

completed_registrations
number
required

Whop pixel-attributed complete-registration events, last-click.

contacts
number
required

Whop pixel-attributed contact events, last-click.

cost_per_added_to_cart
number | null
required

Spend divided by attributed add-to-cart events; null when they are not the goal and none are attributed.

cost_per_click
number
required

Spend divided by clicks; 0 when there are no clicks.

cost_per_completed_registration
number | null
required

Spend divided by attributed complete-registration events; null when they are not the goal and none are attributed.

cost_per_contact
number | null
required

Spend divided by attributed contact events; null when contacts are not the goal and none are attributed.

cost_per_lead
number | null
required

Spend divided by attributed leads; null when leads are not a goal and none are attributed.

cost_per_mille
number
required

Spend per 1,000 impressions; 0 when there are no impressions.

cost_per_purchase
number | null
required

Spend divided by attributed purchases; null when purchases are not a goal and none are attributed.

cost_per_result
number | null
required

Spend divided by Whop pixel-attributed results; null when nothing Whop-attributable is being optimized for.

cost_per_schedule
number | null
required

Spend divided by attributed schedule events; null when schedules are not the goal and none are attributed.

cost_per_submitted_application
number | null
required

Spend divided by attributed submit-application events; null when they are not the goal and none are attributed.

cost_per_viewed_content
number | null
required

Spend divided by attributed view-content events; null when they are not the goal and none are attributed.

created_at
string
required

When the ad was created, as an ISO 8601 timestamp.

creatives
object[]
required
custom_conversions
number
required

Whop pixel-attributed custom (merchant-defined) conversion events, last-click, across all custom event names.

delivery_status
enum<string>
required

The current delivery state, mirroring the Delivery column in the ads dashboard. When several states apply at once, the highest-precedence one is returned.

Available options:
rejected,
in_review,
draft,
campaign_paused,
ad_group_paused,
paused,
processing,
issues,
learning_limited,
learning,
active
Example:

"rejected"

descriptions
string[]
required

The description variants shown on the ad.

frequency
number | null
required

Platform-reported impressions divided by reach.

headlines
string[]
required

The headline variants shown on the ad.

id
string
required

Unique identifier for the ad.

impressions
number
required

The number of impressions.

issues
object[]
required
lead_form
object | null
required

The instant lead form on the ad (Meta lead ads), or null when the ad group's conversion_location is not an instant-form destination. An object with name, form_type (more_volume or higher_intent), an optional intro, questions, a privacy_policy, an optional completion screen, and phone_verification.

lead_form_id
string | null
required

The Meta lead form the ad uses. Set when the ad references an existing form via lead_form_id, or once a form built from lead_form has been created on Meta at launch.

leads
number
required

Whop pixel-attributed leads, last-click.

messaging_config
object | null
required

The click-to-message welcome copy, an object with message and keyword, or null when the ad has none.

multi_advertiser_ads
boolean
required

Whether the ad can appear alongside other advertisers' ads in the same unit. Defaults to true.

post_id
string | null
required

The existing post this ad promotes (a Facebook post or Instagram media), or null when it uses uploaded creatives.

post_source
enum<string> | null
required

Which network post_id refers to — facebook (a page post) or instagram (a media id) — or null when the ad uses uploaded creatives.

Available options:
facebook,
instagram,
null
Example:

"facebook"

post_thumbnail_url
string | null
required

Preview image of the existing post this ad promotes. Null for ads that use uploaded creatives, or until the post's media has been fetched from the network.

primary_texts
string[]
required

The primary text variants shown in the ad body.

purchase_value
number
required

USD value of pixel-attributed purchases.

purchases
number
required

Whop pixel-attributed purchases, last-click.

reach
number
required

The number of unique people who saw this.

result_event
enum<string> | null
required

The Whop pixel conversion event whose attributed count represents results — the optimization goal, or the highest-volume attributed event for campaigns that budget per ad group. Null when the goal isn't a Whop-attributed event.

Available options:
purchase,
lead,
schedule,
submit_application,
contact,
complete_registration,
view_content,
add_to_cart,
custom,
null
Example:

"purchase"

result_event_name
string | null
required

The merchant-defined event name when result_event is custom; null for the standard events.

return_on_ad_spend
number
required

Purchase value divided by spend, both in USD (a currency-neutral ratio); 0 when there is no spend.

schedules
number
required

Whop pixel-attributed schedule events, last-click.

social_accounts
object[]
required
spend
number
required

The amount charged, in spend_currency.

spend_currency
string | null
required

The ISO 4217 currency code of all monetary metrics.

status
enum<string>
required

The delivery status of the ad.

Available options:
active,
paused,
in_review,
rejected
Example:

"active"

submitted_applications
number
required

Whop pixel-attributed submit-application events, last-click.

title
string | null
required

The display title of the ad. Falls back to the creative set caption when unset.

unique_click_through_rate
number | null
required

Unique clicks divided by impressions, between 0 and 1.

unique_clicks
number
required

The number of unique clicks.

updated_at
string
required

When the ad was last updated, as an ISO 8601 timestamp.

url
string | null
required

The URL the ad links to.

url_parameters
object
required

Query parameters appended to the URL, as a string-to-string map.

viewed_contents
number
required

Whop pixel-attributed view-content events, last-click.