---
title: "Stored read: List creatives"
method: GET
path: "/observe/creatives"
tags: ["Creatives"]
---

# Stored read: List creatives

`GET /observe/creatives`

## Request

- Base URL: `https://api.adcrunch.dev`
- URL: `https://api.adcrunch.dev/observe/creatives`
- Auth: HTTP bearer

**Available on:** [![Meta](/providers/meta.svg)](https://docs.adcrunch.dev/connect/providers)

Lists the creatives of every ad account your organization connects, newest first.

## Meta only, today

A standalone Creative is Meta’s model. **TikTok has none** — its creative material (the video or image, the ad text, the call to action) is embedded in the Ad itself, so a TikTok advertiser lists nothing here and AdCrunch does not invent a creative for it. Google Ads has none either: it keeps its creative material on the `ad_group_ad` link resource.

An empty answer for those providers is normal, and it is not a failure.

## No parent

A creative is **account-level**: it belongs to an advertiser and not to any one campaign or ad group, and one creative can be reused across many ads. So there is no campaign or ad group to filter by, and a row carries no `campaignId` and no `adGroupId`.

## Freshness

A creative is re-read only when the ad that carries it changes. A body-copy tweak or a thumbnail swap made in the provider’s own interface lags until the next ad-level change reaches AdCrunch.

## Not an Asset

A Creative is the provider’s — the assembled payload it returns once an ad exists. An **Asset** is yours: a source media file your organization owns, held before any ad references it. They are deliberately unlinked; read the Assets API for those.

## 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`.
- `advertiserId` string: Read one ad account from what AdCrunch holds, prefixed `acc_`. One your organization does not own answers an empty list rather than a failure. To ask the provider instead, put the advertiser in the path.
- `provider` union: Read one provider. Omit it to read every provider your organization connects.
  - 'meta'
  - 'tiktok'
  - 'snapchat'
  - 'gads'
  - 'dv360'
  - 'x'
  - 'openai'
- `status` 'ACTIVE' | 'PAUSED' | 'DELETED' | 'ARCHIVED': Read one status, normalized across the providers. TikTok `ENABLE` and `DISABLE` are read here as `ACTIVE` and `PAUSED`.

## Response `200`

The matching creatives, and how many there are in all. Only Meta advertisers answer rows today.

- 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.
    - `type` string, required: The type the provider uses, kept as the provider writes it: `creative`. Only Meta has a creative of its own. 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`.

---

[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)
