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

# Update a campaign

`PUT /v1/ads/campaigns/{campaignId}`

Campaign-level edits. Send at least one of `budget`, `bidStrategy`, `name`
or `platformSpecificData`. An unsupported field is always an error, never a
silent drop.

| Body field | Meta | Google | Others |
|---|---|---|---|
| `bidStrategy` | Yes | Yes | 501 |
| `bidAmount`, `roasAverageFloor` | 400 — ad-set level | Yes | 400 |
| `budget` (CBO; ABO returns 409) | Yes | 501 | 501 |
| `name` | Yes | 501 | 501 |
| `platformSpecificData.spendCap` | Yes | 400 | 400 |
| `accountId` (empty campaigns) | Yes | - | - |

Google maps the shared enum onto its own strategies: `LOWEST_COST_WITHOUT_CAP`
to Maximize Clicks, `LOWEST_COST_WITH_BID_CAP` to Maximize Clicks with a max
CPC (`bidAmount`), `COST_CAP` to Target CPA (`bidAmount`),
`LOWEST_COST_WITH_MIN_ROAS` to Target ROAS (`roasAverageFloor`). A campaign on
a PORTFOLIO bidding strategy is rejected: detach it in Google Ads first, since
it is shared across campaigns.

`accountId` forwards the update straight to Meta for a campaign with zero ads,
which would otherwise 404; the response then carries `updated: 0`.

## Path parameters

- `campaignId` string, required

## Request body

- object
  - `platform` 'facebook' | 'instagram' | 'google', required — Required: platform campaign IDs are not globally unique.
  - `accountId` string — **Meta only.** Zernio SocialAccount id owning the ad account. Needed only for an EMPTY campaign (zero ads); ignored otherwise.
  - `bidStrategy` 'LOWEST_COST_WITHOUT_CAP' | 'LOWEST_COST_WITH_BID_CAP' | 'COST_CAP' | 'LOWEST_COST_WITH_MIN_ROAS' — Meta bid strategy. Same enum applies at campaign and ad-set level; ad-set value (when set) overrides campaign-level. Cross-field rules: - `LOWEST_COST_WITHOUT_CAP` (default): auto-bid, forbids `bidAmount` and `roasAverageFloor`. - `LOWEST_COST_WITH_BID_CAP` / `COST_CAP`: require `bidAmount` (whole currency units). - `LOWEST_COST_WITH_MIN_ROAS`: requires `roasAverageFloor` (decimal multiplier, 2.0 = 2.0x). Source: facebook-business-sdk-codegen api_specs/specs/enum_types.json (`AdSet_bid_strategy`, `Campaign_bid_strategy`).
  - `bidAmount` number — **Google only.** Whole currency units (USD: 12 = $12.00). Max CPC for LOWEST_COST_WITH_BID_CAP, CPA target for COST_CAP; required for both.
  - `roasAverageFloor` number — **Google only.** Decimal ROAS multiplier (2.0 = 2.0x), required for LOWEST_COST_WITH_MIN_ROAS.
  - `budget` object — **Meta only.** The CBO budget.
    - `amount` number, required — Budget amount in the ad account's currency
    - `type` 'daily' | 'lifetime', required
  - `name` string — **Meta only.** Rename the campaign.
  - `platformSpecificData` object — **Meta only.** Platform implied by the `platform` body param, same convention as POST /v1/ads/create.
    - `spendCap` number, nullable — Campaign lifetime spend cap, in the ad account's currency (Meta `spend_cap`). Pass null to remove the cap; 0 is rejected by Meta.

## Response `200`

Campaign updated

- object — Echoes back only the fields you sent, plus `updated`.
  - `updated` integer — Local Ad documents mirrored. 0 on the empty-campaign path.
  - `budget` AdBudget — Budget amount in the ad account's native currency (see the campaign's `currency` field for the code).
    - `amount` number, required
    - `type` 'daily' | 'lifetime', required
  - `budgetLevel` 'campaign'
  - `bidStrategy` 'LOWEST_COST_WITHOUT_CAP' | 'LOWEST_COST_WITH_BID_CAP' | 'COST_CAP' | 'LOWEST_COST_WITH_MIN_ROAS' — Meta bid strategy. Same enum applies at campaign and ad-set level; ad-set value (when set) overrides campaign-level. Cross-field rules: - `LOWEST_COST_WITHOUT_CAP` (default): auto-bid, forbids `bidAmount` and `roasAverageFloor`. - `LOWEST_COST_WITH_BID_CAP` / `COST_CAP`: require `bidAmount` (whole currency units). - `LOWEST_COST_WITH_MIN_ROAS`: requires `roasAverageFloor` (decimal multiplier, 2.0 = 2.0x). Source: facebook-business-sdk-codegen api_specs/specs/enum_types.json (`AdSet_bid_strategy`, `Campaign_bid_strategy`).
  - `bidAmount` number
  - `roasAverageFloor` number
  - `platformSpecificData` object

## Other responses

- `400` — Invalid input, or a field the resolved platform does not support at the campaign level (see the support table)
- `401` — Unauthorized
- `404` — Campaign not found
- `409` — Campaign is ABO — route to /v1/ads/ad-sets/{adSetId} instead
- `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/versions/f81ca70ea6b9/schema)
