Zernio
APIFor you
Zernio
APIFor you
API Reference

Messaging & Call Ads

Create Click-to-Call adPOSTCreate messaging adPOST
Dashboard
OverviewPlatformsAPI ReferenceResources
Messaging & Call Ads

Create Click-to-Call ad

Creates a Meta ad with a Call Now button that dials your phone number, optimized for quality calls.

Same shape and flow as POST /v1/ads/ctwa, but the CTA is CALL_NOW dialing phoneNumber via a tel: link. The ad set is destination_type PHONE_CALL optimizing QUALITY_CALL and the campaign objective defaults to OUTCOME_LEADS. Supports the same single-creative and multi-creative shapes as CTWA.

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). If the first request is cut off mid-create (for example by a function timeout), its key can stay in progress and keep returning 409 until it expires; use a new key to retry sooner, after checking whether the ad was created. Keys are scoped to your credential and expire after 24h.


PlatformsMeta
POST
/v1/ads/call

Authorization

bearerAuth
AuthorizationBearer <token>

API key authentication: send your Zernio API key in the Authorization header, prefixed with Bearer.

In: header

Header Parameters

Idempotency-Key?string

Optional client-generated unique key (e.g. a UUID) that makes retries safe. Same key + same body replays the original response; same key + different body → 422; key still processing → 409. A request cut off mid-handler (for example by a function timeout) can leave its key in progress, answering 409 until the key expires after 24 hours.

Lengthlength <= 255

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

In addition to the required list, the request must use EXACTLY ONE of the two shapes:

  • Single-creative: headline, body, and one of imageUrl / video, OR platformPostId / objectStoryId to reuse an organic post. On POST /v1/ads/messaging, placementAssets can replace imageUrl / video.
  • Carousel (messaging and CTWA): body and carouselCards (2-10 image cards) instead of imageUrl / video, top level or per creatives[] entry.
  • Multi-creative: a non-empty creatives[] array. Top-level creative fields must NOT be set on this shape.

Existing post references work on messaging and CTWA only (not call ads). They cannot be combined with each other or with headline, body, imageUrl or video. welcomeMessage works on them (it lives on the ad, not the post). No media is uploaded and the organic post is retained. Fresh creatives still require headline, body, and image or video.

The route enforces this at the Zod boundary; OpenAPI's required cannot express the OR cleanly.

Campaign, ad set and targeting fields match POST /v1/ads/create on Meta and run through the same builders: the full targeting set (including rawTargeting, languages, gender, exclusions and savedTargetingId), budgetLevel (campaign budget), startDate / endDate in the ad account timezone, and existingCampaignId to add a new ad set to a campaign you already have.

Response Body

application/json

application/json

application/json

application/json

import Zernio from '@zernio/node';const zernio = new Zernio({ apiKey: process.env.ZERNIO_API_KEY });const { data } = await zernio.messagingads.createCallAd({  body: {    accountId: 'account_abc123',    adAccountId: 'adaccount_abc123',    name: 'Example',    phoneNumber: 'string',    linkUrl: 'https://example.com',  },});console.log(data);
{  "adType": "single",  "ad": {},  "message": "string",  "warnings": [    "string"  ]}
Was this page helpful?

Send conversion events

