Skip to main content

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.

Overview

A storefront is a publisher’s inventory marketplace as seen from the buyer side. Each storefront wraps one or more inventory sources — the underlying ADCP agents (MCP or A2A) that handle product discovery and media-buy execution — and exposes them under a single name buyers can transact with. Buying through a storefront is gated on credentials per source: every inventory source declares whether it requires authentication, and the buyer registers credentials (API key, JWT, or OAuth) once per source. Once a source reports connected: true, discovery and media buys flow through it normally.
Storefront
  └── Inventory Source(s)        (MCP / A2A agent)
        └── Buyer credentials    (per source, per buyer)
              └── Customer accounts
This page covers the buyer side: browsing storefronts, expressing interest in upcoming supply, and wiring up credentials. If you operate a storefront, see Storefront onboarding.
All examples below use the buyer base URL:
https://api.interchange.io/api/v2/buyer

Why storefronts matter

  • One-stop access to publisher inventory — a storefront aggregates multiple inventory sources behind a single ID, so buyers don’t track agent endpoints individually
  • Per-source credential management — credentials are scoped to the inventory source, so rotating or revoking one doesn’t affect access to the others
  • AAO compliance gating — marketplace storefronts are gated on the Agentic Advertising Organization registry; only compliant sources surface to buyers
  • Multiple auth options — sources support API key, JWT, and OAuth flows, so the platform fits whatever the publisher’s agent already uses
  • Discoverable upcoming supply/storefronts/discover and /storefronts/interest let buyers see and request access to publishers they aren’t yet connected to

Key fields

The storefront resource has two response shapes:
  • Summary — returned by GET /storefronts (list). Row-level fields plus scalar source counts.
  • Full — returned by GET /storefronts/:id (get). The complete resource with the embedded sources[] array and per-source customer accounts.

BuyerStorefrontSummary (list rows)

FieldTypeDescription
idintegerStorefront ID
platformIdstringPublic-facing slug
namestringStorefront display name
publisherDomainstring | nullPublisher domain
sourceCountintegerTotal number of inventory sources in this storefront
connectedSourceCountintegerNumber of sources the buyer already has working credentials for
Use GET /storefronts/:id when you need the full source list (credential state, customer accounts).

BuyerStorefront (single storefront)

FieldTypeDescription
idintegerStorefront ID
platformIdstringPublic-facing slug
namestringStorefront display name
publisherDomainstring | nullPublisher domain
sourcesBuyerStorefrontSource[]Inventory sources available in this storefront

BuyerStorefrontSource

FieldTypeDescription
sourceIdstringInventory source identifier within the storefront
namestringInventory source display name
requiresCredentialsbooleanWhether the buyer must register credentials to use this source
connectedbooleanWhether the buyer has active credentials for this source
customerAccounts[{ accountIdentifier, status }]Buyer’s registered accounts for this source
Detecting whether a source uses OAuth. BuyerStorefrontSource does not expose an explicit authType field. To find out which auth modes a source accepts:
  • requiresCredentials: false — no auth needed; you can call discovery and media-buy endpoints directly.
  • requiresCredentials: true — POST to the credentials endpoint without a body; the validation error response lists the supported auth types (api_key, jwt, oauth). Alternatively, query the underlying agent’s ADCP capabilities, which advertise the supported authentication types.
If OAuth is in the list, follow the OAuth flow below instead of POSTing to the credentials endpoint.

Common operations

Listing storefronts

GET /storefronts returns the storefronts you can transact with, paginated.
curl "https://api.interchange.io/api/v2/buyer/storefronts?limit=20" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
Query parameters:
ParamNotes
nameCase-insensitive partial match on storefront name
limit1..50 (default 20)
offsetPagination offset (default 0)
Response (summary rows):
{
  "items": [
    {
      "id": 42,
      "platformId": "premium-ctv",
      "name": "Premium CTV Storefront",
      "publisherDomain": "premium-ctv.example.com",
      "sourceCount": 3,
      "connectedSourceCount": 1
    }
  ],
  "total": 1,
  "hasMore": false,
  "nextOffset": null
}
For the full source list — credential state, customer accounts — call GET /storefronts/:id.
When hasMore is true, pass nextOffset back as the offset parameter to walk pages.

Getting a storefront

