Create standalone ad
Create a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X, LinkedIn, and OpenAI Ads (ChatGPT Ads).
Google Performance Max: set campaignType: "pmax" and supply assetGroup with text, images by role, business name and finalUrl. Creates a daily budget, PAUSED campaign and asset group atomically. validateOnly: true validates the complete request with Google without creating or persisting resources. Read assets with GET /v1/ads/campaigns/{campaignId}/asset-groups. The logo is required; video is optional via assetGroup.youtubeVideoId. Brand guidelines are disabled at creation. All supplied asset links are validated together against Google's minimum asset requirements. PMax rejects ACTIVE creation, portfolio bidding, bid caps, legacy creative fields and attach shapes. Geo and language targeting are supported; omitted geo targets all locations. PMax does not require top-level goal, headline, body or linkUrl. Supported bidding: omitted or LOWEST_COST_WITHOUT_CAP for Maximize Conversions, COST_CAP plus bidAmount for target CPA, LOWEST_COST_WITH_MIN_ROAS plus roasAverageFloor for Maximize Conversion Value with target ROAS.
Other mutually-exclusive request shapes are selected by the body:
- Legacy single-creative shape (all platforms, the default).
- Meta-only multi-creative shape via the creatives array: one ad set with N ads sharing budget and targeting.
- Attach shape via adSetId: adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, Google Ads, TikTok, and LinkedIn). On LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted. On LinkedIn goal may be omitted too (taken from the Campaign's objective), and the created ad's targeting echoes the Campaign's audience.
Meta accepts creativeFeatures on the single and attach shapes and as defaults for creatives[]; an item replaces the whole feature map. promotion is not supported on any shape and any object is rejected with 400. Reusing existingCreativeId uses the existing creative settings instead of new settings. Requested settings are persisted for lists, exports, and default ad-detail reads.
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.
Headers
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.
Request body
Example request
{
"creativeFeatures": {
"auto_promotion_tag": "OPT_IN"
},
"creatives": [
{
"creativeFeatures": {
"auto_promotion_tag": "OPT_IN"
}
}
],
"placementAssets": {
"defaultImageUrl": "https://example.com/feed-4x5.jpg",
"rules": [
{
"imageUrl": "https://example.com/feed-4x5.jpg",
"headline": "Build with Zernio",
"body": "Schedule social posts from your app.",
"description": "One API for your social content.",
"placements": {
"publisherPlatforms": [
"facebook"
],
"facebookPositions": [
"feed"
]
}
},
{
"imageUrl": "https://example.com/story-9x16.jpg",
"headline": "Your next story",
"body": "Bring your social workflow to Zernio.",
"placements": {
"publisherPlatforms": [
"facebook"
],
"facebookPositions": [
"story",
"facebook_reels"
]
}
}
]
},
"locationTargetingType": "presence",
"assetGroup": {
"finalUrl": "https://zernio.com",
"headlines": [
"Schedule posts",
"One social API",
"Build with Zernio"
],
"longHeadline": "Schedule social content from your app with Zernio",
"descriptions": [
"Connect your social accounts.",
"Publish and manage social content through one API."
],
"businessName": "Zernio",
"images": {
"landscape": [
"https://example.com/landscape.png"
],
"square": [
"https://example.com/square.png"
],
"logo": [
"https://example.com/logo.png"
]
}
},
"additionalHeadlines": [
"Schedule Your Posts",
{
"text": "Build With Zernio",
"pinnedField": "HEADLINE_2"
}
],
"additionalDescriptions": [
"Build social publishing into your application.",
{
"text": "Connect social accounts with one API.",
"pinnedField": "DESCRIPTION_2"
}
]
}Response
validateOnly dry-run passed, nothing was created
Changes
Changed in 29 of the 56 revisions of this API.2523104
- ▲
added
subschema #1subschema #2to the response bodyoneOflist for the response statusresponse-body-one-of-added
- ○
removed
subschema #1subschema #2from the response bodyoneOflist for the response statusresponse-body-one-of-removed
- ▲
- ▲
the
/request property type changed fromobjectto no typerequest-property-type-changed
- ▲
the
/request property type changed fromobjectto no typerequest-property-type-changed
- ▲
the
/request property type changed fromobjectto no typerequest-property-type-changed
- ▲
the
//////request property type changed fromobjectto no typerequest-property-type-changed
- ▲
the
//////request property type changed fromobjectto no typerequest-property-type-changed
- ▲
the
/request property type changed fromobjectto no typerequest-property-type-changed
- ●
removed the request property
//request-property-removed
- ●
removed the request property
//request-property-removed
- ●
removed the request property
//request-property-removed
- ●
removed the request property
//request-property-removed
- ●
removed the request property
//request-property-removed
- ●
removed the request property
//request-property-removed
- ●
removed the request property
///////request-property-removed
- ●
removed the request property
///////request-property-removed
- ●
removed the request property
///////request-property-removed
- ●
removed the request property
///////request-property-removed
- ●
removed the request property
///////request-property-removed
- ●
removed the request property
///////request-property-removed
- ●
removed the request property
//request-property-removed
- ●
removed the request property
//request-property-removed
- ○
added the new optional request property
new-optional-request-property
- ○
added
subschema #1subschema #2to the/request propertyoneOflistrequest-property-one-of-added
- ○
added
subschema #1subschema #2to the/request propertyoneOflistrequest-property-one-of-added
- ○
added
subschema #1subschema #2to the/request propertyoneOflistrequest-property-one-of-added
- ○
added
subschema #1subschema #2to the//////request propertyoneOflistrequest-property-one-of-added
- ○
added
subschema #1subschema #2to the//////request propertyoneOflistrequest-property-one-of-added
- ○
added
subschema #1subschema #2to the/request propertyoneOflistrequest-property-one-of-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
This revision also has 2 changes that name no endpoint, such as unreferenced schemas being removed. See the revision's changelog
- ▲
- ○
added the non-success response with the status
response-non-success-status-added
- ○
- ○
added the new optional request property
new-optional-request-property
- ○
- ▲
added
subschema #1subschema #2to the response bodyoneOflist for the response statusresponse-body-one-of-added
- ○
removed
subschema #1subschema #2from the response bodyoneOflist for the response statusresponse-body-one-of-removed
- ▲
- ○
added the new optional request property
new-optional-request-property
- ○
added the new
BC_AUTH_TTenum value to the request propertyrequest-property-enum-value-added
- ○
- ○
added the new optional request property
new-optional-request-property
- ○
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
added the optional property
/to the response with the statusresponse-optional-property-added
- ○
- ○
added the new optional request property
new-optional-request-property
- ○
added the new optional request property
/////new-optional-request-property
- ○
added the new optional request property
//////new-optional-request-property
- ○