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

# Advertiser

> The brand-and-operator identity that owns campaigns, creatives, audiences, and linked partner accounts

## Overview

An **Advertiser** in Interchange is the commercial media identity on whose
behalf campaigns run: a **brand care of an operator**. The brand answers whose
products are being advertised; the operator answers which organization drives
the buying. This is an Interchange product projection, not an assertion that
AdCP collapses the two entities: AdCP keeps Brand, Operator, Account, and Agent
separate.

For buyer-declared AdCP accounts, `(brand, operator, sandbox)` is the natural
key of the account relationship. An upstream-managed `account_id` instead
names an entry in the seller's own namespace, whose declared `account_scope`
may be operator-, brand-, operator-and-brand-, or agent-wide. See
[AdCP Accounts and agents](https://docs.adcontextprotocol.org/docs/building/by-layer/L2/accounts-and-agents).

Direct buying is the identity case where the brand operates its own seat. For
example, Coca-Cola buying directly from an account registered to
`coca-cola.com` is "Coca-Cola care of Coca-Cola"; Coca-Cola through WPP is
"Coca-Cola care of WPP." **Self-serve is an interface, not an operator
identity**: using Interchange directly does not replace Coca-Cola with
"self-serve" as the operator. Likewise, an agent is the software acting for the
operator, not the operator itself. When a buyer account has no registered
domain, current v2 outbound AdCP calls use `interchange.io` as a platform
operator fallback until the account records its real domain; that fallback is
an implementation compromise, not the meaning of self-serve.

In the current Scope3 v2 buyer API, an advertiser is also the top-level resource
container for media. Every campaign, creative, audience, frequency cap, and
linked partner account belongs to one. The authenticated buyer account
establishes the operator context, so the v2 advertiser payload does not repeat
an `operator` field.

<Note>
  **Renamed from Brand Agent**: In v1 this concept was called a "Brand Agent". In v2 it has been renamed to **Advertiser** to align with industry terminology used by Google Ads, The Trade Desk, DV360, and Amazon DSP.
</Note>

## Why advertisers matter

* **Resource ownership** — campaigns, creatives, audiences, and frequency caps all roll up to a single advertiser
* **Commercial identity** — every advertiser combines a brand reference with the operator acting for it
* **Brand identity** — every advertiser links to a brand resolved from the AdCP brand registry (or a `/.well-known/brand.json` document on the brand's domain)
* **Default policies** — `optimizationApplyMode`, UTM parameters, and frequency caps set on the advertiser flow down to its campaigns
* **Sandbox isolation** — sandbox advertisers route every ADCP call to test accounts, so you can rehearse end-to-end flows without real spend
* **Linked accounts** — connect the advertiser to existing accounts on upstream platforms (e.g. Snap, programmatic DSPs) for cross-platform reporting and execution

## Key fields

The advertiser resource has two response shapes:

* **Summary** — returned by `GET /api/v2/buyer/advertisers` (list). A small, fixed set of row-level fields.
* **Full** — returned by `GET /api/v2/buyer/advertisers/:id` (get). The complete resource with nested brand, linked accounts, UTM config, and frequency caps.

### Summary shape (list rows)

| Field                     | Type                   | Notes                                                                                         |
| ------------------------- | ---------------------- | --------------------------------------------------------------------------------------------- |
| `id`                      | string                 | Stable advertiser identifier                                                                  |
| `name`                    | string                 | Human-readable name (max 255 chars)                                                           |
| `status`                  | `ACTIVE` \| `ARCHIVED` | Soft-delete state                                                                             |
| `sandbox`                 | boolean                | When true, all ADCP calls route to sandbox accounts. **Immutable after creation.**            |
| `brand`                   | string                 | Brand domain (e.g. `northwind.example`) or brand website URL                                  |
| `linkedAccountCount`      | integer                | Number of partner accounts linked to this advertiser. Use `get_advertiser` for the full list. |
| `createdAt` / `updatedAt` | datetime               | ISO 8601 timestamps                                                                           |

### Full shape (single advertiser)

The single-advertiser endpoint returns every field above plus:

| Field                   | Type               | Notes                                                                                                                                 |
| ----------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| `description`           | string             | Optional description (max 1000 chars)                                                                                                 |
| `linkedBrand`           | object             | Resolved brand identity — name, domain, logos, colors, fonts, manifest                                                                |
| `optimizationApplyMode` | `AUTO` \| `MANUAL` | Default for the advertiser's campaigns. `MANUAL` requires approval before applying optimizations.                                     |
| `primaryCurrency`       | string             | ISO 4217 code. The single currency for every campaign under this advertiser. Changeable until the first campaign exists, then locked. |
| `currencyLocked`        | boolean            | `true` once the advertiser has at least one campaign; while `false`, `primaryCurrency` can still be changed.                          |
| `linkedAccounts`        | array              | Partner accounts linked to this advertiser (e.g. Snap account, agency seats)                                                          |
| `utmConfig`             | array              | Default UTM parameters appended to landing page URLs                                                                                  |
| `frequencyCaps`         | array              | Buyer-side caps enforced by Scope3 across all publishers                                                                              |
| `brandWarning`          | string             | Warning about brand resolution (e.g. manifest not found)                                                                              |

## Brand resolution

Advertisers do not store brand identity directly. Instead, they reference a **brand domain or website URL**, and Scope3 resolves the brand identity from one of three sources:

1. The advertiser's `/.well-known/brand.json` (per the AdCP spec)
2. The AdCP brand registry
3. Brandfetch enrichment

Pass `brand: "northwind.example"` and Scope3 fetches the resolved brand identity, surfacing logos, colors, fonts, tone, and product catalog under `linkedBrand` when available. If the advertiser is created or updated from enrichment rather than an official registry entry, the response includes `brandWarning`; do not retry create for that case. After reviewing the enriched details, set `saveBrand: true` on an update if you want to persist the brand in the registry. If no enrichment data is available, retry create with `saveBrand: true` only after confirming the advertiser name and brand domain.

<Tip>
  See the [Brand object guide](/v2/object-guides/brand-story) for the brand resolution model in detail.
</Tip>

## Uniqueness

The conceptual Interchange advertiser identity is `BrandRef × Operator`. The
current v2 resource partitions that identity operationally by
**`primaryCurrency`** and sandbox mode. The same brand domain can therefore
back more than one advertiser resource under the same operator when each uses a
different currency — for example one `northwind.example` resource in `USD` and
another in `EUR`. Those rows are separate campaign and billing containers, not
different operator identities. AdCP account relationships have their own
identity rule: buyer-declared sandbox accounts add `sandbox: true` to the
`(brand, operator)` natural key, while account-id namespaces use distinct
seller-assigned test-account IDs.

Within a buyer account and sandbox mode, creating a second resource with both
the same brand domain and currency returns a conflict, as does changing an
existing resource's brand or currency onto a pair already taken by a sibling.
Sandbox and non-sandbox advertisers are tracked separately, so each
`(brand domain, currency)` pair has its own slot in each mode.

## Sub-resources

The advertiser is the hub for many sub-resource collections. Each lives under `/api/v2/buyer/advertisers/:advertiserId/...` and inherits the advertiser's auth, brand, and sandbox context.

| Collection               | Endpoint root                                                      | Purpose                                                                                                              |
| ------------------------ | ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------- |
| **Campaigns**            | `/api/v2/buyer/campaigns?advertiserId=…`                           | Marketing initiatives — flight dates, budget, products, creatives ([guide](/v2/object-guides/campaign))              |
| **Linked accounts**      | `/advertisers/:id/accounts`                                        | Existing accounts on upstream platforms (Snap, programmatic DSPs, agency seats) — see [below](#linked-accounts)      |
| **Catalogs**             | `/advertisers/:id/catalogs`                                        | Product / offering / inventory feeds pushed via ADCP `sync_catalogs` and reused by discovery and creative generation |
| **Audiences**            | `/advertisers/:id/audiences`                                       | First-party audiences synced via ADCP for targeting and incrementality test cohorts                                  |
| **Property lists**       | `/advertisers/:id/property-lists`                                  | Domain/email allow-and-block lists (up to 100k entries) ([guide](/v2/guides/property-lists))                         |
| **Event sources**        | `/advertisers/:id/event-sources`                                   | Conversion event source registration ([measurement guide](/v2/guides/measurement-incrementality))                    |
| **Measurement config**   | `/advertisers/:id/measurement-config`                              | MMM, incrementality, and brand-lift configuration ([measurement guide](/v2/guides/measurement-incrementality))       |
| **Test cohorts / plans** | `/advertisers/:id/test-cohorts`, `/advertisers/:id/test-plans/:id` | Incrementality test scaffolding ([measurement guide](/v2/guides/measurement-incrementality))                         |
| **Hypotheses**           | `/advertisers/:id/hypotheses`                                      | A/B test hypotheses                                                                                                  |
| **Belief state**         | `/advertisers/:id/belief-state`                                    | Bayesian belief state from the measurement engine ([measurement guide](/v2/guides/measurement-incrementality))       |
| **Tracking config**      | `/advertisers/:id/tracking-config`                                 | Tracking macro and pixel template configuration                                                                      |
| **UTM config**           | inline on the advertiser                                           | Default UTM parameters appended to landing-page URLs (set via `utmConfig` on create/update)                          |
| **Frequency caps**       | inline on the advertiser                                           | Buyer-side caps that flow down to all of the advertiser's campaigns ([guide](/v2/guides/frequency-caps))             |
| **Allocations**          | `/advertisers/:id/allocations`                                     | Budget allocation entries used by the optimizer                                                                      |
| **Event summary**        | `/advertisers/:id/events/summary`                                  | Aggregated conversion event metrics                                                                                  |
| **Syndication**          | `/advertisers/:id/syndicate`                                       | Syndicate first-party audiences to partner platforms                                                                 |
| **Log event**            | `/advertisers/:id/log-event`                                       | Custom event ingestion ([guide](/v2/guides/log-events))                                                              |

See the [Buyer API Reference](/v2/buyer-api-reference) for the full request and response shape of each.

## Lifecycle

<Steps>
  <Step title="Create the advertiser">
    Provide a name and a brand domain. Optionally link partner accounts, set sandbox mode, configure UTM params, and add buyer-side frequency caps. Sandbox flag is locked after creation.
  </Step>

  <Step title="Configure defaults">
    Update `optimizationApplyMode`, UTM params, and frequency caps as your operational policy evolves. Campaigns under the advertiser inherit these defaults unless overridden.
  </Step>

  <Step title="Run campaigns">
    Create campaigns under the advertiser. Discovery, audiences, and creatives are scoped to this advertiser.
  </Step>

  <Step title="Archive when done">
    `DELETE /api/v2/buyer/advertisers/:id` archives the advertiser (soft delete). Use `POST /api/v2/buyer/advertisers/:id/restore` to bring it back.
  </Step>
</Steps>

## Common operations

Before creating an advertiser from a domain, buyer MCP clients can call the
side-effect-free `resolve_buyer_brand` operation to show the brand-confirmation card.
The user then confirms by creating the advertiser normally.

### Create an advertiser

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.interchange.io/api/v2/buyer/advertisers \
    -H "Authorization: Bearer $SCOPE3_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Acme Corp",
      "description": "Acme global advertiser account",
      "brand": "acme.com",
      "optimizationApplyMode": "MANUAL",
      "sandbox": false
    }'
  ```

  ```json Request body theme={null}
  {
    "name": "Acme Corp",
    "brand": "acme.com",
    "optimizationApplyMode": "MANUAL",
    "linkedAccounts": [
      { "storefrontId": 1, "sourceId": "src_main", "accountId": "acc_67890", "credentialId": "cred_snap_coke", "billingType": "brand" }
    ],
    "frequencyCaps": [
      { "max_impressions": 3, "window": { "interval": 7, "unit": "days" } }
    ]
  }
  ```
</CodeGroup>

### Get / list advertisers

```bash theme={null}
# List active advertisers (summary rows)
curl "https://api.interchange.io/api/v2/buyer/advertisers?status=ACTIVE&limit=50" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"

# Get a single advertiser (full resource — linkedBrand, linkedAccounts, utmConfig, frequencyCaps)
curl https://api.interchange.io/api/v2/buyer/advertisers/12345 \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
```

List rows return the summary shape — `id`, `name`, `status`, `sandbox`, `brand`, `linkedAccountCount`, `createdAt`, `updatedAt`. Call `GET /api/v2/buyer/advertisers/:id` for the full resource (resolved brand object, full linked-account list, UTM config, frequency caps).

```json List response theme={null}
{
  "items": [
    {
      "id": "12345",
      "name": "Acme Corp",
      "status": "ACTIVE",
      "sandbox": false,
      "brand": "acme.com",
      "linkedAccountCount": 3,
      "createdAt": "2025-01-15T10:30:00Z",
      "updatedAt": "2025-01-20T14:45:00Z"
    }
  ],
  "total": 1,
  "hasMore": false,
  "nextOffset": null
}
```

List supports filtering: `status`, `name` (partial match), `sandbox` (true/false), plus `limit` and `offset` pagination.

### Update an advertiser

```bash theme={null}
curl -X PUT https://api.interchange.io/api/v2/buyer/advertisers/12345 \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Corporation",
    "optimizationApplyMode": "AUTO",
    "frequencyCaps": [
      { "max_impressions": 5, "window": { "interval": 7, "unit": "days" } }
    ]
  }'
```

<Warning>
  `sandbox` is immutable after creation. To convert sandbox work to production, create a new production advertiser. When `frequencyCaps` is provided on update, it **replaces** all existing non-archived caps. Pass an empty array to clear; omit the field to leave caps untouched.
</Warning>

### Archive / restore

```bash theme={null}
curl -X DELETE https://api.interchange.io/api/v2/buyer/advertisers/12345 \
  -H "Authorization: Bearer $SCOPE3_API_KEY"

curl -X POST https://api.interchange.io/api/v2/buyer/advertisers/12345/restore \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
```

## Linked accounts

The `linkedAccounts` field connects the advertiser to existing accounts on upstream platforms — Snap, programmatic DSPs, agency seats. Each linked account is the pre-existing seat ID a partner already has for this brand or buyer; the link makes that ID addressable to Interchange for cross-platform reporting and pass-through execution.

<Note>
  Use `linkedAccounts` whenever the buyer **already has** a relationship with the upstream platform — an existing Snap seat, a DV360/Trade Desk account, an agency-managed seat. Linked accounts let Interchange reuse the seat ID for unified reporting and pass-through execution without re-provisioning credentials per call. This account choice is independent of campaign mode, BYOA, protocol connectivity, and settlement; do not infer those from `routingType`.
</Note>

### Fields

Each link maps these fields:

| Field          | Type              | Notes                                                                                                                                                                |
| -------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `storefrontId` | integer           | Storefront the source lives on. Get from `GET /api/v2/buyer/storefronts`.                                                                                            |
| `sourceId`     | string            | Inventory source within `storefrontId` whose account is being linked.                                                                                                |
| `accountId`    | string            | The pre-existing account ID at the source (e.g. `acc_67890`). Must come from `GET /accounts/available` — Scope3 does not mint it.                                    |
| `credentialId` | string \| null    | The connected provider credential that owns this linked account. Include it when creating or updating links if multiple credentials can expose the same `accountId`. |
| `billingType`  | string (optional) | The billing arrangement for this link. Defaults to the source's default billing type when omitted.                                                                   |

`billingType` is a source-defined string. The supported values per source are reported on the discovery endpoint (`GET /api/v2/buyer/advertisers/:advertiserId/accounts/available?storefrontId=...&sourceId=...` returns `billingOptions.supported` and `billingOptions.default`). Common values:

| Value    | Meaning                                                       |
| -------- | ------------------------------------------------------------- |
| `brand`  | The advertiser is billed directly by the partner              |
| `agency` | An agency is the billing entity acting on behalf of the brand |

Other values may be supported by individual partners — always check `billingOptions.supported` before sending.

### Endpoints

| Method | Path                                                          | Purpose                                                    |
| ------ | ------------------------------------------------------------- | ---------------------------------------------------------- |
| `GET`  | `/api/v2/buyer/advertisers/:advertiserId/accounts`            | List linked accounts on the advertiser                     |
| `GET`  | `/api/v2/buyer/advertisers/:advertiserId/accounts/available`  | List accounts the source has discovered but not yet linked |
| `GET`  | `/api/v2/buyer/advertisers/:advertiserId/accounts/:accountId` | Get a single linked account                                |
| `POST` | `/api/v2/buyer/advertisers/:advertiserId/accounts`            | Link a source account to the advertiser                    |

### List linked accounts

```bash theme={null}
curl "https://api.interchange.io/api/v2/buyer/advertisers/12345/accounts?storefrontId=1&sourceId=src_main&status=active&take=50" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
```

Filters: `storefrontId` + `sourceId` (must be paired), `status` (`active`, `pending_approval`, `payment_required`, `suspended`, `closed`). Pagination: `take`, `skip`.

```json Response theme={null}
{
  "data": {
    "accounts": [
      {
        "linkId": "42",
        "accountId": "acc_67890",
        "credentialId": "cred_snap_coke",
        "name": "Acme c/o Pinnacle",
        "sources": [
          {
            "storefrontId": 1,
            "storefrontName": "Retail Media Network",
            "sourceId": "src_main",
            "sourceName": "Retail Network Agent"
          }
        ],
        "advertiserId": "12345",
        "billing": "brand",
        "status": "active",
        "createdAt": "2025-01-15T10:30:00Z",
        "updatedAt": "2025-01-20T14:45:00Z"
      }
    ],
    "total": 1
  }
}
```

### Link an account

```bash theme={null}
curl -X POST https://api.interchange.io/api/v2/buyer/advertisers/12345/accounts \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "storefrontId": 1,
    "sourceId": "src_main",
    "accountId": "acc_67890",
    "billingType": "brand"
  }'
