Boost post as ad
Creates a paid ad from an existing published post, keeping the post's engagement. By default it provisions the whole hierarchy (campaign, ad set, ad).
Attach shape (Meta). Send adSetId to put the ad under an EXISTING
ad set instead, so that ad set keeps its learning phase. It then owns
budget, schedule and targeting, and sending any of those alongside
adSetId is a 400 rather than a silent drop. budget is required only
without adSetId.
instagramAccountId, destinationType and adSetId are Meta-only and
return 400 on other platforms.
Retries. Boosts are NOT idempotent and can take minutes when Meta requires re-hosting an Instagram video, so do not retry on client timeout. Send an Idempotency-Key header to make retries safe: same key and body replays the original 201, and distinct keys always create distinct ads. Without the header, an identical request is treated as a retry: while one is in flight it returns 409, and within 10 minutes of a completed boost it returns the already-created ad instead of creating another. To intentionally duplicate an ad, send distinct Idempotency-Keys (or vary the body, e.g. the name).
Authorization
bearerAuth 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 retries safe. Same key + same body replays the original response; same key + different body → 422; key still processing → 409.
length <= 255Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
{ "ad": { "_id": "string", "name": "string", "platform": "facebook", "status": "active", "configuredStatus": "string", "reviewStatus": "in_review", "adType": "boost", "creativeType": "carousel", "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, "allConversions": 0, "costPerConversion": 0, "actions": { "property1": 0, "property2": 0 }, "actionValues": { "property1": 0, "property2": 0 }, "purchaseValue": 0, "roas": 0, "costPerAction": { "property1": 0, "property2": 0 }, "outboundClicks": 0, "outboundClicksCtr": 0, "inlineLinkClicks": 0, "inlineLinkClickCtr": 0, "uniqueClicks": 0, "uniqueCtr": 0, "videoPlayActions": 0, "video30SecWatchedActions": 0, "videoThruplayWatchedActions": 0, "videoP25WatchedActions": 0, "videoP50WatchedActions": 0, "videoP75WatchedActions": 0, "videoP95WatchedActions": 0, "videoP100WatchedActions": 0, "videoAvgTimeWatchedActions": 0, "costPerThruplay": 0, "funnel": { "landingPageViews": 0, "contentViews": 0, "searches": 0, "wishlistAdds": 0, "cartAdds": 0, "checkoutsInitiated": 0, "paymentInfoAdds": 0, "purchases": 0, "leads": 0, "registrationsCompleted": 0, "appInstalls": 0, "messagingConversationsStarted": 0, "messagingFirstReplies": 0 }, "engagementBreakdown": { "postEngagement": 0, "pageEngagement": 0, "reactions": 0, "comments": 0, "shares": 0, "saves": 0, "pageLikes": 0, "videoViews": 0, "linkClicks": 0 }, "lastSyncedAt": "2019-08-24T14:15:22Z" }, "platformAdId": "string", "platformAdAccountId": "string", "platformCampaignId": "string", "platformAdSetId": "string", "campaignName": "string", "adSetName": "string", "platformObjective": "string", "optimizationGoal": "string", "costType": "string", "servingStatuses": [ "string" ], "platformAdAccountName": "string", "platformCreatedAt": "2019-08-24T14:15:22Z", "bidStrategy": "LOWEST_COST_WITHOUT_CAP", "bidAmount": 0, "roasAverageFloor": 0, "promotedObject": { "custom_event_type": "string", "pixel_id": "string", "page_id": "string", "application_id": "string", "product_set_id": "string" }, "creative": { "thumbnailUrl": "string", "imageUrl": "string", "videoId": "string", "videoUrl": "string", "creativeId": "string", "objectType": "string", "objectStoryId": "string", "effectiveObjectStoryId": "string", "pageId": "string", "effectiveInstagramMediaId": "string", "instagramUserId": "string", "instagramPermalinkUrl": "string", "mediaUrls": [ "string" ], "isServing": true, "servingHoldReasons": [ "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"}Create standalone ad
Creates a paid ad with custom creative across Meta, Google Ads, Pinterest, TikTok, X/Twitter, LinkedIn, and OpenAI Ads (ChatGPT Ads). 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 an attach shape via adSetId that adds one new ad to an existing ad set, inheriting its budget, targeting, and schedule (Meta, TikTok, and LinkedIn; on LinkedIn adSetId is the existing Campaign id, and the budget, schedule, targeting and bidding fields must be omitted). 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.
Update ad
Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style — `headline` is ignored, `body` becomes `ad_text`). - **Google**: status, budget, KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords`, and DEVICE bid adjustments via `targeting.devices` — each list you send becomes the FULL new set of its kind (criteria not in the list are removed); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate broad targeting post-create without recreating the campaign. `creative` returns 501. - **LinkedIn**: status, budget, targeting (geo countries only, applied to the LinkedIn Campaign via PARTIAL_UPDATE), and creative (uploads new media, creates a replacement inline creative on the same campaign, pauses the old one). - **Pinterest / X / OpenAI Ads**: status + budget only. Sending `targeting` or `creative` returns 501 with code `unsupported_platform_operation`. OpenAI Ads budget is lifetime-only (see `budget.type` below). **Google keyword replacement:** These edits affect the ad's entire ad group, including sibling ads. Positive (`targeting.keywords`) and negative (`targeting.negativeKeywords`) sets are independent: omit a field to leave that set unchanged, or send `[]` to remove every keyword of that kind. Zernio compares each supplied set with Google's live criteria by case-insensitive keyword text and match type. A matching criterion is left untouched, retaining its criterion ID, enabled/paused status, keyword-level bid overrides, labels, and criterion-associated history/statistics. Zernio does not reset its quality score; Google continues to calculate scores and statistics normally. Text comparison does not trim whitespace. A bare string or an object without `matchType` means `broad`, not the existing criterion's match type. For example, resending an existing `{ "text": "plumber", "matchType": "exact" }` preserves it; sending `"plumber"` instead removes that EXACT criterion and requests a BROAD one. Changing text or match type removes criteria no longer requested and creates any missing criteria. New criteria get new IDs and do not inherit removed criteria's bid overrides, labels, or history. Historical reporting for a removed criterion is not transferred to its replacement. To add keywords without replacing a set, use [POST /v1/ads/keywords](https://docs.zernio.com/ad-campaigns/add-ad-keywords). Use `PATCH /v1/ads/keywords/{keywordId}` to pause/enable one keyword, or `DELETE /v1/ads/keywords/{keywordId}` to remove it.