---
title: "Duplicate a campaign"
method: POST
path: "/v1/ads/campaigns/{campaignId}/duplicate"
tags: ["Ad Campaigns"]
---

# Duplicate a campaign

`POST /v1/ads/campaigns/{campaignId}/duplicate`

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}/copies` endpoint.
- **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` /
  `runSchedule` and every Creative's `content` object verbatim.
  `statusOption: INHERITED_FROM_SOURCE` is evaluated **per entity**:
  any Group / Campaign / Creative whose source is `ACTIVE` gets its
  clone activated too. Duplicating an ACTIVE campaign with
  `INHERITED_FROM_SOURCE` starts a second front of spend the moment
  the clone activates — the safe default is `PAUSED`.

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.

## Path parameters

- `campaignId` string, required

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `platform` 'facebook' | 'instagram' | 'tiktok' | 'linkedin', required
  - `deepCopy` boolean — Copy child ad sets + ads + creatives + targeting
  - `statusOption` 'ACTIVE' | 'PAUSED' | 'INHERITED_FROM_SOURCE' — ACTIVE = 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.
  - `startTime` string, date-time — Reschedule the copied hierarchy's start time
  - `endTime` string, date-time
  - `renameStrategy` 'DEEP_RENAME' | 'ONLY_TOP_LEVEL_RENAME' | 'NO_RENAME'
  - `renamePrefix` string
  - `renameSuffix` string
  - `syncAfter` boolean — Trigger ads discovery on the owning account after the copy succeeds

## Response `200`

Campaign duplicated

- object
  - `copiedCampaignId` string — Platform ID of the new campaign
  - `discovery` 'triggered' | 'skipped' | 'failed'
  - `raw` object — Platform-native response from the copy endpoint (Meta includes ad_object_ids for child copies)

## Other responses

- `400` — Invalid input
- `401` — Unauthorized
- `404` — Source campaign not found
- `501` — Operation not supported on this platform

---

[API](https://skmtc.net/zernio/apis/zernio-api.md) · [All operations](https://skmtc.net/zernio/apis/zernio-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/zernio/zernio-api/revisions/15e893e69e8c/schema)
