> ## 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.

# Storefronts

> Browse storefronts, connect inventory sources, and manage adapter credentials

A **storefront** is a publisher's buyer-facing home on Interchange — a single ID that aggregates one or more **inventory sources**. A source can be an external AdCP sales agent or managed ad-server-backed inventory. As a buyer you browse the storefronts you can transact with and connect the credentials each source or adapter needs so discovery and media buys flow. For the full conceptual model — the Merchandising Agent, composition vs. passthrough storefronts, OAuth flows, and the seller side — see the [Storefront object guide](/v2/object-guides/storefront).

Buying through a source-backed storefront is gated on **credentials per source** when the source requires them. List endpoints return compact summaries with scalar source counts: `sourceCount` is the number of active sources behind the storefront, and `connectedSourceCount` is how many of those sources the buyer is already wired to use. Fetching a single storefront returns the rolled-up `connected`, `requiresCredentials`, and `customerAccounts` fields rather than exposing the full source list.

There are two bills: intelligence units (IUs) and media. Interchange clears the media transaction — and it appears on your Interchange media bill — only when the storefront advertises `agent` billing (AdCP `BillingParty` vocabulary: the agent, Interchange, is the invoiced party and bills you). Every storefront list and marketplace card carries `supportedBilling`, and every hosted AdCP capability response carries the protocol-native `account.supported_billing`, so you know the counterparty before you buy. Adapter storefronts advertise `["operator", "advertiser"]`: your connected platform account bills you directly, and Interchange never touches the media money.

Storefront names are not always the names buyers use in conversation. The
authenticated storefront list's `name` filter also resolves the seller
account or company, brand, publisher/operator domain, and website. Public Murph
lookup uses only curated storefront name, brand, domain, and website fields for
marketplace-listed storefronts, so questions such as
"Is OptOut's storefront available?" work without supplying an exact domain or
connecting the Slack channel to an account. That public answer contains only
the seller and storefront names, public status, domain, channels, and regions;
buyer credentials and account-specific data still require authentication.

When a Scope3 admin declares a Slack channel shared between a buyer and a
seller, Interchange records that relationship as demand and automatically
shows the seller's marketplace-visible storefront relationship in the buyer's
**Supply I would buy** view with the `storefront` channel. These rows are labeled as shared-channel tracking and are not
removable manual requests. Any seller-facing demand summary keeps the buyer's
identity private unless disclosure is separately permitted.

Use `GET /api/v2/buyer/storefronts/:storefrontId/capabilities` when you need a diagnostic view of the active sources behind a storefront. External AdCP sales-agent sources are capability-checkable and include cached-or-refreshed capability details. Managed ad-server-backed sources are returned with `probeable: false` and `probeStatus: "not_applicable"`; do not treat those rows as unreachable agents just because they are not checked through the AdCP capabilities endpoint.

Adapter storefronts can have more than one connected provider account for the same buyer. For example, an agency can connect separate Snap business accounts for different brands, or a single advertiser can connect separate provider accounts for separate product lines. Use the storefront connection OAuth flow again to add another provider account; already-connected storefronts show this as adding an account rather than replacing the existing one.

When listing or linking advertiser accounts from an adapter storefront, use the returned `credentialId` to distinguish which connected provider credential owns the account. This is required when more than one connected credential can expose the same upstream `accountId`.

Account discovery is stored as an authoritative provider snapshot. The account
list preserves the provider's normalized and provider-native status, hierarchy,
advertiser label, and ISO currency; these fields are returned consistently by
the buyer REST API and service routes. Only active advertiser accounts can
become the default or selected buying account. Manager containers and accounts that are pending,
payment-blocked, suspended, rejected, or closed remain visible for setup and
diagnosis but are not selectable. If provider pagination or validation fails,
Interchange keeps the previous valid snapshot rather than treating a partial
response—or a storage error midway through publication—as account deletion.
When a credential is replaced while an older refresh is still running, the
older response is discarded even if it completes last; only the snapshot made
with the current credential can replace the stored list. For Meta, a
`sandbox: true` account-list request returns no accounts until Meta test-account
classification is supported, so production accounts are never returned to a
sandbox canary. A database lock or statement timeout during publication also
keeps the prior complete account list. Publication is rejected before changing
the stored list if a provider returns more than 5,000 accounts or the complete
database publication exceeds 30 seconds. During a rolling deployment, an older
application replica can still change which existing account is selected, but
cannot replace authoritative provider account fields without the current
credential proof.
OAuth token refresh publishes a replacement credential atomically. If that
publication fails, the previously connected credential remains bound and
usable; the old credential is retired only after the replacement commits.
When a reconnect succeeds, Interchange keeps the selected account and its
stable account identity only if the refreshed grant's complete account list
still contains that account; the account is then rebound to the refreshed
credential. A selected Snap account is not reported as authorized unless that
exact active OAuth credential still owns the account and its stored secret can
be read. Missing, expired, errored, mismatched, or unavailable credentials fail
closed before a provider tool runs and expose the safe diagnostic reason
`delegated_auth_unready`; reconnect Snap to restore the account.

