---
title: "Create a standalone ad group"
method: POST
path: "/v1/ads/ad-sets"
tags: ["Ad Campaigns"]
---

# Create a standalone ad group

`POST /v1/ads/ad-sets`

Google Ads compliance row C.190: creates an ad group WITHOUT an ad,
under an existing campaign. Ads join it later via `adSetId`
on POST /v1/ads/create. Google only; every other platform returns 501.

Created `PAUSED` unless `status: ACTIVE`. The new ad group has no ad
yet, so it will not appear in GET /v1/ads/tree (built purely from `ads`
rows) until one is added; use GET /v1/ads/ad-sets to see it in the
meantime.

**Idempotency:** send an `Idempotency-Key` header to make retries safe.

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `accountId` string, required — Zernio SocialAccount id owning the Google Ads connection.
  - `platform` 'facebook' | 'instagram' | 'tiktok' | 'linkedin' | 'pinterest' | 'google' | 'twitter' | 'openai', required — Only "google" is implemented today; every other value returns 501.
  - `campaignId` string, required — Google platform campaign ID (numeric) the ad group is created under.
  - `name` string, required
  - `status` 'ACTIVE' | 'PAUSED'
  - `adAccountId` string — Platform ad account ID (Google customer ID, digits only). Only required when the connection has more than one.
  - `customerId` string — Alias of adAccountId, kept for existing callers

## Response `201`

Ad group created

- object
  - `adSetId` string — Platform id of the new ad group
  - `campaignId` string

## Other responses

- `400` — Invalid request
- `401` — Unauthorized
- `403` — Returned with code `ads_allowance_exceeded` when the team has no payment method on file and has reached the 500 free live ads: add a card to resume.
- `404` — The account or requested resource was not found or is not accessible. An account ID may have been disconnected and removed. Read GET /v1/accounts for current account IDs.
- `409` — The account exists but is inactive or needs reconnection. Reconnect it, then read GET /v1/accounts for its current account ID before retrying. Code: ads_connection_required.
- `501` — Only supported on Google Ads

## Changes

- **2026-09-23** `dd3865482f9f` — 2 info
  - added the new optional request property `adAccountId`
  - request property `customerId` deprecated
- **2026-09-16** `3e6ddf2a99ea` — 3 info
  - added the optional property `details/budgetScope` to the response with the `400` status
  - added the optional property `details/budgetScope` to the response with the `404` status
  - added the optional property `details/budgetScope` to the response with the `409` status
- **2026-09-15** `0dba7d004d75` — 6 info
  - added the optional property `details/quotaExhausted` to the response with the `400` status
  - added the optional property `details/quotaExhausted` to the response with the `404` status
  - added the optional property `details/quotaExhausted` to the response with the `409` status
  - added the optional property `details/quotaScope` to the response with the `400` status
  - …2 more
- **2026-09-10** `e70ed06e7150` — 2 info
  - added the media type `application/json` for the response with the status `404`
  - added the non-success response with the status `409`
- **2026-09-08** `d7a8fa118ef0` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/zernio/apis/zernio-api/changes/v1/ads/ad-sets/post.md)

---

[API](https://skmtc.dev/zernio/apis/zernio-api.md) · [All operations](https://skmtc.dev/zernio/apis/zernio-api/llms.txt) · [OpenAPI document](https://skmtc.dev/zernio/apis/zernio-api/revisions/dd3865482f9f?raw)