Sends conversion events, such as purchases or leads, from your server to an ad platform so it can attribute and optimize ads. Relay one or more conversion events to the target ad platform's native Conversions API. Platform is inferred from the provided `accountId`. Requires the Ads add-on. Supported platforms: - Meta (`metaads`) via Graph API - Google Ads (`googleads`) via Data Manager API `ingestEvents` - LinkedIn (`linkedinads`) via `/rest/conversionEvents` - TikTok (`tiktokads`) via the Offline Events API `/offline/batch/` (OFFLINE conversions only) - OpenAI Ads (`openaiads`) via its Conversions API (a separate host, `bzr.openai.com`) - Pinterest (`pinterestads`) via `POST /v5/ad_accounts/{id}/events` - Reddit (`redditads`) via the Reddit Conversions API (`POST /api/v3/pixels/{pixelId}/conversion_events`) `destinationId` semantics differ per platform: - Meta: pixel (dataset) ID, e.g. `123456789012345` - Google: conversion action resource name, e.g. `customers/1234567890/conversionActions/987654321` - LinkedIn: conversion rule ID or URN, e.g. `104012` or `urn:lla:llaPartnerConversion:104012` - TikTok: Offline Event Set ID, e.g. `7057103914977558530` - OpenAI Ads: pixel wire id (numeric `pixel_id`, distinct from the internal pixel id), as returned by `GET /v1/accounts/{accountId}/conversion-destinations` - Pinterest: numeric ad account id, e.g. `549755885175` (Pinterest attributes to the ad account, not to a tag) - Reddit: pixel id, e.g. `a2_abc123`, as returned by `GET /v1/accounts/{accountId}/conversion-destinations` (any other shape returns 400) Pinterest notes: each event needs an `email`, or `ipAddress` plus `userAgent`; others are listed in `failures` with code `INVALID_EVENT` and the rest are still sent. `clickIds.epik` (the `_epik` cookie) is sent as `click_id`. `actionSource` `web` stays `web`, offline sources become `offline`, and app events need `platformData.action_source` `app_android` or `app_ios`. Pinterest answers per event, so one bad event does not fail its chunk (failures carry code `PINTEREST_EVENT_FAILED`). `consent.adUserData: DENIED` sets `opt_out`. The connected user needs a Business Access role on the ad account (403 otherwise). Reddit notes: each event needs a match key: `clickIds.rdt_cid`, `clickIds.rdt_uuid`, `email`, `phone`, `externalId`, or `ipAddress` plus `userAgent`. Reddit accepts events up to 7 days old, and `eventTime` is unix SECONDS (a value more than an hour in the future is refused as milliseconds). Events failing these checks are listed in `failures` with code `INVALID_EVENT` and the rest are still sent. Email (lowercased, dots and `+tags` stripped from the local part), phone (E.164 with the leading `+`) and `externalId` are SHA-256 hashed; IP and user agent go plaintext. `consent.adUserData: DENIED` sends no user fields. `actionSource` maps to WEBSITE (`web`), APP (`app`) or OTHER, overridable with `platformData.action_source`; `platformData.order_id` is forwarded. `testCode` is sent as Reddit's `test_id`. The connection must hold the `adsconversions` permission: one authorized without it returns 403 `reconnect_required` (reconnect via GET /v1/connect/redditads/ads), and a Reddit user with no role on the ad account that owns the pixel returns 403 `insufficient_permissions`. Reddit throttling and other rejections are reported per chunk in `failures` with code `REDDIT_REJECTED`. TikTok notes: this path sends OFFLINE conversions (in-store / CRM / call-center), not web-pixel events. Each event must carry an email or phone (TikTok requires at least one). The connected TikTok ads account must have granted the Offline Events permission; older grants must reconnect. OpenAI Ads notes: requires a tracking tag (pixel) to already exist on the account. Returns 422 with code `TRACKING_TAG_REQUIRED` if `POST /v1/accounts/{accountId}/tracking-tags` hasn't been called yet. Callers can list valid destinations via `GET /v1/accounts/{accountId}/conversion-destinations`. All PII (email, phone, names, external IDs) is hashed with SHA-256 server-side per each platform's normalization spec, including Google's Gmail-specific dot/plus-suffix stripping. Send plaintext. LinkedIn `externalIds` are passed through as plaintext per LinkedIn's spec; only emails and phones are hashed. For LinkedIn, the connected account must have been authorized after the Conversions API rollout (i.e. the OAuth grant must include `rw_conversions`). Older accounts must reconnect. Batching is handled automatically. Meta caps at 1000 events per request and rejects the entire batch if any event is malformed. Google caps at 2000. LinkedIn caps at 5000 and is also all-or-nothing per chunk. OpenAI Ads caps at 1000 per request; larger submissions are split into 1000-event chunks, each all-or-nothing (a malformed event fails every event in that chunk, not the whole request). Reddit works the same way, in chunks of 1000. Dedup: pass a stable `eventId` on every event. Meta and LinkedIn use it to dedupe against browser-side pixel/Insight Tag events; Google maps it to `transactionId`; Reddit receives it as `conversion_id`, its dedup key against Reddit Pixel events. Per-platform `eventName` semantics: - Meta: free-form. Standard names (Purchase, Lead, ...) match Meta's built-in events; custom strings are accepted. - Google: ignored. The conversion action's category determines the event type. Send the standard name closest to your action for documentation, but the platform will not branch on it. - LinkedIn: ignored. The conversion rule's `type` (LEAD, PURCHASE, etc.) is locked to the destination at rule-creation time. Send the standard name for documentation; LinkedIn does not branch on it. - OpenAI Ads: a fixed subset of standard names (Purchase, Lead, AddToCart, ViewContent, InitiateCheckout, CompleteRegistration, Subscribe, StartTrial, Schedule) maps 1:1 onto OpenAI's own event-type enum; any other standard name or custom string is sent as `type: custom` with the name preserved. - Pinterest: standard names map onto Pinterest's (Purchase = `checkout`, AddToCart = `add_to_cart`, InitiateCheckout = `initiate_checkout`, AddPaymentInfo = `add_payment_info`, Lead = `lead`, CompleteRegistration = `signup`, Subscribe = `subscribe`, ViewContent = `view_content`, Search = `search`, PageView = `page_visit`); any other string is sent as is, so it matches an advertiser defined event of that name.