GET /storefronts/:id returns the full BuyerStorefront resource — including the embedded sources[] array with per-source requiresCredentials, connected, and customerAccounts. Use this when you need fresh source state (e.g. after registering credentials or completing the OAuth flow) or when a row-level summary isn’t enough.
curl "https://api.interchange.io/api/v2/buyer/storefronts/42" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
Response
{
  "id": 42,
  "platformId": "premium-ctv",
  "name": "Premium CTV Storefront",
  "publisherDomain": "premium-ctv.example.com",
  "sources": [
    {
      "sourceId": "src_main",
      "name": "Premium CTV — Direct",
      "requiresCredentials": true,
      "connected": false,
      "customerAccounts": []
    }
  ]
}

Discovery (lightweight)

GET /storefronts/discover returns every storefront visible to a buyer — both ACTIVE and PENDING (upcoming) — with just id, name, publisherDomain, and status. This is the right endpoint for buyers who don’t yet have programmatic access but want to see what supply is coming.
curl "https://api.interchange.io/api/v2/buyer/storefronts/discover" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
{
  "items": [
    {
      "id": 42,
      "name": "Premium CTV Storefront",
      "publisherDomain": "premium-ctv.example.com",
      "status": "ACTIVE"
    },
    {
      "id": 77,
      "name": "Travel Vertical Network",
      "publisherDomain": null,
      "status": "PENDING"
    }
  ]
}
Discovery is intentionally minimal — no source list, no credential state. Use it to populate a “what’s available” picker, then submit interest with the IDs you care about.

Submitting interest

For private or upcoming storefronts you don’t yet have access to, submit an interest form. Scope3’s onboarding team picks it up via Slack. POST /storefronts/interest accepts:
FieldTypeNotes
storefrontIdsnumber[]Up to 100 storefront IDs you’re interested in
notesstringFree-form notes, up to 4000 chars
You must provide at least one of storefrontIds or notes.
curl -X POST "https://api.interchange.io/api/v2/buyer/storefronts/interest" \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "storefrontIds": [42, 77],
    "notes": "Targeting Q3 CTV upfronts; need access to travel vertical."
  }'
{
  "submitted": true,
  "submittedAt": "2026-04-26T15:00:00.000Z"
}
To check whether you’ve already submitted, call GET /storefronts/interest:
curl "https://api.interchange.io/api/v2/buyer/storefronts/interest" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
{
  "submitted": true,
  "submittedAt": "2026-04-26T15:00:00.000Z"
}

Listing your credentials

GET /storefronts/credentials returns every credential you’ve registered, scoped to the storefront sources each credential gives access to. Use it to build a single “connected sources” view in your dashboard without paging through each storefront.
curl "https://api.interchange.io/api/v2/buyer/storefronts/credentials" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
Response
[
  {
    "id": "722",
    "accountIdentifier": "your-account-id",
    "accountType": "CLIENT",
    "status": "ACTIVE",
    "registeredBy": "user@example.com",
    "createdAt": "2026-02-23T19:55:11.602Z",
    "updatedAt": "2026-02-23T19:56:56.272Z",
    "sources": [
      {
        "storefrontId": 42,
        "storefrontName": "Premium CTV Storefront",
        "sourceId": "src_main",
        "sourceName": "Premium CTV — Direct"
      }
    ]
  }
]
Each credential lists every (storefrontId, sourceId) pair it covers in sources[]. A single credential can cover the same source across multiple storefronts when the underlying agent is shared.

Registering credentials per source

For sources that report requiresCredentials: true, you must register credentials before you can run discovery or create media buys. POST /storefronts/:storefrontId/sources/:sourceId/credentials
Inspect the source’s requiresCredentials field on the parent storefront before calling this endpoint — sources that report requiresCredentials: false don’t need this step.
curl -X POST \
  "https://api.interchange.io/api/v2/buyer/storefronts/42/sources/src_main/credentials" \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "accountIdentifier": "your-account-id",
    "auth": {
      "type": "api_key",
      "token": "<SOURCE_API_KEY>"
    }
  }'
