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

# Platform Accounts and Advertiser Mapping

> How connections, provider accounts, and advertiser mapping fit together across ad and creative platforms

When you connect an ad or creative platform (Meta, Google Ads, TikTok, Snap,
LinkedIn, Pinterest, Reddit, Spotify, OpenAI Ads, Amazon Ads, AudioStack,
ElevenLabs),
Apostra works with three distinct
things that are easy to conflate: the **connection** you authorized, the
**accounts** it can reach, and the **mapping** between those accounts and your
advertisers. This page defines each layer. For the permissions each platform
asks for and what Apostra does and doesn't need, see
[Connecting Ad Platform Accounts](/v2/guides/connecting-ad-platforms). For what
each platform's adapter can actually do once connected — products, creative
formats, targeting, and reporting — see
[Ad platform compatibility](/v2/guides/ad-platform-compatibility).

## The three layers

```mermaid theme={null}
flowchart LR
    subgraph grant["1 · Connection"]
        C["OAuth grant or API key<br/>(connect once at the<br/>organization or account level)"]
    end
    subgraph accounts["2 · Discovered accounts"]
        O["Organization account<br/>(Business Manager, MCC, …)<br/>context only — never buyable"]
        A1["Ad account A"]
        A2["Ad account B"]
        O --- A1
        O --- A2
    end
    subgraph mapping["3 · Advertiser mapping"]
        M1["Your advertiser X"]
        M2["Your advertiser Y"]
    end
    C --> O
    A1 --> M1
    A2 --> M2
    M1 --> B["Buys or generation for X use<br/>the account mapped to X"]
```

1. **Connection** — one OAuth grant or API key against a platform: "I linked
   this account." You can connect at the **organization level** (a manager
   account that reaches many ad accounts) or at the **advertiser level** (a
   single ad account). The connection carries the credential; revoking it on
   the platform side stops all access.
2. **Discovered accounts** — the accounts that connection credential can
   reach. After you connect, Apostra lists them from the platform. Each account carries
   an **account type** and, where the platform has hierarchy, its **parent
   organization**.
3. **Advertiser mapping** — links a platform account to one of *your*
   advertisers, so campaigns for that advertiser transact or generate on the
   right provider tenant. A connection may also have a display/default account,
   but advertiser-scoped work never falls back to it when a mapping is missing.

## Account types

Every discovered account is classified so you (and Murph) can tell what it is
and what it can do:

| Account type         | What it is                                                                                                                                                                                                                               | What it can run                                         |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| `advertiser`         | A mappable leaf account used for advertiser-scoped buying or creative generation                                                                                                                                                         | Ad platforms: buys; creative providers: generation only |
| `organization`       | A manager container (Meta Business Manager, Google MCC, Snap Organization, Reddit/Spotify Business, LinkedIn Organization, TikTok Business Center). Shown for context and grouping; it holds ad accounts but is not itself an ad account | **No** — never selectable, mappable, or buyable         |
| `sponsored_ads`      | An Amazon **Sponsored Ads profile**: retail media (Sponsored Products, Sponsored Brands, Sponsored Display), one profile per marketplace/country, tied to a seller or vendor account                                                     | Yes                                                     |
| `dsp`                | An Amazon **DSP advertiser**: programmatic display, video, and CTV bought through Amazon DSP — a separate system from Sponsored Ads under the same login                                                                                 | Yes                                                     |
| `publisher_identity` | A TikTok **channel authorization**: a creator or brand handle granted for Spark Ads. It is an identity for creative delivery, not a media-buying account                                                                                 | No — used for creative workflows                        |

Accounts with a parent also report `parentExternalId` and `parentName`, so an
agency grant reads as one organization with its client accounts underneath.

### Amazon Sponsored Ads readiness

Existing Buyer REST account calls require no changes. For an Amazon Sponsored
Ads profile, use `amazonSponsoredAds.marketplaceId` and
`amazonSponsoredAds.validPaymentMethod` to confirm that the selected profile is
ready before creating a media buy. `amazonSponsoredAds.countryCode` is included
when Amazon supplies a valid two-letter country code.

The `amazonSponsoredAds` projection is `null` for other account types and for
Amazon account data that does not meet the required shape. A matching
marketplace confirms account scope only; it does not grant catalog access,
ASIN eligibility, or another Amazon entitlement.

This readiness projection remains available when Amazon Sponsored Products
Manual creation is turned off. The rollout adds no Apostra charge, plan, or
entitlement.

## What each platform calls these