Create messaging ad

Creates a Meta ad that opens a chat with you on WhatsApp, Messenger or Instagram Direct when someone taps it. Creates a click-to-message ad; `destination` selects where the tapped ad opens a conversation: WhatsApp, the Page's Messenger inbox or the linked Instagram account's Direct inbox. `destinations` puts two or three of them on one ad set and lets Meta pick the app per viewer. The ad set is created with the matching destination_type and CONVERSATIONS optimization; the campaign objective defaults to OUTCOME_ENGAGEMENT. Supports single-creative and multi-creative shapes. Supersedes POST /v1/ads/ctwa (deprecated, equivalent to `destination: whatsapp`). Existing posts and reels are supported through `platformPostId` (alias `existingPostId`) or `objectStoryId`, either per creative or at the top level. Omit fresh media and copy for that creative. Optional `whatsappPhoneNumber` selects a number already paired with the Page (WhatsApp destination only). `accountId` is a Facebook, Instagram or Meta ads (business login) connection; `pageId` picks the Page when that connection was granted several. **Required fields per shape** (a missing one is a 400 naming it in `param`): - Always `accountId`, `adAccountId`, `name`, and exactly one of `destination` / `destinations`. - `budgetAmount` and `budgetType` unless `adSetId` or `existingCampaignId` is set, plus `endDate` for a lifetime budget. - Single image or video: `headline`, `body`, and exactly one of `imageUrl` / `video`. With `placementAssets`, `headline` and `body` only (the media comes from `placementAssets`). - `carouselCards`: `body` and the 2-10 cards; `headline` is optional, `imageUrl` / `video` / top-level `description` are a 400. - Existing post (`platformPostId` or `objectStoryId`): no copy or media fields. - `creatives[]`: the same rules per entry, with no top-level creative fields. - `welcomeMessage`, when sent: `text` plus exactly one of `prefillText` / `quickReplies`. **WhatsApp number prerequisite.** For the WhatsApp destination, link the WhatsApp number to the Facebook Page used for the ad before creating it: Meta checks the pairing at creation. Link it from the WhatsApp Business app (Settings > Business tools > Facebook & Instagram) or from the Page settings (Linked accounts > WhatsApp). Linking does not affect the number's WhatsApp connection in Zernio (Cloud API or coexistence), so no reconnect or re-sync is needed. If Meta creates a new ad set without the requested `whatsappPhoneNumber`, the 201 response carries a `warnings` entry. This can happen even when the number is linked (Meta can drop a Page's second linked number). **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). If the first request is cut off mid-create (for example by a function timeout), its key can stay in progress and keep returning 409 until it expires; use a new key to retry sooner, after checking whether the ad was created. Keys are scoped to your credential and expire after 24h.

