Duplicate a campaign
Duplicates a campaign, including its ad sets, ads, creatives, and
targeting by default (deepCopy: true). The copy is created paused
so callers can review before launching.
Per-platform implementation:
- Meta uses the native
POST /{campaign-id}/copiesendpoint. - TikTok has no native copy primitive; Zernio walks the source
graph (
/v2/campaign/get/,/v2/adgroup/get/,/v2/ad/get/) and recreates each entity via the corresponding/create/endpoints, carrying over budget / targeting / bid_type / bid_price / deep_bid_type / creative fields. Spark Ad linkage (tiktok_item_id) is preserved. - LinkedIn has no native copy primitive; Zernio walks the source
CampaignGroup → Campaigns → Creatives and recreates each entity,
carrying over
type/costType/unitCost/optimizationTargetType/creativeSelection/objectiveType/format/dailyBudget/totalBudget/targetingCriteria/runScheduleand every Creative'scontentobject verbatim.statusOption: INHERITED_FROM_SOURCEis evaluated per entity: any Group / Campaign / Creative whose source isACTIVEgets its clone activated too. Duplicating an ACTIVE campaign withINHERITED_FROM_SOURCEstarts a second front of spend the moment the clone activates — the safe default isPAUSED.
The new hierarchy is asynchronous to materialize in our DB — we
trigger sync discovery automatically. Set syncAfter: false to
skip and poll /v1/ads/tree on your own cadence.
Other platforms return 501 Not Implemented.
API key authentication - use your Zernio API key as a Bearer token
In: header
Path Parameters
Source platform campaign ID
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. Only 2xx responses are stored, so a request that failed with a 4xx can be retried with a corrected body under the SAME key.
length <= 255"facebook" | "instagram" | "tiktok" | "linkedin"Copy child ad sets + ads + creatives + targeting
trueACTIVE = launch the clone immediately (spends the moment LinkedIn approves it). PAUSED = clone stays DRAFT, safe default. INHERITED_FROM_SOURCE = mirror each entity's source status per-entity. Duplicating an ACTIVE campaign this way starts a second front of spend.
"PAUSED""ACTIVE" | "PAUSED" | "INHERITED_FROM_SOURCE"Reschedule the copied hierarchy's start time
date-timedate-time"DEEP_RENAME" | "ONLY_TOP_LEVEL_RENAME" | "NO_RENAME"Trigger ads discovery on the owning account after the copy succeeds
trueResponse Body
application/json
application/json
import Zernio from '@zernio/node';const zernio = new Zernio({ apiKey: process.env.ZERNIO_API_KEY });const { data } = await zernio.adcampaigns.duplicateAdCampaign({ path: { campaignId: 'campaign_abc123', }, body: { platform: 'facebook', },});console.log(data);{
"copiedCampaignId": "string",
"discovery": "triggered",
"raw": {}
}{
"error": "Unauthorized"
}Boost post as ad POST
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).
Duplicate an ad set POST
Duplicates an ad set, including its ads and creatives by default (`deepCopy: true`), via Meta's native `POST /{adset-id}/copies`. The copy is created paused so callers can review before launching. `campaignId` retargets the copy into another campaign; omitted = the source's own campaign. The new hierarchy materializes asynchronously — sync discovery is triggered automatically (`syncAfter: false` to skip).