| Platform   | Organization account                  | Mappable provider account                                  |
| ---------- | ------------------------------------- | ---------------------------------------------------------- |
| Meta       | Business Manager / Business Portfolio | Ad account (`act_…`)                                       |
| Google Ads | Manager account (MCC)                 | Customer account (10-digit ID)                             |
| TikTok     | Business Center                       | Advertiser account (plus channel identities for Spark Ads) |
| Snap       | Organization                          | Ad account                                                 |
| LinkedIn   | Organization                          | Ad account (sponsored account)                             |
| Pinterest  | — (flat)                              | Ad account                                                 |
| Reddit     | Business                              | Ad account                                                 |
| Spotify    | Business                              | Ad account                                                 |
| OpenAI Ads | — (one credential per account)        | Advertiser account                                         |
| Amazon Ads | — (two systems, not a hierarchy)      | Sponsored Ads profile *or* DSP advertiser                  |
| AudioStack | API-key access grant                  | Credential grant billed to the authorized organization     |
| ElevenLabs | API-key access grant                  | Credential grant billed against the workspace quota        |

## Manager accounts and agencies

If your access flows through a manager account — an agency MCC on Google, a
Business Manager on Meta — connect **that** account. Apostra expands the
manager into its client ad accounts automatically: on Google, client accounts
under an MCC are discovered through the manager grant, attributed to the MCC as
their parent, and available to map and buy on individually. The manager account
itself is listed for context but can never be selected or transacted on.

