> ## Documentation Index
> Fetch the complete documentation index at: https://docs.semicola.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Dimensions and labels

> Organize advertisers and campaigns with buyer-owned dimensions and labels, filter by them, and group delivery by a label.

A **dimension** is a buyer account's named organizing axis, such as Market, Quarter or Brand. A
**label** is one value from a dimension attached to an advertiser or campaign. Dimensions keep labels
consistent: the same value means the same thing everywhere in the account.

Every buyer account also has the built-in `tags` dimension. It's open, so you can apply a new tag
without creating it first. There's no separate tag object or tag tool.

Dimensions organize work. They don't grant access, select inventory, change targeting, or travel to
sellers. They have no screen of their own: they show up as labels on objects, search filters and
delivery report axes, and you set them up in chat or over MCP when you first organize work by an axis.

## Dimension fields

| Field        | Notes                                                                                                                                                       |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`         | Server-issued. Use it to read or update the dimension. The built-in `tags` dimension is `dim_tags`.                                                         |
| `key`        | Your slug (lowercase letters, digits, underscore; starts with a letter), unique in the account and immutable. It's the key in `labels` and `filter.labels`. |
| `name`       | Display name, up to 100 characters. Rename it without changing `key`.                                                                                       |
| `valuesMode` | `open` accepts a new value when you apply a label; `governed` accepts only its listed, active values.                                                       |
| `values`     | Each has a stable `value`, a display `name` and a `retired` flag. Retired values stay readable but can't be newly applied.                                  |
| `appliesTo`  | `advertiser`, `campaign` or both (the default).                                                                                                             |
| `usage`      | Read-only counts of labeled advertisers and campaigns.                                                                                                      |
| `retired`    | A retired dimension can't receive new labels but stays readable.                                                                                            |
| `builtIn`    | `true` for `tags`.                                                                                                                                          |

## Create and manage dimensions

Use `save_dimension`. Create with a unique `key`, a `name`, `valuesMode`, `appliesTo` and an
`idempotencyKey`:

```json theme={null}
{
  "key": "market",
  "name": "Market",
  "valuesMode": "governed",
  "appliesTo": ["advertiser", "campaign"],
  "values": [{ "value": "us", "name": "United States" }, { "value": "ca", "name": "Canada" }],
  "idempotencyKey": "dimension-market-create-01"
}
```

After that, update by `id` (the key can't change). The same tool adds or renames values, retires a
value (`retired: true`) or the whole dimension, and merges one value into another with `mergeInto`.

`mergeInto` must name another existing, active value. Merging moves existing labels to the target but
doesn't retire the source; retire it explicitly when it should no longer be offered.

You can't narrow `appliesTo` while the dimension still labels objects of the kind you're removing
("Clear or move them before narrowing appliesTo.").

| Limit                                     | Value |
| ----------------------------------------- | ----: |
| Dimensions per account (including `tags`) |    20 |
| Values per dimension                      |   200 |
| Labels per advertiser or campaign         |    50 |

List dimensions with `search` (`kind: "dimension"`, optional `filter.appliesTo`) and read one with
`get` (`kind: "dimension"`, `id`).

## Apply labels

Pass `labels` to `save_advertiser` or `save_campaign`:

```json theme={null}
{ "labels": { "market": ["us", "ca"], "tags": ["launch"] } }
```

* Each dimension you send replaces that dimension's labels on the object; `[]` clears it.
* Omitting `labels` leaves every label unchanged.
* Values are normalized: trimmed, lowercased, and spaces become dashes (`"Q4 Launch"` → `q4-launch`).
* An open dimension learns a new value the first time you apply it. A governed dimension refuses
  values it doesn't list, naming the allowed ones.
* Unknown, retired or inapplicable dimensions and retired values are refused with the dimensions you
  can use.

`get` and `search` return labels in the same `{ "dimensionKey": ["value"] }` shape. REST campaign and
advertiser writes don't take `labels`; use the MCP tools.

## Find by label

`search` with `kind: "advertiser"` or `kind: "campaign"` takes `filter.labels`: AND across dimension
keys, OR within a value array. The literal `"unlabeled"` finds objects with no value for a dimension.

```json theme={null}
{ "kind": "campaign", "filter": { "labels": { "market": ["us", "ca"], "quarter": "unlabeled" } } }
```

Over REST, `GET /api/v2/buyer/campaigns?labels=` takes the same predicate as JSON, for example
`labels={"market":["us"],"quarter":"unlabeled"}` (URL-encoded).

## Group delivery by a label

In `get_delivery` (`report: "campaign_delivery"`), add a label axis as `"labels.<key>"`:

```json theme={null}
{
  "report": "campaign_delivery",
  "metrics": ["impressions", "spend"],
  "dimensions": ["labels.market"],
  "range": { "startDate": "2026-08-01", "endDate": "2026-08-31" }
}
```

Each row takes the campaign's label for that dimension, or its advertiser's when the campaign has none.
Several values on one object read as one bucket joined with ", " (for example `ca, us`); rows with no
value land in `"Unlabeled"`. Labels are read when you run the report, so relabeling reorganizes past
rows too. An unknown, retired or inapplicable key is refused with the available dimensions.

## Who can use them

People in the buyer account can. [Buyer agents](/v2/setup/buyer-agent-credentials) can't call
`save_dimension` or read `kind: "dimension"`, because dimensions are account-wide rather than
per-advertiser.

## Related

* [Advertiser](/buy/advertiser)
* [Campaign](/buy/campaign)
* [Reporting](/buy/reporting)