creativeFeatures?

Meta enhancement settings for single or attached ads, and defaults for creatives[]. An item replaces the entire map, including with an empty object.

tracking?

Meta, plus urlTags on ChatGPT (OpenAI) and pixelId on Reddit. Meta: 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 is stored on the new creative as url_tags and retained on the ad for compatibility. 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. ChatGPT (OpenAI): urlTags becomes the ad's landing_page_configuration.query_string_template, which OpenAI appends to linkUrl on click. Reddit: pixelId picks the pixel of the new ad group, like promotedObject.pixelId (which wins when both are sent).

accountId*string

Facebook or Instagram SocialAccount ID.

Length1 <= length
adAccountId*string

Meta ad account ID, e.g. act_123456789.

Length1 <= length
name*string

Ad display name. Used to derive campaign / ad set names. On the multi-creative shape, each ad's Meta name gets a " #N" suffix (1-indexed) so Ads Manager shows them as a numbered batch.

Length1 <= length
campaignName?string

Exact name for the campaign this request provisions. Omitted keeps <name> - Campaign. Ignored with adSetId (the ad set already has a campaign).

Lengthlength <= 255
adSetName?string

Exact name for the ad set this request provisions. Omitted keeps <name> - Ad Set. Ignored with adSetId.

Lengthlength <= 255
platformPostId?string

Messaging and CTWA only. Platform post or reel ID, the same input boostPost takes as platformPostId. Facebook IDs become object_story_id; Instagram IDs become source_instagram_media_id run as the media owner (resolved from the media on a Meta ads business-login connection, so no Instagram connection is needed). Mutually exclusive with objectStoryId and fresh creative fields.

Length1 <= length
existingPostId?string
Deprecated

Alias of platformPostId, kept for existing callers. Sending both with different values is a 400.

Length1 <= length
objectStoryId?string

Messaging and CTWA only. Raw Facebook pageId_postId reference, used as object_story_id even with an Instagram account. Mutually exclusive with platformPostId and fresh creative fields.

Match^\d+_\d+$
pageId?string

Facebook Page the ad runs as, when the connection was granted several Pages. Defaults to the Page bound to the connection. Any Page granted to the connection is accepted; other ids answer 400 listing the granted Pages. Same semantics as pageId on POST /v1/ads/create.

whatsappPhoneNumber?string

WhatsApp only. Optional E.164 number already paired with the Facebook Page. Omit to let Meta select the paired number. Sent to the creative CTA and, when creating a new ad set, its promoted_object. Meta can accept the number yet create the ad set without it; the response then carries a warnings entry. Attach requests do not change the existing ad set. Stored as creative.whatsappPhoneNumber on every created ad.

Match^\+[1-9]\d{6,14}$
headline?string

Single-creative shape only. Mutually exclusive with creatives[]. Required on a single image or video ad (including one built with placementAssets); not used by a carouselCards ad and not accepted with an existing post reference.

Length1 <= length <= 255
body?string

Primary text shown above the image / video. Single-creative shape only. Mutually exclusive with creatives[].

Length1 <= length
description?string