For an agency to buy on a client's behalf, the grant happens **on the
platform**, not in Apostra: the client adds the agency's manager account /
Business Manager / Business Center as a partner with campaign-management
access. Once the platform-side grant exists, connecting the agency's manager
account in Apostra surfaces the client's ad accounts. Each platform's
[agency setup runbook](/v2/guides/connecting-ad-platforms#agencies-link-the-manager-account)
walks through the client-side steps per platform.

## After connecting

If an OAuth-only provider cannot be linked because Apostra has not configured
that provider's OAuth app in the current environment, the Connections page
disables **Connect account** and explains that Apostra must finish the provider
setup. This state does not indicate a problem with your provider account or
credentials, and retrying the connection will not fix it. No buyer action is
needed until the provider app becomes available.

API clients receive the same state from
`GET /api/v2/buyer/storefront-connections`. Each row includes
`setupRequired`, which is `null` when platform setup is complete. When an
OAuth-only provider app is unavailable, it is:

```json theme={null}
{
  "code": "oauth_client_not_configured",
  "message": "The provider account-linking app must be configured by Scope3."
}
```

Treat `oauth_client_not_configured` as a platform-owned blocker: show the
message and disable only the OAuth action. Providers that also support a bearer
credential still report the missing OAuth setup, but remain connectable through
the bearer mode.

For buyers managing creative and AI provider connections in Sellers, providers
that offer API-key authentication — including ElevenLabs, OpenAI, Gemini, fal,
Veo, and AudioStack — show **Update API key**. The action opens the secure
connection page, where the replacement key is stored; the key is never entered
into or returned by the Sellers widget. When a provider exposes account
discovery, the connection page checks account access before replacing the
credential. When a provider also supports OAuth, this action explicitly selects
its API-key flow.

1. Apostra discovers the accounts the grant can reach and classifies them.
   If discovery fails, the connection's `<auth-mode>.accountDiscovery`
   metadata (`oauth` or `bearer`) reports a stable `reason` (for example,
   `missing_configuration`,
   `permission_denied`, or `provider_unavailable`) and, when safe, a
   `providerCode`. Provider error messages and account details are not copied
   into this metadata.
2. If the connection reaches exactly one buyable account, it becomes the
   connection's **default account** automatically; otherwise pick one on the
   **Connections** tab.
3. Map each provider account to the advertiser whose campaigns should use it.
   The Connections page (**Settings → Connections**) splits this into two
   tabs: the **Connections** tab is where you link, unlink, and re-authorize
   grants; the **Advertiser mapping** tab is where discovered accounts —
   grouped under their manager account — are mapped to advertisers. An account
   can be mapped to more than one advertiser, and an advertiser can be mapped
   on several platforms. **The mapping decides which account a buy or creative
   generation runs on**: either a media buy or AudioStack/ElevenLabs generation
   for an unmapped advertiser fails with an
   `account_mapping_required` blocker pointing back to the Advertiser mapping
   tab — it never silently falls back to another account. For AudioStack and
   ElevenLabs, mapping chooses the billed provider tenant; the brand's
   `voice_synthesis` setting chooses the voice.
   You can complete this setup while the storefront is still configuring;
   mapping an account does not make the storefront transacting or allow buys
   before transacting is enabled.
   Each mapping also shows the provider account's **effective reporting time
   zone**. This is the calendar zone the seller uses for reporting-day
   boundaries. When it differs from the advertiser's preferred reporting time
   zone, Connections shows both values and flags the mismatch; it does not
   rewrite either one. A seller-fixed or seller-assigned account time zone wins
   for that account, while the advertiser preference remains available for
   providers that support buyer selection. Different connected accounts for
   the same advertiser can therefore have different reporting-day boundaries.
4. Connection summaries report a **mapped advertiser count** so you (and your
   agent) can see "connected, but 0 advertisers mapped" — connected is not the
   same as ready to buy or generate — before a campaign trips over it.
5. If accounts were added or removed on the platform side (for example, a new
   client under your MCC), choose **Refresh account list** next to
   **Reconnect**.
   Apostra reuses every active credential grant, adds newly visible accounts, and
   keeps the history and advertiser mappings for accounts that are no longer
   visible while marking those mappings unreachable. If a credential grant has
   expired or lost permission, the connection honestly changes to a
   reconnect-required state instead of showing a successful refresh.

An OAuth attempt that never reaches the callback is provisional. After its
signed state expires, it no longer appears as a separate storefront connection;
the next connection start or successful completion archives it. An unexpired
attempt remains available so a second, concurrent provider-account connection
can still finish. A callback already completing gets a short grace period before
it is hidden as abandoned; if that callback is merely slow and later succeeds,
the completed connection appears normally.

On the Connections page, feature controls are scoped to declared AdCP
capabilities. **Events** appears only when a seller source advertises
`sync_event_sources`; **Audiences** appears only for `sync_audiences`.
Unsupported controls are absent rather than disabled. Both data-sharing
permissions are independently consented and default off. **Buy** remains a
separate connection policy. Creative-tool cards never show buying or event
controls. Capability checks load independently for each connection; checking,
unavailable, and unsupported states remain distinct so a failed lookup does not
silently claim the seller lacks support.

### Agent and API flow

Official adapters use the connection-level account model:

1. `list_storefront_connections` identifies the connection.
2. When provider-side access changed, call
   `refresh_storefront_connection_accounts` with that `connectionId`. The
   operation reuses every active credential grant; reconnect only when its
   error says authorization is no longer healthy.
3. `list_storefront_connection_accounts` lists the accounts reached by that
   grant.
4. `list_storefront_connection_account_mappings` returns their current
   advertiser mappings, plus `effectiveTimezone` and `timezoneSource` for the
   provider account. A null `effectiveTimezone` means the provider has not
   supplied an authoritative time zone; it must not be inferred from the
   advertiser preference.
5. `map_storefront_connection_account_to_advertiser` maps an account with
   `connectionId`, `accountId`, and `advertiserId`. The path already identifies
   the adapter, so callers do not need to copy another identifier into the
   request body.

Official adapter responses expose one canonical provider `sourceId`, such as
`meta`, `google`, `tiktok`, or `snap`. A storefront's `platformId` (for example,
`meta-scope3-adapter`) identifies the storefront resource and is not a second
provider identity. Historical adapter/platform IDs remain accepted as
compatibility input, but responses normalize them to the canonical provider
ID.

`list_available_accounts` is the legacy advertiser-scoped AdCP path. A
compatibility bridge can mirror official-adapter accounts into it, but it also
applies advertiser/source matching and provisioning behavior and is not the
authoritative connection workflow. Do not interpret an empty result there as
the state of a Meta, Google Ads, TikTok, Snap, or other official adapter
connection.

## Unlinking

Unlinking a connection archives the grant and its credential, but your
advertiser mappings are **kept, not deleted**. A mapping whose provider account is
still reachable through another connection of the same platform (for example,
a second grant that covers the same account) keeps working. A mapping only
this connection reached is marked **unreachable** (`unreachableAt` on the
linked-account resource): it never resolves for buying or generation — the
affected buy or generation request is rejected and directs you to reconnect or
re-map rather than silently using another account. The mapping recovers
automatically when you reconnect the platform or re-map the account. A temporary
disconnect/reconnect never loses your mapping work.

## Revoking

Revoke access from the platform's own console (partner settings, manager
account, OAuth apps, or API keys). Apostra stops discovery, buying,
generation, creative sync, and reporting for that connection. See
[Revoking access](/v2/guides/connecting-ad-platforms#revoking-access).
