Ad Campaigns

Lists your campaigns with spend, impressions and clicks summed across their ads, plus each campaign's status and budget.

Returns campaigns as virtual aggregations over ad documents grouped by platform campaign ID. Metrics (spend, impressions, clicks, etc.) are summed across all ads in each campaign. Campaign status is derived from child ad statuses (active > pending_review > paused > error > completed > cancelled > rejected). Google campaign budgets include amountMicros, explicitlyShared, resourceName and deliveryMethod after the next successful sync. This endpoint does not fetch Google live.

Status freshness. status, configuredStatus, platformStatus, platformAdSetStatus and platformCampaignStatus are the values Zernio last stored. Background sync refreshes them, typically within 15 to 60 minutes (Google up to about 3 hours), and ended or long-paused objects may be refreshed less often. Zernio's own status writes re-read the switches they change. A change made in the platform's own ads manager therefore shows up here only after the next sync. Controllers that act on a switch should pass live=true, which reads the switches from the platform now, stores them, and returns statusReadAt (null when the read failed and the stored values were returned). With live=true (which needs limit of 20 or less) each returned campaign's own switch (platformCampaignStatus) is read live. Live reads cover TikTok, Meta, Google, OpenAI and Reddit. The rolled-up status is not re-derived by a live read.

Budgets here are SYNCED, never read live, including with live=true. To read the current budgets (and status) of every campaign and ad set of a Meta ad account live in one call, for example as a pre-write spend gate, use GET /v1/ads/accounts/live.

get/v1/ads/campaigns

Request

  • Base URL: https://zernio.com/api
  • URL: https://zernio.com/api/v1/ads/campaigns
  • Auth: HTTP bearer

Query parameters

includeEmptyboolean

Meta only. Campaign reads aggregate over ad documents, so a campaign with ZERO ads is normally invisible here, the state the two-step create (campaign, then ads via existingCampaignId) leaves behind whenever Meta rejects the ad step. Set true to list those too, with adCount: 0 and zeroed metrics. Requires accountId and adAccountId, since an empty campaign has no ad row to resolve a token or ad account from.

pageinteger

Page number (1-based)

limitinteger
source'zernio' | 'all'

all (default) returns both Zernio-created ads and those discovered from the platform's ad manager. Matches the web UI's default view. Pass zernio to restrict to isExternal=false only. Status is NOT filtered by default; use the status param for that.

platform'facebook' | 'instagram' | 'tiktok' | 'linkedin' | 'pinterest' | 'google' | 'twitter' | 'openai' | 'reddit'
status'active' | 'paused' | 'pending_review' | 'rejected' | 'completed' | 'cancelled' | 'error'

Filter by derived campaign status (post-aggregation)

adAccountIdstring

Platform ad account ID (e.g. act_123 for Meta)

campaignIdstring

Platform campaign ID (the platformCampaignId on each returned campaign). Returns only that campaign, or an empty list when it is not visible to the caller. Mirrors the same filter on /v1/ads and /v1/ads/tree.

pageIdstring

Meta only: Facebook Page ID. Campaigns have no Page of their own, so this keeps campaigns having at least one ad backed by this Page, with adCount and metrics computed over those ads only. Mirrors the same filter on /v1/ads and /v1/ads/tree.

accountIdstring

Account ID

profileIdstring

Profile ID

fromDatestring date

Start of metrics date range (YYYY-MM-DD, inclusive). Defaults to 90 days ago when both date params are omitted.

toDatestring date

End of metrics date range (YYYY-MM-DD, inclusive). Defaults to today. Max 730-day range.

hasDeliveryboolean

Return only campaigns that delivered between fromDate and toDate: spend above zero, or impressions served at zero spend. Unlike status, which reads a campaign's CURRENT state, this filters on what happened inside the window. Filters the campaign set itself, so pagination.total counts only matching campaigns. Mirrors the same filter on /v1/ads/tree.

minSpendnumber

Return only campaigns whose spend between fromDate and toDate reaches this amount, in each campaign's OWN currency (the currency field on the campaign). Implies hasDelivery; minSpend=0 applies no filter. Mirrors the same filter on /v1/ads/tree.

liveboolean

Read the on/off switches live from the platform instead of returning the synced values. The fresh values are stored (so later reads return them too) and the response carries statusReadAt, the time of the read. At most 20 platform objects are read per request. Where a read fails (credentials, platform error, no reader on that platform), the stored values come back with statusReadAt: null. See "Status freshness" in the operation description. On X the budget is read live in the same read: on GET /v1/ads/{adId} budget, adSetBudget, campaignBudget and budgetLevel are the line item and campaign budgets X holds now (stored like the switches); on the ad set and campaign listings budget is the one that line item or campaign holds now (returned, not stored); a row whose budget the other level holds keeps its synced budget.

Response

Paginated campaigns

Example response

{
  "campaigns": [
    {
      "metrics": {
        "actions": {
          "link_click": 160,
          "post_engagement": 300,
          "offsite_conversion.fb_pixel_purchase": 42
        },
        "actionValues": {
          "offsite_conversion.fb_pixel_purchase": 2456.78,
          "offsite_conversion.fb_pixel_add_to_cart": 980.5
        },
        "costPerAction": {
          "link_click": 0.1052,
          "offsite_conversion.fb_pixel_purchase": 4.0114
        }
      }
    }
  ]
}

Changes

    • info

      added the optional property // to the response with the status

    • warning

      added the new reddit enum value to the // response property for the response status

    • info

      added the new enum value reddit to the query request parameter platform