Link description, independent of headline and body (Meta's link_data.description, video_data.link_description on video, and the shared description of a placementAssets feed). Meta shows it mainly on Facebook Feed placements, under the headline, when there is room; Instagram, Stories, Reels and Messenger placements do not display it. Also accepted per entry in creatives[]. Not allowed with an existing post creative.

Length1 <= length <= 255
imageUrl?string

Image asset for single-creative shape. Mutually exclusive with video and with creatives[]. Required on the single-creative shape if neither video nor an existing post reference is supplied.

Formaturi
video?

Video creative for single-creative shape. Mutually exclusive with imageUrl and with creatives[]. Required on the single-creative shape if neither imageUrl nor an existing post reference is supplied.

welcomeMessage?

Custom chat welcome message (Meta's page_welcome_message, "Mensaje de bienvenida" / "Mensaje predefinido" in Ads Manager). Single-creative shape only; for creatives[] set it per entry.

carouselCards?array<>

Messaging and CTWA only (a 400 on POST /v1/ads/call). A hand-built carousel of 2-10 image cards, sent to Meta in the order given as link_data.child_attachments (by default Meta may reorder them for performance, since multi_share_optimized defaults to true; optimizeCardOrder: false keeps the order given); every card (and the carousel itself) carries the destination's messaging call to action (WHATSAPP_MESSAGE, MESSAGE_PAGE or INSTAGRAM_MESSAGE), so a tap on any card opens the conversation. Replaces imageUrl / video (sending either is a 400). body is required as the primary text; headline is optional and only names the creative (each card has its own headline); a top-level description is a 400 (set it per card). welcomeMessage, whatsappPhoneNumber and destinations apply as on a single-image ad. Also a 400 with placementAssets, platformPostId, existingPostId or objectStoryId. Single-creative shape; for creatives[] set it per entry.

Items2 <= items <= 10
optimizeCardOrder?boolean

Only with carouselCards (a 400 without them). Sets the creative's link_data.multi_share_optimized. false keeps the cards in the order given; Meta then takes at most 5 cards, so false with more than 5 carouselCards is a 400. true lets Meta pick and reorder the cards for performance (up to 10). Omitted, nothing is sent and Meta's default (true) applies. Single-creative shape; for creatives[] set it per entry.

creatives?array<>

Multi-creative shape: N CTWA ads under one campaign + one ad set, sharing budget and targeting. Mutually exclusive with the top-level single-creative fields (headline / body / imageUrl / video): setting both is a 400, unlike POST /v1/ads/create where the top-level fields are silently ignored in multi-creative mode. Each entry supplies headline, body, and image/video, or a platformPostId or objectStoryId reference. Fresh and existing creatives can be mixed.

Items1 <= items
adSetId?string

Attach the creatives to this EXISTING messaging ad set instead of building a campaign, so the ad set keeps its learning phase. It then owns budget, targeting and schedule, so budgetAmount, budgetType, budgetLevel, startDate, endDate, objective, campaignStatus, adSetStatus, existingCampaignId, the special ad category fields and every targeting field except ageMin, ageMax, placements and advantageAudience are rejected with a 400 alongside it. Its destination_type must match the ad's destination.

existingCampaignId?string

Create the new messaging ad set (and its ads) under this EXISTING Meta campaign instead of a new one, e.g. several audience ad sets under one campaign. The campaign's objective must be OUTCOME_ENGAGEMENT, OUTCOME_SALES or OUTCOME_LEADS (400 otherwise). If the campaign has a campaign budget, omit budgetAmount and budgetType (400 if sent); otherwise they are required and land on the new ad set. objective, campaignName, campaignStatus, budgetLevel, specialAdCategories, specialAdCategoryCountry and adSetId are rejected alongside it. To add ads to an existing ad set instead, use adSetId.

Match^\d+$
budgetLevel?string

Where the budget lives. adset (default) puts it on the new ad set. campaign creates an Advantage campaign budget (CBO): the budget and bid strategy sit on the campaign and the ad set inherits them, same as POST /v1/ads/create. Not allowed with adSetId or existingCampaignId.

Value in

  • "adset"
  • "campaign"
budgetAmount?number

Budget amount in the ad account's currency major units (e.g. dollars for USD, not cents). Must be > 0. Required unless adSetId is set (the ad set owns it) or existingCampaignId names a campaign with a campaign budget.

Range0 < value
budgetType?string

Required unless adSetId is set or existingCampaignId names a campaign with a campaign budget. lifetime requires endDate.

Value in

  • "daily"
  • "lifetime"
currency?string

ISO 4217 currency code matching the ad account's currency (e.g. USD). Optional: Zernio resolves it from the ad account when omitted. The value selects the minor-unit exponent Zernio converts budget/bid amounts by before calling Meta (most currencies are cents; zero-decimal currencies like JPY/KRW are sent as-is).

Length3 <= length <= 3
startDate?string

When the ad set starts delivering. ISO 8601 date or date-time. A value with an offset (2027-01-15T10:00:00+01:00, ...Z) is used as is; one without an offset (2027-01-15T10:00:00) is read in the ad account's timezone, and a date-only value starts at 00:00 local. Defaults to now.

endDate?string

ISO 8601 date or date-time, read like startDate; a date-only value ends at 23:59:59 local. Required when budgetType is lifetime.

countries?array<>

ISO 3166-1 alpha-2 country codes. Defaults to ["US"] only when no other geo (cities, regions, zips, metros, customLocations) is supplied.

cities?array<>

City-level geo targeting for local CTWA campaigns. Each entry maps to Meta's TargetingGeoLocationCity. key is Meta's city ID. radius and distance_unit are coupled: set both or neither. Meta enforces a minimum city radius (~17 km / 10 mi); smaller values resolve to a 0-size audience and the ad fails at launch. For a tighter catchment use customLocations (lat/lng).

regions?array<>

Region / state-level geo targeting. key is Meta's region ID (lookupable via GET /v1/ads/targeting/search?type=region).

zips?array<>

ZIP / postal-code geo targeting. key is the platform's postal id resolved via /v1/ads/targeting/search.

metros?array<>

DMA / metro-area geo targeting. key is Meta's metro id (e.g. DMA:807).

countryGroups?array<>

Meta only. Continents and trade blocs (geo_locations.country_groups), for targeting a whole region without listing its countries. Combines with countries rather than replacing it, and is also accepted under excludedLocations. Discoverable via GET /v1/ads/targeting/search?dimension=geo&geoType=country_group.

customLocations?array<>

Point-radius geo (Meta geo_locations.custom_locations). Use for targeting a radius around a specific lat/long when no Meta city/region key fits. distanceUnit is required.

ageMin?integer
Range13 <= value <= 65
ageMax?integer
Range13 <= value <= 65
interests?array<>
audienceId?string

Custom audience ID to target.

placements?

Manual ad placements on the shared ad set. Omit for automatic placements. 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 and restricts which placements are eligible for click-to-WhatsApp ads, returning an actionable error which we surface.

gender?string

Restrict the audience by gender (Meta genders). Omit or send all for everyone; all is ignored in adSetId attach mode. Stored on the ad and read back in targeting.gender.

Value in

  • "all"
  • "male"
  • "female"
languages?array<string>

Audience languages (Meta locales). A bare ISO 639-1 code targets all regional variants ("en" = all English), a region-qualified code a specific one ("en_GB", "pt_BR"); unknown codes are rejected.

places?array<>

Meta place keys (from GET /v1/ads/targeting/search).

neighborhoods?array<>

Meta neighborhood keys (from GET /v1/ads/targeting/search).

excludedLocations?

Geo to exclude, same shape as POST /v1/ads/create (countries, countryGroups, regions, cities, zips, places, neighborhoods, customLocations).

behaviors?array<>

Behavior ids from /v1/ads/targeting/search?dimension=behavior. Meta: each dimension is its own flexible_spec entry (OR within, AND across). TikTok: video/creator interaction categories, sent as the ad group's actions.

workPositions?array<>
workEmployers?array<>
workIndustries?array<>
incomeTier?string

Normalized household-income tier, same as POST /v1/ads/create. Incompatible with housing, employment and credit specialAdCategories.

Value in

  • "top_5"
  • "top_10"
  • "top_10_25"
  • "top_25_50"
userOs?array<string>

Meta user_os, e.g. ["iOS_ver_14.0_and_above"].

Items1 <= items
userDevice?array<string>

Meta user_device.

Items1 <= items
audienceInclude?array<string>

Custom or lookalike audience ids to include.

Items1 <= items
audienceExclude?array<string>

Custom or lookalike audience ids to exclude.

Items1 <= items
savedTargetingId?string

ID of a saved_targeting audience (POST /v1/ads/audiences), expanded as the base targeting. Precedence: savedTargetingId, then targeting, then the flat fields.

targeting?

Nested targeting object, same contract as POST /v1/ads/create and boost. Flat fields win per key.

rawTargeting?

Meta targeting spec sent as the BASE layer of the ad set's targeting, exactly as POST /v1/ads/create does: use it for anything the flat fields cannot express, such as a layered flexible_spec (entries AND together, ids inside one entry OR). Flat fields you also send are layered on top and win per key. With rawTargeting present the US geo and advantage_audience: 0 defaults are not injected, so include targeting_automation in it (or send advantageAudience), as Meta requires it on create.

specialAdCategories?array<>

Meta special ad categories on the new campaign.

specialAdCategoryCountry?array<string>

Countries the special ad category applies to. Requires specialAdCategories.

advantageAudience?integer

Meta's Advantage+ audience expansion. 0 (default) keeps targeting strict; 1 lets Meta expand beyond the supplied targeting when its delivery system finds better matches. Always sent on CREATE (Meta requires it).

Value in

  • 0
  • 1
objective?string

Defaults to OUTCOME_ENGAGEMENT. OUTCOME_SALES and OUTCOME_LEADS require additional account configuration (Dataset linked to the WABA for sales) and may be rejected by Meta if missing.

Value in

  • "OUTCOME_ENGAGEMENT"
  • "OUTCOME_SALES"
  • "OUTCOME_LEADS"
status?string

Defaults to ACTIVE. PAUSED pauses only the top-most object this call creates: the new campaign (ad set and ads switched on), or, with adSetId, the new ads themselves.

Value in

  • "ACTIVE"
  • "PAUSED"
campaignStatus?string

Campaign-level status, same semantics as POST /v1/ads/create. Defaults to status. PAUSED holds the new campaign off while the ad set and ads switch on (one resume call brings the whole hierarchy live); ACTIVE with status: PAUSED switches the campaign on and pauses the new ad set instead. Only meaningful when a new campaign is being created; rejected with a 400 alongside adSetId (the attach shape reuses an existing campaign).

Value in

  • "ACTIVE"
  • "PAUSED"
adSetStatus?string

Ad-set-level status, same semantics as POST /v1/ads/create. Sets the new ad set's switch alone and overrides status for it. A level status (campaignStatus, adSetStatus, adStatus) always wins for its level, and status: PAUSED adds a hold of its own only when none of them is PAUSED. Rejected with a 400 alongside adSetId (that ad set already exists).

Value in

  • "ACTIVE"
  • "PAUSED"
adStatus?AdActivationStatus

Ad-level status, same semantics as POST /v1/ads/create. Sets the new ads' switch and overrides status for them, also with adSetId. Send campaignStatus, adSetStatus and adStatus all PAUSED to create every object paused.

Value in

  • "ACTIVE"
  • "PAUSED"
bidStrategy?string

Meta bid strategy applied to the shared ad set. Defaults to LOWEST_COST_WITHOUT_CAP (auto-bid) when omitted. LOWEST_COST_WITH_BID_CAP and COST_CAP require bidAmount. LOWEST_COST_WITH_MIN_ROAS requires roasAverageFloor. CTWA's optimization_goal is fixed to CONVERSATIONS, but the bid strategy is independent.

Value in

  • "LOWEST_COST_WITHOUT_CAP"
  • "LOWEST_COST_WITH_BID_CAP"
  • "COST_CAP"
  • "LOWEST_COST_WITH_MIN_ROAS"
bidAmount?number

Whole currency units (e.g. 5 = $5.00 on a USD account). Required when bidStrategy is LOWEST_COST_WITH_BID_CAP or COST_CAP; rejected otherwise.

Range0 < value
roasAverageFloor?number

Decimal ROAS multiplier (e.g. 2.0 = 2.0× ROAS floor). Required when bidStrategy is LOWEST_COST_WITH_MIN_ROAS; rejected otherwise. Meta enforces its own upper bound server-side.

Range0 < value
dsaBeneficiary?string

Legal entity that benefits from the ad. Required when targeting EU users (EU DSA, Article 26). Optional if the ad account has a default beneficiary: set it once via PATCH /v1/ads/accounts or in Meta Ads Manager, and Meta fills it in whenever the field is omitted.

Lengthlength <= 100
dsaPayor?string

Legal entity that pays for the ad. Can differ from dsaBeneficiary (for example, an agency paying for a client's ads). Same rules as dsaBeneficiary: required for EU targeting unless the ad account has a default payor.

Lengthlength <= 100
regionalRegulatedCategories?array<string>

Meta only. Regional regulation categories required when the ad set targets certain countries (e.g. AUSTRALIA_FINSERV, AUSTRALIA_UNIVERSAL, BRAZIL_REGULATION, INDIA_FINSERV, MALAYSIA_UNIVERSAL, SINGAPORE_UNIVERSAL, TAIWAN_FINSERV, TAIWAN_UNIVERSAL, THAILAND_UNIVERSAL). Forwarded to the ad set.

regionalRegulationIdentities?

Meta only. Verified identity IDs of the beneficiary and payer for each declared regionalRegulatedCategories value. Meta may require them on ad sets created through the API even when a default beneficiary and payer are set in Ads Manager advertising settings (seen on AUSTRALIA_FINSERV), so sending them explicitly is the reliable path. The value is the Verified identity ID (Meta Business Settings > Verified identities), not a Page or Business ID, and beneficiary and payer may be the same ID. Send each ID as a string of digits: Verified identity IDs can have 17 digits, more than a JSON number holds exactly, and a number that arrives rounded is rejected. Numbers up to 9007199254740991 are still accepted. The IDs reach Meta unchanged. Keys by category: AUSTRALIA_FINSERV uses australia_finserv_beneficiary / australia_finserv_payer; TAIWAN_FINSERV uses taiwan_finserv_beneficiary / taiwan_finserv_payer; INDIA_FINSERV uses india_finserv_beneficiary / india_finserv_payer; TAIWAN_UNIVERSAL uses taiwan_universal_beneficiary / taiwan_universal_payer; SINGAPORE_UNIVERSAL uses singapore_universal_beneficiary / singapore_universal_payer; AUSTRALIA_UNIVERSAL, BRAZIL_REGULATION, MALAYSIA_UNIVERSAL and THAILAND_UNIVERSAL use universal_beneficiary / universal_payer. When Meta rejects the ad set for a missing verified advertiser, the error carries param regionalRegulationIdentities, details.expectedIdentityKeys (the keys the declared categories expect), details.suggestedCategories (the markets Meta ties to that subcode) and Meta's metaCode, metaSubcode and fbtraceId. Ignored when adSetId adds the ad to an existing ad set.

phoneNumber*string

E.164 number the CALL_NOW CTA dials (e.g. +34600111222).

linkUrl*string

Website shown as the creative's link. Required: Meta rejects tel: as link_data.link; the phone number rides only the CTA.

Formaturi