```

The response carries the full `AccountOutput` with the server-assigned `linkId`. To pre-fill the request body, call `GET /accounts/available?storefrontId=1&sourceId=src_main` first — it returns every discovered account with its supported `billingOptions`.

### Get a single linked account

```bash theme={null}
curl https://api.interchange.io/api/v2/buyer/advertisers/12345/accounts/acc_67890 \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
```

Returns the same `AccountOutput` shape as list. Use this to confirm a link's current `status` after a source-side state change (e.g. moving from `pending_approval` to `active`).

<Tip>
  Linked accounts surface external account IDs (e.g. `acc_67890`) so cross-platform reporting and pass-through execution can target them without re-discovering credentials. The `linkId` is the Interchange-side primary key for the link itself; the `accountId` is the source-side account.
</Tip>

## Sandbox advertisers

Set `sandbox: true` at creation to mark the advertiser as test-only. All ADCP operations under sandbox advertisers — discovery, media buy creation, execution — route to sandbox-flagged sales agent accounts. No real platform calls are made and no real spend occurs.

Use sandbox advertisers to:

* Rehearse the discovery → execute → report flow end-to-end
* Test creative manifest workflows without notifying publishers
* Train AI agents against the API without billing implications

## Optimization apply mode

`optimizationApplyMode` controls whether Scope3's RL optimizer applies suggestions to media buys automatically.

* `MANUAL` (default) — suggestions appear in the suggestion feed; a human or agent must approve before they hit media buys
* `AUTO` — suggestions are applied immediately

The advertiser-level setting is the default for campaigns under the advertiser. Each campaign can override it.

## Related concepts

<CardGroup cols={2}>
  <Card title="Campaign" href="./campaign" icon="rocket">
    Marketing initiatives owned by the advertiser
  </Card>

  <Card title="Brand" href="./brand-story" icon="book-open">
    Brand identity resolved from AdCP registry or `/.well-known/brand.json`
  </Card>

  <Card title="Frequency caps" href="../guides/frequency-caps" icon="gauge">
    Buyer-side caps enforced by Scope3 across publishers
  </Card>

  <Card title="Creatives" href="./creative" icon="image">
    Manifest-based creatives nested under campaigns
  </Card>
</CardGroup>
