Create standalone ad
Creates a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X/Twitter, and LinkedIn. Supports three mutually-exclusive request shapes selected by the body, a legacy single-creative shape (all platforms, default), a Meta-only multi-creative shape via the creatives array (one ad set with N ads sharing budget and targeting), and a Meta-only attach shape via adSetId (adds one new ad to an existing ad set). Per-platform required fields, budget minimums, and video-ad rules are documented on each property below. LinkedIn creates a Single Image or Single Video Ad backed by a Direct Sponsored Content "dark post" authored by a Company Page (see organizationId); supported goals are engagement, traffic, awareness, and video_views (video ads use the video field; video_views requires a video), and traffic ads require linkUrl.
Idempotency: this endpoint is not idempotent at the platform level (a blind retry creates a second campaign/ad set/ad). Send an Idempotency-Key header to make retries safe: the first request with a given key creates the ad and we store the response; a retry with the same key replays that exact response (with Idempotent-Replayed: true) instead of creating duplicates. Reusing a key with a different body returns 422; a key whose first request is still in flight returns 409 (retry after a short backoff). Keys are scoped to your credential and expire after 24h.
API key authentication - use your Zernio API key as a Bearer token
In: header
Header Parameters
Optional client-generated unique key (e.g. a UUID) that makes create retries safe. Same key + same body replays the original response; same key + different body → 422; key still processing → 409.
length <= 255length <= 255Meta only. Exact campaign name. Overrides the default <name> - Campaign.
length <= 255Meta only. Exact ad set name. Overrides the default <name> - Ad Set. (For per-ad names on the multi-creative shape, set name on each creatives[] entry.)
length <= 255Meta only. Exact ad name (the single-creative ad object's name). Overrides the default, which is name. (For per-ad names on the multi-creative shape, set name on each creatives[] entry instead.)
length <= 255Meta only. Attaches pixel measurement to the ad regardless of the optimization goal (the "Website events" tracking row in Ads Manager). pixelId becomes the ad's tracking_specs (offsite_conversion + fb_pixel); urlTags becomes the ad's url_tags (click-tracking query params). Applied on the legacy single-creative shape, every ad of the multi-creative shape, and the attach shape. NOTE: tracking lives on the AD object and is not inherited from the ad set, so pass it on EVERY attach call that should carry the pixel.
Required on legacy + multi-creative shapes. Inherited from the ad set on the attach shape. Available goals vary by platform. Meta-specific: conversions (OUTCOME_SALES) requires promotedObject.pixelId + promotedObject.customEventType (use a commerce event, e.g. PURCHASE, START_TRIAL); lead_conversion (OUTCOME_LEADS, website pixel leads) requires the same pixel + event but with a leads-class event (e.g. LEAD, SUBMIT_APPLICATION, SCHEDULE, CONTACT) — these are rejected under conversions because Meta gates conversion events by objective; lead_generation is OUTCOME_LEADS with instant forms (leadGenFormId), distinct from lead_conversion's website pixel optimization; app_promotion requires promotedObject.applicationId + promotedObject.objectStoreUrl; catalog_sales (Advantage+ catalog ads, e.g. vehicle inventory) requires promotedObject.productSetId + promotedObject.pixelId + promotedObject.customEventType and builds a catalog TEMPLATE creative from the copy fields (headline/body/description/linkUrl/callToAction, which may carry catalog template tags like {{product.name}} or {{vehicle.make}}) — no imageUrl/video is sent, Meta renders the visuals per catalog item; discover catalogs via GET /v1/ads/catalogs and product sets via GET /v1/ads/catalogs/{catalogId}/product-sets; single shape only (no creatives[]/adSetId/dynamicCreative/placementAssets); lead_generation accepts an optional promotedObject.pageId (auto-filled from the connected Page when omitted). TikTok-specific: conversions (website-conversion ad group) requires promotedObject.pixelId (your TikTok Pixel ID) and accepts an optional promotedObject.customEventType (a TikTok optimization_event code like ON_WEB_ORDER, INITIATE_ORDER, ON_WEB_REGISTER, FORM); to inherit a pixel + event from an existing ad group, pass adSetId instead. LinkedIn-specific: engagement, traffic, awareness, and video_views are supported for standalone ads (creates a Direct Sponsored Content single image or single video ad). traffic requires linkUrl; video_views requires the video field. For lead_generation / conversions on LinkedIn — or to promote an existing post — use POST /v1/ads/boost.
"engagement" | "traffic" | "awareness" | "video_views" | "lead_generation" | "lead_conversion" | "conversions" | "app_promotion" | "catalog_sales"Meta only. Explicit ad-set optimization_goal (e.g. LANDING_PAGE_VIEWS, LINK_CLICKS, REACH, IMPRESSIONS, OFFSITE_CONVERSIONS, THRUPLAY, LEAD_GENERATION). Overrides the default derived from goal (e.g. traffic defaults to LINK_CLICKS). Forwarded verbatim to Meta, which validates compatibility with the campaign objective and rejects incompatible combinations.
Required on legacy + multi-creative shapes. Inherited on attach.
Required on legacy + multi-creative shapes. Inherited on attach.
"daily" | "lifetime"Meta only. Publish state of the created ad set + ad. Omitted or ACTIVE publishes live (default, back-compat); PAUSED creates them paused and skips activation, so you can review before they spend.
"ACTIVE" | "PAUSED"Meta only. Where the budget lives, which selects the Meta budget model:
adset(default): ABO (Ad-set Budget Optimization). The budget is set on the ad set. This is the back-compatible behaviour — omit this field to keep it.campaign: CBO (Campaign Budget Optimization / Advantage Campaign Budget). The budget ANDbidStrategyare set on the CAMPAIGN, and Meta distributes spend across ad sets automatically. Meta requires the budget at exactly one level, never both. Non-Meta platforms ignore this field. Ignored on the attach shape (adSetId), which inherits the existing budget.
"adset""adset" | "campaign"Required for Meta, Google, Pinterest, and LinkedIn on legacy + attach shapes (skip for multi-creative — use creatives[].headline). Ignored for TikTok and X/Twitter. Max: Meta=255, Google=30, Pinterest=100, LinkedIn=400. On LinkedIn this is the ad's headline (the bold text on the creative); for traffic ads it's the link card title.
Google Display only — defaults to headline if omitted. On LinkedIn, reused as the optional secondary description text on traffic (link) ads; omitted if not provided.
length <= 90Required on legacy + attach shapes. For X/Twitter this is the tweet text (max 280 chars including a ~24-char URL when linkUrl is set). On LinkedIn this is the post commentary (the intro text shown above the ad). Max: Google=90, Pinterest=500.
Meta only (facebook/instagram). Link description — the secondary text shown below the headline (Meta's link_data.description; on video creatives mapped to video_data.link_description). When omitted, Meta auto-pulls the destination URL's OpenGraph description. Applies on legacy, attach, and placementAssets shapes; for multi-creative use creatives[].description (this field is the shared fallback). For multi-text variations use dynamicCreative.descriptions instead.
length <= 255Required on legacy + attach shapes for Meta. Honoured on TikTok (passes through to the Spark Ad creative's call_to_action) and on LinkedIn (the CTA button on the ad; defaults to LEARN_MORE when linkUrl is set). LinkedIn accepts: LEARN_MORE, SIGN_UP, DOWNLOAD, SUBSCRIBE, REGISTER, JOIN, ATTEND, REQUEST_DEMO, VIEW_QUOTE, APPLY, SEE_MORE, SHOP_NOW, BUY_NOW. Ignored by Google, Pinterest, and X/Twitter.
"LEARN_MORE" | "SHOP_NOW" | "SIGN_UP" | "BOOK_TRAVEL" | "CONTACT_US" | "DOWNLOAD" | "GET_OFFER" | "GET_QUOTE" | "SUBSCRIBE" | "WATCH_MORE" | "REGISTER" | "JOIN" | "ATTEND" | "REQUEST_DEMO" | "VIEW_QUOTE" | "APPLY" | "SEE_MORE" | "BUY_NOW"Required on legacy + attach shapes (skip for multi-creative). On LinkedIn it's the ad's destination URL; required for traffic ads, optional for engagement / awareness. NOT required when goal is lead_generation (the ad opens a Lead Gen form instead of a destination).
uriMeta Lead Gen forms only (facebook/instagram). The leadgen_forms ID to attach to the ad's creative — create one via POST /v1/ads/lead-forms. REQUIRED when goal is lead_generation, and on every ATTACH (adSetId) call that targets a lead ad set (the form attaches per-ad; Meta rejects a formless ad in a lead ad set). Ignored otherwise. The ad set's promoted_object.page_id + LEAD_GENERATION optimization + destination_type ON_AD are derived automatically from the goal. Both placementAssets (per-placement creative) and dynamicCreative (multi-text / multi-asset pool, e.g. multiple headlines and primary texts) ARE supported on instant-form lead ads — the form is attached for you, and for dynamicCreative the ad set is created as a Dynamic Creative ad set automatically (Meta requires that for any multi-text feed; there is no non-DCO multi-text path). Send a single imageUrls entry plus your text variations to get Meta's "Multiple Text Options" behavior on a lead ad.
Image creative for Meta/Google/Pinterest/LinkedIn on legacy + attach shapes (mutually exclusive with video). Required for LinkedIn ads unless video is set. Not required for Google Search campaigns. For TikTok, this field carries the VIDEO URL (the TikTok ads endpoint is video-only; the field retains the imageUrl name for cross-platform consistency). Ignored for X/Twitter. For Google Display, treated as the landscape image (alias of images.landscape); supply images.square alongside or the request is rejected. For LinkedIn the image is uploaded to LinkedIn under the authoring Company Page (see organizationId); recommended ratio 1.91:1 (e.g. 1200×627).
uriGoogle Display (Responsive Display Ads) only. Google RDA requires both a landscape (1.91:1) and a square (1:1) marketing image; sending only one is rejected upstream as 'Too few.' (NOT_ENOUGH_*_MARKETING_IMAGE_ASSET). Supply both URLs here. Either this field or the legacy imageUrl can provide the landscape, but square has no legacy counterpart so it must be set here for Display.
Meta (facebook, instagram) and LinkedIn. When set, creates a VIDEO ad on the legacy (or, for Meta, attach) shape. Mutually exclusive with imageUrl. For Meta multi-creative, set video per entry inside creatives[] instead. For LinkedIn the video is uploaded to LinkedIn under the authoring Company Page (see organizationId) and the campaign format is set to SINGLE_VIDEO; LinkedIn ignores thumbnailUrl (it auto-generates the poster frame) — supply MP4 H.264/AAC, 3s-30min, 75KB-500MB.
Meta-only. When present, switches to the multi-creative shape:
creates 1 campaign + 1 ad set + N ads (one per entry here).
Top-level headline / body / imageUrl / linkUrl /
callToAction are ignored in this mode. Mutually exclusive with adSetId.
1 <= itemsMeta-only. When present, switches to the attach shape: adds
one new ad to this existing ad set without creating a new
campaign. Budget, targeting, goal, schedule, AND bid strategy
are inherited from the ad set on Meta — passing bidStrategy
in attach mode returns 400. To change an existing ad set's
bid, use PUT /v1/ads/ad-sets/{adSetId}. Mutually exclusive
with creatives[].
The attached ad takes the full single-creative surface:
headline/body/description/callToAction plus either
imageUrl/video OR placementAssets (its own per-placement
Feed/Story assets), and leadGenFormId when the target is a
lead ad set (the parent must be ON_AD — true for ad sets
created via goal lead_generation; Meta rejects a formless ad
there, so pass the form on EVERY attached ad). This is the way
to build N full ads sharing one ad set: create the first ad
via the normal shape, then attach the rest one call each.
Supported on Meta (facebook, instagram) and TikTok. On TikTok
the adSetId is the ad group ID; the new ad inherits the
ad group's bid + budget + targeting.
Meta only. Add the new ad set under this EXISTING campaign
instead of creating a new one (multi-ad-set audience testing).
The new ad set's budget is matched to the campaign's mode
automatically: for a CBO campaign (campaign-level budget) omit
budgetAmount/budgetType — the campaign owns the budget; for
an ABO campaign pass them (they go on the new ad set). On
failure only the new ad set is cleaned up; the existing campaign
is left untouched and is never (re)activated. Mutually exclusive
with adSetId and creatives[].
Meta only. Reuse an EXISTING ad creative by id instead of
building a new one from the copy/media fields (which are then
ignored). Combine with existingCampaignId to build a
multi-ad-set campaign that shares one creative. Mutually
exclusive with creatives[], dynamicCreative, and
placementAssets. The creative id used is returned as
creativeId on the create response.
Google Display only
length <= 25Pinterest only. Board ID (auto-creates if not provided).
LinkedIn only. The Company Page that authors the Direct Sponsored Content ("dark") post backing the ad — accepts a numeric organization ID or a full urn:li:organization:N URN. Required unless the resolved accountId is a connected LinkedIn Company-Page account (defaults to that page) or the LinkedIn ad account is org-owned (defaults to the account's owning organization). The authenticated member must be an ADMINISTRATOR or DIRECT_SPONSORED_CONTENT_POSTER of this page (and the page must be associated with the ad account), or LinkedIn returns 403. Ignored by every other platform.
ISO 3166-1 alpha-2 country codes (e.g. ['NL']). Defaults to ['US'] when no cities or regions are provided. (LinkedIn currently honours country-level targeting only.)
Meta-only. City-level geo targeting. Each city is targeted by Meta's opaque key (the city ID) which can be looked up via GET /v1/ads/targeting/search?type=city&q=<name>&country_code=<ISO>. Optional radius + distance_unit extend the targeting beyond the city limits (e.g. radius 25 km around the city center). Both must be set together, or both omitted (Meta defaults to ~16 km when omitted).
Cannot overlap with the same country in countries (Meta returns a "locations overlap" error). Either drop the country or scope it to a different country.
Meta-only. Region-level (state/province) geo targeting. Each region is targeted by Meta's opaque key (the region ID) which can be looked up via GET /v1/ads/targeting/search?type=region&q=<name>&country_code=<ISO>.
13 <= value <= 6513 <= value <= 65Interest objects from /v1/ads/interests. Each must include id and name.
Postal/ZIP geo targeting. key is the platform's postal location ID from /v1/ads/targeting/search?dimension=geo&geoType=zip. Supported on Meta, Google, TikTok, Pinterest, X.
DMA / metro-area geo targeting. key is the platform's metro ID from /v1/ads/targeting/search?dimension=geo&geoType=metro.
Point-radius (lat/lng) geo targeting. Meta only (custom_locations). Rejected on platforms without radius support.
Behaviour entities from /v1/ads/targeting/search?dimension=behavior. Supported on Meta and TikTok. Each must include id.
Normalized household-income tier. Meta and TikTok express all four; Google maps only
top_10; rejected on LinkedIn, X, and Pinterest. On Meta, income targeting is incompatible
with housing/employment/credit specialAdCategories.
"top_5" | "top_10" | "top_10_25" | "top_25_50"Language codes (e.g. ['en']). Restricts the audience by language.
Meta only. Manual ad placements. Omit for automatic placements (Meta's default,
recommended for most cases — Meta optimises delivery across all eligible surfaces).
When set, restricts delivery to the chosen surfaces, mapped onto the ad set's
targeting.{publisher_platforms, facebook_positions, instagram_positions, messenger_positions, audience_network_positions, threads_positions, whatsapp_positions, device_platforms}. Enum membership is validated here; Meta
additionally enforces co-selection rules (e.g. some positions require their parent
publisher platform) and returns an actionable error which we surface. Non-Meta
platforms reject this field.
ID of a saved_targeting audience (created via POST /v1/ads/audiences). When set, its stored
TargetingSpec is expanded as the base targeting; inline fields on this body merge on top. Lets you
reuse a named targeting preset without re-sending every field.
Meta only. A raw Meta-native targeting spec passed to the ad set VERBATIM (snake_case:
geo_locations, age_min, excluded_custom_audiences, flexible_spec, targeting_automation,
business places, etc.) — exactly the shape GET /v1/ads/{adId} returns for external ads. Use it to
clone a campaign's targeting EXACTLY, preserving advanced fields the camelCase targeting fields can't
model. Mutually exclusive with the camelCase targeting fields (countries/regions/cities/interests/
ageMin/...), audienceId, and savedTargetingId (sending both → 422). Sent as-is; Meta validates and
surfaces any errors. If cloning an EU campaign, also pass dsaBeneficiary / dsaPayor (those are
separate fields, not part of targeting).
Meta only. Declares the ad's special category, required for housing, employment, credit, or political/social-issue ads (Meta enforces restricted targeting for these). Note: setting a special category disables income/zip targeting on Meta.
Required for lifetime budgets
date-timeMeta only. Ad-set start time (ISO 8601, e.g. "2026-06-10T09:00:00Z"), mapped to the
ad set's start_time. When omitted the ad starts delivering immediately. For lifetime
budgets Meta also requires endDate. (Same schedule.startDate semantics already
available on POST /v1/ads/boost.)
date-timeMeta only. Override the Instagram account the ad is delivered as — pass an Instagram
Business Account ID (e.g. 17841...), mapped to the creative's instagram_user_id.
When omitted we auto-resolve the IG account linked to the connected Facebook Page
(the existing default). Useful when a Page has more than one eligible IG account.
Meta only. Dynamic Creative: supply a POOL of assets and Meta auto-combines and
optimises them into the best-performing variations within a single ad (mapped to the
creative's asset_feed_spec). When set, the top-level single-creative fields
(imageUrl, headline, body, linkUrl, callToAction) are ignored. Mutually
exclusive with the creatives[] multi-creative shape. Meta limits: ≤10 images,
≤5 bodies / titles / descriptions.
Meta only. Placement asset customization: pin a SPECIFIC asset (image OR video) to
each placement group on a SINGLE ad (e.g. a 9:16 on Stories/Reels and a 4:5 on Feed).
The same thing Meta Ads Manager produces with "different creative per placement",
mapped to the creative's asset_feed_spec + asset_customization_rules. Deterministic
pinning, NOT the auto-optimizing pool of dynamicCreative (mutually exclusive). Works
on the legacy single shape AND the attach shape (adSetId + placementAssets adds one
placement-customized ad to an existing ad set — the way to build N per-placement ads
sharing one ad set: create the first normally, attach the rest). Cannot be combined
with creatives[]. Shared copy (headline, body, link,
CTA) comes from the top-level single-creative fields since only the asset varies by
placement. Each rule's placements accepts the same fields as the top-level
placements object; Meta enforces co-selection rules and returns an actionable error.
Note on text rendering: Meta suppresses primary text and headline on fullscreen placements (Stories and Reels) in actual ad delivery; the fields are accepted and the ad publishes, but the copy is not shown to users. For visible copy on those placements, bake the text into the creative image or video itself.
A block is all-image OR all-video, never mixed (Meta's asset_feed_spec carries one ad
format). Image mode: defaultImageUrl + rules[].imageUrl. Video mode:
defaultVideoUrl + rules[].videoUrl (optional thumbnailUrl/defaultThumbnailUrl
posters; Meta auto-generates when omitted). Exactly one catch-all default is required.
Custom audience ID for targeting
Google only
"display""display" | "search"Google Search only
Google Search RSA only. Extra headlines.
Google Search RSA only. Extra descriptions.
Meta only. Controls the Advantage audience feature (targeting_automation). 0 = disabled (default), 1 = enabled. Meta Marketing API requires this field on all ad set creation requests.
0 | 1Meta only. Conversion attribution window for the ad set — maps 1:1 to Meta's
ad-set attribution_spec. Only honored for conversion goals (conversions,
lead_generation, app_promotion); ignored for awareness/traffic/engagement.
Omit to use Meta's default (7-day click + 1-day view). Meta enforces the
valid combinations: VIEW_THROUGH only allows windowDays: 1 (7d/28d view
windows were removed Jan 2026); ENGAGED_VIDEO_VIEW only 1 and only alongside
VIEW_THROUGH: 1; CLICK_THROUGH: 28 only on certain objectives. Invalid combos
surface as a Meta 400.
Example: [{ "eventType": "CLICK_THROUGH", "windowDays": 7 }, { "eventType": "VIEW_THROUGH", "windowDays": 1 }]
1 <= items <= 3Meta only. Restrict the audience by gender. 'male' targets men only, 'female' targets women only, 'all' (default) targets everyone. Ignored by non-Meta platforms.
"all""all" | "male" | "female""LOWEST_COST_WITHOUT_CAP" | "LOWEST_COST_WITH_BID_CAP" | "COST_CAP" | "LOWEST_COST_WITH_MIN_ROAS"Bid cap in WHOLE currency units (USD: 5 = $5.00; JPY: 100 = ¥100). Required when
bidStrategy is LOWEST_COST_WITH_BID_CAP or COST_CAP.
Minimum ROAS as a decimal multiplier (e.g. 2.0 = 2.0x ROAS). Required when
bidStrategy is LOWEST_COST_WITH_MIN_ROAS. Sent to Meta as
bid_constraints.roas_average_floor × 10000.
Name of the legal entity benefiting from the ad. Required by Meta when targeting EU users (DSA Article 26). Not enforced at schema level; enforced server-side when targeting intersects EU member states.
length <= 100Name of the legal entity paying for the ad. Required by Meta when targeting EU users (DSA Article 26). Note Meta API spelling: dsa_payor (not dsa_payer).
length <= 100TikTok only. Synthetic Brand Identity used when the ad
attributes to a CUSTOMIZED_USER (instead of a real TT_USER
@username). Required on the FIRST CUSTOMIZED_USER ad on a
tiktokads SocialAccount with no cached identity; omit on
subsequent ads (the identity is cached on the account after
first creation). Non-TikTok platforms ignore this field.
Alternative: configure once via PATCH /v1/connect/tiktok-ads,
then create ads without this field.
TikTok only. Forces the identity attribution on the ad:
TT_USER: the posting account's open_id (real @username branding). Requires a connected TikTok posting account on the same profile.CUSTOMIZED_USER: synthetic Brand Identity (display name + avatar). Requires a configured Brand Identity (cached on thetiktokadsSocialAccount viaPATCH /v1/connect/tiktok-ads) or an inlinebrandIdentityto create one on the fly.
When omitted, defaults to TT_USER if a posting account is
connected on this profile, else CUSTOMIZED_USER. Spark
Ads (POST /v1/ads/boost) always use TT_USER regardless
of this field — TikTok requires the original organic
post's author identity for Spark.
"TT_USER" | "CUSTOMIZED_USER"What the ad optimises against. Behaviour depends on the platform.
Meta: forwarded to the ad set's promoted_object (snake-cased).
Required for goals whose ad-set optimization_goal points at a specific
event/page/app (without it Meta rejects the ad-set create with
error_subcode: 1815430 "Please select a promoted object for your ad set"):
goal: conversions(OFFSITE_CONVERSIONS): requirespixelId+customEventTypegoal: app_promotion(APP_INSTALLS): requiresapplicationId+objectStoreUrlgoal: lead_generation(LEAD_GENERATION):pageIdis auto-filled from the connected Page when omitted
Other Meta goals (engagement, traffic, awareness, video_views) ignore this field.
TikTok: only goal: conversions uses it.
pixelIdmaps to the ad group'spixel_id. Required: a TikTok website-conversion ad group without a pixel is rejected with40002: Please select a pixel.customEventTypemaps to the ad group'soptimization_event(the pixel event to optimise for). Optional: TikTok accepts a pixel-only auto-bid conversion ad group. See thecustomEventTypefield below for the valid TikTok codes.
The remaining promotedObject.* fields are Meta-only. Platforms other than
Meta and TikTok ignore promotedObject entirely.
Response Body
application/json
application/json
import Zernio from '@zernio/node';const zernio = new Zernio({ apiKey: process.env.ZERNIO_API_KEY });const { data } = await zernio.ads.createStandaloneAd({ body: { accountId: 'account_abc123', adAccountId: 'adaccount_abc123', name: 'Example', },});console.log(data);{
"ad": {
"_id": "string",
"name": "string",
"platform": "facebook",
"status": "active",
"adType": "boost",
"goal": "engagement",
"isExternal": true,
"budget": {
"amount": 0,
"type": "daily"
},
"metrics": {
"spend": 0,
"impressions": 0,
"reach": 0,
"clicks": 0,
"ctr": 0,
"cpc": 0,
"cpm": 0,
"engagement": 0,
"conversions": 0,
"costPerConversion": 0,
"actions": {
"link_click": 160,
"post_engagement": 300,
"offsite_conversion.fb_pixel_purchase": 42
},
"actionValues": {
"offsite_conversion.fb_pixel_purchase": 2456.78,
"offsite_conversion.fb_pixel_add_to_cart": 980.5
},
"purchaseValue": 0,
"roas": 0,
"lastSyncedAt": "2019-08-24T14:15:22Z"
},
"platformAdId": "string",
"platformAdAccountId": "string",
"platformCampaignId": "string",
"platformAdSetId": "string",
"campaignName": "string",
"adSetName": "string",
"platformObjective": "OUTCOME_SALES",
"optimizationGoal": "OFFSITE_CONVERSIONS",
"platformAdAccountName": "Zernio - previously Late",
"platformCreatedAt": "2019-08-24T14:15:22Z",
"bidStrategy": "LOWEST_COST_WITHOUT_CAP",
"bidAmount": 5,
"roasAverageFloor": 2,
"promotedObject": {
"custom_event_type": "PURCHASE",
"pixel_id": "string",
"page_id": "string",
"application_id": "string",
"product_set_id": "string"
},
"creative": {
"thumbnailUrl": "string",
"imageUrl": "string",
"videoId": "string",
"videoUrl": "string",
"objectType": "string",
"objectStoryId": "string",
"effectiveObjectStoryId": "string",
"effectiveInstagramMediaId": "string",
"instagramUserId": "string",
"instagramPermalinkUrl": "string",
"mediaUrls": [
"string"
],
"body": "string",
"googleHeadline": "string",
"googleDescription": "string",
"linkUrl": "string",
"pinterestImageUrl": "string",
"pinterestTitle": "string",
"pinterestDescription": "string"
},
"targeting": {},
"schedule": {
"startDate": "2019-08-24T14:15:22Z",
"endDate": "2019-08-24T14:15:22Z"
},
"rejectionReason": "string",
"createdAt": "2019-08-24T14:15:22Z",
"updatedAt": "2019-08-24T14:15:22Z"
},
"message": "string"
}{
"error": "Unauthorized"
}Boost post as ad POST
Creates a paid ad campaign from an existing published post. Creates the full platform campaign hierarchy (campaign, ad set, ad).
Create Click-to-WhatsApp ad POST
Creates one or more Click-to-WhatsApp (CTWA) ads on Meta under a single campaign and ad set. When tapped, each ad opens a WhatsApp conversation with the business attached to the supplied Facebook Page. The full hierarchy (campaign, ad set, creative(s), ad(s)) is created and activated in one call. The CTA is locked to WHATSAPP_MESSAGE and the destination is hard-coded to api.whatsapp.com/send; Meta resolves the actual WhatsApp number from the Page-to-WA pairing configured in Page settings or Business Manager. Supports two mutually-exclusive shapes: - **Single-creative**: supply top-level `headline`, `body`, and one of `imageUrl` / `video`. Creates 1 campaign + 1 ad set + 1 ad. - **Multi-creative**: supply a `creatives[]` array with N entries (each carrying its own headline, body, and image/video). Creates 1 campaign + 1 ad set + N ads sharing budget and targeting so Meta A/Bs the creatives inside a single auction instead of fragmenting budget across N parallel campaigns. Recommended when launching multiple creative variants for the same campaign. Prerequisites enforced by Meta (surfaced as platform_error on failure): the Facebook Page must be paired with a verified WhatsApp Business number, the WhatsApp Business Account must be business-verified, and the Meta access token must carry ads_management.