---
title: "Live read: List an advertiser’s asset groups"
method: GET
path: "/observe/{advertiserId}/asset-groups"
tags: ["Asset groups"]
---

# Live read: List an advertiser’s asset groups

`GET /observe/{advertiserId}/asset-groups`

## Request

- Base URL: `https://api.adcrunch.dev`
- URL: `https://api.adcrunch.dev/observe/{advertiserId}/asset-groups`
- Auth: HTTP bearer

**Available on:** [![Google Ads](/providers/gads.svg)](https://docs.adcrunch.dev/connect/providers)

Asks the provider for the asset groups of one ad account, now. This is a **live read**: the path names the advertiser, so the answer is what the provider holds, not what AdCrunch holds.

An advertiser that your organization does not own answers `404`, with `error` of `not_found`. An advertiser that does not exist answers the same. The answer does not tell the two apart.

Send `campaignId` to read one Performance Max campaign’s asset groups.

Google Ads is the one provider that has an asset group. An advertiser on Meta or TikTok answers an empty list, because its provider has none. An advertiser on a provider AdCrunch cannot read live answers `501`.

A live row carries no `createdAt`, `updatedAt` or `deletedAt`, because AdCrunch stores nothing for it. Each request counts against the rate limits of the provider.

For the stored rows of the same advertiser, read `/observe/asset-groups?advertiserId=…`. That path takes every `status`, and the Status section below lists the statuses this one takes.

`limit` and `cursor` page the answer. Send `nextCursor` back as `cursor` to get the next page. A live cursor is good only for a live read. At TikTok, every page keeps the page size of the first.

## Status

`status` selects the status an entity is set to, not whether it delivers, and every row of the answer carries it. A provider takes a status only where one request to it selects exactly the entities in that status. Any other status answers `501`.

The stored read, `/observe/asset-groups?advertiserId=…&status=…`, takes every status. A status that a provider never uses answers an empty list.

| Provider | Takes `status` |
| --- | --- |
| Google Ads | `ACTIVE`, `PAUSED`, `DELETED`, `ARCHIVED` |

## Path parameters

- `advertiserId` string, required: The ad account to read, prefixed `acc_`. It must belong to your organization. One that does not answers `404`, with `error` of `not_found`.

## Query parameters

- `ids` string: Ids to filter on, separated by commas. An id is the bare id its provider gives.
- `cursor` string: The `nextCursor` of the previous page. Omit it to get the first page. Send it with no change, and with the same filters as the request that answered it: a cursor from a different query gets a 400 `invalid_cursor`. Do not build or change a cursor.
- `limit` integer: The greatest number of rows on the page, from 1 to 500. The default is 100. A greater value gets a 400, with `error` of `invalid_request`.
- `status` 'ACTIVE' | 'PAUSED' | 'DELETED' | 'ARCHIVED': Read one status, normalized across the providers: the status the entity is set to, not whether it delivers. Every row of the answer carries this status. A provider that cannot select this status exactly answers `501`; the description of this operation lists what each provider selects.
- `campaignId` string: Read only what this campaign holds. Send the bare id its provider gives, which is the `campaignId` every row answers.

## Response `200`

The matching asset groups of this advertiser. An advertiser that is not on Google Ads answers an empty list.

- object
  - `data` object[], required: The matching rows. From the store, the row AdCrunch stored last comes first; from the provider, the provider’s own order. An empty array means nothing matched, which is a normal answer and not a failure.
    - `advertiserId` string, required: The advertiser that owns it, prefixed `acc_`.
    - `createdAt` number, nullable, required: When AdCrunch first stored this row. **Null when the row was read live**: AdCrunch holds no copy of it. `createdAt`, `updatedAt` and `deletedAt` are AdCrunch’s own times, so all three are null together on a live row.
    - `createdTime` number, nullable, required: When the provider created the entity. This is the provider’s own time, so a live row carries it. Null where the provider reports none.
    - `currency` string, nullable, required: The account currency, ISO 4217. Every row of one advertiser carries the same one. Null when AdCrunch does not know it yet.
    - `deletedAt` number, nullable, required: When AdCrunch marked the row deleted. A listing never carries a deleted row, so this is null.
    - `id` string, required: The id the provider gives, with no prefix. It is unique for one provider and one type, and it may legitimately recur across two types or two providers.
    - `name` string, required: The name at the provider.
    - `path` string, required: The ancestors and this entity, ids joined by `/`, oldest first. This is what makes a subtree one string comparison.
    - `provider` string, required: The ad platform: `meta`, `tiktok` or `gads`. Those three are the providers whose entities AdCrunch reads, and https://docs.adcrunch.dev/connect/providers says how deep each one goes.
    - `status` 'ACTIVE' | 'PAUSED' | 'DELETED' | 'ARCHIVED', required: The status, normalized across the providers. TikTok `ENABLE` and `DISABLE` read here as `ACTIVE` and `PAUSED`.
    - `updatedAt` number, nullable, required: When AdCrunch last rewrote this row. Null if it never changed.
    - `updatedTime` number, nullable, required: When the provider last edited the entity. Null where the provider reports none.
    - `budgetLevel` 'campaign' | 'ad_group', nullable, required: Where the budget of this entity’s campaign lives. `campaign` when the campaign carries it — Meta Advantage campaign budget, TikTok Campaign Budget Optimization, and every Google Ads campaign. `ad_group` when each ad group carries its own. Null on a TikTok campaign whose payload does not say.
    - `campaignId` string, nullable, required: The campaign it belongs to, as the bare id its provider gives. Null only when the stored path of the row names no campaign.
    - `type` string, required: The type the provider uses, kept as the provider writes it: `asset_group`. Only Google Ads has an asset group. The resource names the concept, and the row keeps the provider’s own word, because a Meta `adset` and a Google Ads `ad_group` are not the same object.
  - `nextCursor` string: Send this value as `cursor` to get the next page. It is absent on the last page.

## Other responses

- `400`: The request does not match the schema of this operation: a field is missing or has the wrong type, or the body is not valid JSON. `error` is `invalid_request`, and `issues` names each field. Nothing was changed. Or AdCrunch cannot use the `cursor`: it cannot read it, or the cursor belongs to a different query. Then `error` is `invalid_cursor`. Send the `nextCursor` of the previous page with no change, or omit `cursor` to get the first page.
- `401`: No API key, or one that does not resolve. See the security scheme. `error` is `unauthorized`.
- `402`: The organization has no active subscription. An owner subscribes at `paywallUrl`. `error` is `organization_unentitled`.
- `403`: The caller does not hold `observe:read`. `error` is `forbidden`.
- `404`: Your organization does not own the advertiser in the path, or it does not exist. The answer does not tell the two apart. `error` is `not_found`. AdCrunch asks the provider nothing.
- `409`: This advertiser has no usable connection to its provider. A person must reconnect it. The stored read of the same resource, with `advertiserId`, still answers what AdCrunch holds.
- `501`: AdCrunch cannot read this resource live from this advertiser’s provider. It is permanent. Read the stored copy instead, at the same resource without the advertiser in the path and with `advertiserId`.
- `502`: The provider refused the request, or could not answer it. Often transient, so a retry is worth making.

---

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