Existing Snap connections require one reconnect after this deployment. This
intentionally establishes fresh account-ownership proof instead of trusting or
backfilling a pre-deployment snapshot. Until that reconnect succeeds, Snap
adapter calls fail closed with `delegated_auth_unready`.

OAuth credentials are never returned in account metadata. Meta financial amounts are converted from the
account currency's minor unit, so zero-decimal currencies such as JPY and
three-decimal currencies such as KWD are not treated as cents. Meta's zero
`spend_cap` value means that no spending cap is configured; it is not reported
as zero available credit.

Adapter credentials are separate from inventory source credentials. Do not use `POST /storefronts/:storefrontId/sources/:sourceId/credentials` to fix an adapter-provider OAuth token, API key, or bearer token; reconnect or rotate the adapter credential through the storefront adapter connection flow for that provider.

In the connected-account campaigns alpha, a registered external AdCP source can
also be projected into the shared buyer connection plane after its account is
discovered and linked to an advertiser. Use
`POST /storefronts/:storefrontId/sources/:sourceId/adcp-connection`; it does not
accept a new endpoint or secret and does not replace source registration.

## Adapter credential lifecycle

Adapter storefront credential status is maintained after the initial connection. OAuth credentials are refreshed automatically during use and by a nightly health sweep before expiry. If refresh fails because the provider token is expired, revoked, or otherwise rejected, Interchange marks the adapter credential `EXPIRED` and the storefront connection summary reports `error` until the buyer reconnects.

Bearer and API-key adapter credentials cannot be refreshed by Interchange. If they carry an expiry timestamp, the health sweep notifies operators before expiry and marks them `EXPIRED` after expiry. Delegated adapter calls that receive provider auth failures also write back credential health: expired OAuth credentials become `EXPIRED`, while invalid API keys, bearer tokens, or permission failures become `ERROR`.

## Key concepts

| Concept                                | Description                                                                                             |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| Storefront                             | A publisher's buyer-facing presence aggregating inventory sources behind one `id`                       |
| Inventory source                       | A source behind a storefront, either an external AdCP sales agent or managed ad-server-backed inventory |
| `requiresCredentials`                  | Whether the buyer must register credentials to use a source                                             |
| `connected`                            | Whether the source is usable without additional credentials or already has working buyer credentials    |
| Credential                             | A buyer's registered account at a source — covers one or more `(storefrontId, sourceId)` pairs          |
| `credentialId`                         | Connected provider credential identifier used to disambiguate duplicate upstream account IDs            |
| `displayStatus`                        | Public storefront state: `configuring`, `transacting`, or `archived`                                    |
| `sourceCount` / `connectedSourceCount` | Total sources vs. those the buyer has wired up                                                          |

## Task reference

<CardGroup cols={2}>
  <Card title="List storefronts" href="/v2/buyer/storefronts/tasks/list-storefronts" icon="list">
    `GET /storefronts` — paginated summaries
  </Card>

  <Card title="Get storefront" href="/v2/buyer/storefronts/tasks/get-storefront" icon="magnifying-glass">
    `GET /storefronts/:storefrontId` — rolled-up connection state
  </Card>

  <Card title="Get storefront capabilities" href="/v2/buyer/storefronts/tasks/get-storefront-capabilities" icon="signal">
    `GET /storefronts/:storefrontId/capabilities` — source diagnostics
  </Card>

  <Card title="List credentials" href="/v2/buyer/storefronts/tasks/list-credentials" icon="key">
    `GET /storefronts/credentials` — all your registered credentials
  </Card>

  <Card title="Register source credentials" href="/v2/buyer/storefronts/tasks/register-source-credentials" icon="user-lock">
    `POST /storefronts/:storefrontId/sources/:sourceId/credentials` — connect an inventory source, not an adapter provider
  </Card>

  <Card title="Connect an AdCP source (alpha)" href="/v2/buyer/storefronts/tasks/connect-adcp-storefront" icon="link">
    Project a mapped source account into tracked campaigns
  </Card>
</CardGroup>

## Related

<CardGroup cols={2}>
  <Card title="Storefront object guide" href="/v2/object-guides/storefront" icon="store">
    Full model: sources, OAuth, seller side
  </Card>

  <Card title="Discovery" href="/v2/guides/discovery" icon="magnifying-glass">
    Once connected, run discovery to find products
  </Card>
</CardGroup>
