Get live campaign details
Reads one campaign live from Meta, returned verbatim, so a caller that knows a
campaign id no longer has to page GET /v1/ads/campaigns to find it. The default
projection covers name, status, objective, buying type, bid strategy, budgets,
spend cap, schedule and issues_info. fields is a raw-passthrough override;
unknown fields return Meta's 400 verbatim. A campaign the resolved connection
cannot see comes back as Meta's own 400, not a 404.
Authorization
bearerAuth API key authentication: send your Zernio API key in the Authorization header, prefixed with Bearer.
In: header
Path Parameters
Meta campaign id (platformCampaignId).
Query Parameters
Zernio SocialAccount id (posting or ads variant) used to resolve the Meta token.
Comma-separated Graph field override. Supports nested {} projections and Graph field modifiers.
Response Body
application/json
application/json
application/json
application/json
application/json
import Zernio from '@zernio/node';const zernio = new Zernio({ apiKey: process.env.ZERNIO_API_KEY });const { data } = await zernio.adcampaigns.getAdCampaignDetails({ path: { campaignId: 'campaign_abc123', }, query: { accountId: 'account_abc123', },});console.log(data);{ "campaign": {}}Create a standalone campaign
Creates a campaign WITHOUT its first ad set / ad, on the platform of the given `accountId`. Ad sets join it later via `existingCampaignId` on the create endpoints. Platform notes: on Meta a budget here is campaign-level (CBO) by definition; omit it for ABO (each ad set carries its own budget), and `specialAdCategories` is Meta-only (400 elsewhere); `bidStrategy` is Meta and Google (400 elsewhere), and Google also accepts `portfolioBidStrategyId` instead. Google, X and OpenAI require a budget (422 without one; OpenAI accepts daily or lifetime, Google only `budgetType: daily`). On OpenAI `goal` sets the campaign objective, and `conversions` needs an active standard conversion event on the account. LinkedIn creates the campaign GROUP (our campaign level) and rejects a budget, which lives on the campaign (ad set) level there; it comes back `status: DRAFT`. Created `PAUSED` (TikTok `DISABLE`) unless `status: ACTIVE` where the platform supports it. **Idempotency:** send an `Idempotency-Key` header to make retries safe.
Update a campaign
Campaign-level edits. Send at least one of `budget`, `bidStrategy`, `portfolioBidStrategyId`, `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 | | `portfolioBidStrategyId` | 400 | Yes | 400 | | `budget` (CBO; ABO returns 409) | Yes | Daily only | OpenAI: daily or lifetime; others 501 | | `name` | Yes | 501 | 501 | | `platformSpecificData.spendCap` | Yes | 400 | 400 | | `accountId` (empty campaigns) | Yes | - | - | Meta budget edits check the live campaign budget, so an older local ABO stamp cannot block a CBO campaign. A successful edit repairs local ad budget fields. A live ABO campaign still returns 409 with the ad-set budget endpoint. On Google: `LOWEST_COST_WITHOUT_CAP` = Maximize Conversions, `COST_CAP` + `bidAmount` = Target CPA, `LOWEST_COST_WITH_MIN_ROAS` + `roasAverageFloor` = Target ROAS, `LOWEST_COST_WITH_BID_CAP` + `bidAmount` = Maximize Clicks with a CPC ceiling; `portfolioBidStrategyId` attaches a portfolio strategy instead (exclusive with `bidStrategy`). Setting the standard triplet on a campaign that is currently on a PORTFOLIO strategy is rejected: detach it in Google Ads first, since it is shared across campaigns. Google budget updates read the current budget before mutation. Shared budgets return 409 unless allowSharedBudgetUpdate=true is explicitly supplied, because the change affects every campaign using that budget. Unknown sharing state also returns 409. OpenAI Ads campaigns carry exactly one spend cap: `budget.type` daily or lifetime replaces whichever cap the campaign had, with a minimum of 1 in the ad account's currency (422 below it). Lifetime can switch to daily, but OpenAI never switches a daily cap back to lifetime (422). `accountId` forwards the update straight to Meta for a campaign with zero ads, which would otherwise 404; the response then carries `updated: 0`.