Body fields:
FieldTypeNotes
accountIdentifierstringUnique account ID at the source (1..255 chars)
authobjectAPI key or JWT credentials. Required for non-OAuth sources.
marketplaceAccountbooleanAdmin-only. When true, creates a marketplace account instead of a client account.
Auth tokens grant ADCP access on your behalf. Treat auth.token (and any private keys) as a production secret:
  • Store it in a managed secret vault. Scope3 itself stores it in Google Secret Manager and references it via auth_secret_ref.
  • Never log the raw token, never echo it to stdout, and never commit it to source control.
  • Rotate on any suspected exposure and on a documented schedule.
  • Use placeholders like <SOURCE_API_KEY> in documentation and sample requests — never a real key.

Registering an account for a source

When you want a source to bill or report against a specific advertiser seat in your account, register an account with advertiserId: POST /storefronts/:storefrontId/sources/:sourceId/accounts
curl -X POST \
  "https://api.interchange.io/api/v2/buyer/storefronts/42/sources/src_main/accounts" \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "advertiserId": "12345",
    "accountIdentifier": "acme-brand-account",
    "auth": {
      "type": "api_key",
      "token": "<SOURCE_API_KEY>"
    }
  }'
Body fields:
FieldTypeNotes
advertiserIdstringNumeric seat ID to associate with this account
accountIdentifierstringUnique account ID at the source (1..255 chars)
authobjectCredentials. Required for API_KEY/JWT sources, omitted for OAuth

OAuth flow for OAuth-secured sources

Some inventory sources use OAuth. In that case, the credentials endpoint isn’t enough — the buyer must complete an interactive consent flow, and the source agent exchanges an authorization code for tokens via the storefront OAuth-authorize endpoint.
The OAuth endpoints sit on the /api/v2/storefront/... mount because they power the storefront’s auth integration on behalf of buyers and sellers alike. Buyers reach them by agentId — the underlying ADCP agent that backs the inventory source. (You can discover the agent ID from the storefront’s source list, or via the Discovery guide.)
Step 1 — Request an authorization URL.
curl -X POST \
  "https://api.interchange.io/api/v2/storefront/agents/agt_premium_ctv/accounts/oauth/authorize" \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "accountIdentifier": "acme-brand-account"
  }'
accountIdentifier is optional — when omitted, the platform uses oauth_<customerId> as the placeholder identifier and you can rename the account later.
Response
{
  "authorizeUrl": "https://idp.example-publisher.com/oauth/authorize?client_id=...&redirect_uri=https%3A%2F%2Fapi.interchange.io%2Fapi%2Fv2%2Fstorefront%2Foauth%2Fcallback&state=pending_abc123&scope=adcp%3Aread+adcp%3Awrite",
  "state": "pending_abc123"
}
Step 2 — Send the operator to authorizeUrl. Open it in a popup or new tab. The publisher’s IdP authenticates the user, asks them to consent, and redirects back to the platform-hosted callback (/api/v2/storefront/oauth/callback). Step 3 — The platform finishes the exchange. The callback page exchanges the authorization code for tokens, stores them under your customer + the source’s underlying agent, and notifies the opener window via postMessage({ type: 'oauth-complete' }) before auto-closing. Refresh GET /api/v2/buyer/storefronts/:storefrontId after that — the source should now report connected: true. If you need to drive the callback yourself (for example, in a non-browser agent), POST /api/v2/storefront/agents/:agentId/oauth/callback accepts the code and state directly. The seller side of OAuth (callback URLs, state handling, secret rotation) is documented in Storefront onboarding.

Endpoint reference

MethodPathPurpose
GET/storefrontsList storefronts (paginated)
GET/storefronts/:storefrontIdGet a single storefront
GET/storefronts/discoverLightweight list of all storefronts (active + upcoming)
GET/storefronts/interestCheck your interest submission status
POST/storefronts/interestSubmit interest in one or more storefronts
GET/storefronts/credentialsList your credentials across all storefronts
POST/storefronts/:storefrontId/sources/:sourceId/credentialsRegister credentials for a source
POST/storefronts/:storefrontId/sources/:sourceId/accountsRegister an account (with advertiser linkage)
When a source isn’t returning products as expected, check connected on that source via GET /storefronts/:id — if it’s false, your credentials aren’t yet active. If it’s true, fall through to the Discovery flow with proposal.action: "discover".

Buyer onboarding

End-to-end setup for a new buyer customer.

Discovery

Once your sources are connected, run discovery to find products.

Advertiser

Advertisers are the seats you link to source accounts.

Storefront onboarding

Operating a storefront? Start here for the seller-side setup.