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

# Authentication

> How to authenticate with the Interchange API using OAuth or API keys.

# Authentication

Interchange uses WorkOS as its credential control plane. Interactive connectors use
OAuth, AI agents can use Agent Registration, simple customer automation uses
organization API keys, and backend integrations that require OAuth client credentials
can use M2M applications.

## Buyer signup and organization invitations

New standalone buyer organizations are admitted in stages. When buyer admission is
closed, selecting **Advertiser** during signup opens the buyer preview form. It asks
whether the buyer is a brand or agency, which countries and channels they plan to
buy, their estimated pilot budget and timing, their self-service buying experience,
and whether they are comfortable testing a pre-launch product with support in Slack.
Buyers whose plans match a live pilot market and channel are sent for solutions
review; buyers outside the current markets stay on the launch list under the exact
countries they selected. Those country-level signals guide where Interchange expands
next; selecting a country does not claim that a pilot is already open there.
When a work-email domain already belongs to a known organization, Interchange
associates the preview request with that organization and pre-fills its canonical
name. This does not grant membership in an existing account: an invitation or the
account's normal domain-approval policy is still required for access.
When admission is open, the same signup creates the buyer organization and then
offers three starting points: work in Interchange, build with the API, or connect an
assistant. Choosing one does not remove access to the other two.

## Storefront signup and IU plans

Public Storefront account creation is independent from the Organization IU Rate Card
rollout. A Storefront prospect can accept Scope3's standard Terms of Service and
create an account even when IU plan selection is unavailable. That acceptance creates
the account's standard agreement; it does not publish or accept an IU Rate Card,
enroll the organization in a paid IU plan, grant setup credit, or enable IU charging.

When the IU rollout is closed, signup does not show pricing previews or signup-code
entry and rejects clients that try to submit IU plan or signup-code data. Custom
signup clients can distinguish the states in the email-availability response:
`storefrontAccountSignupAllowed` controls account creation and
`storefrontIuSignupAllowed` controls the IU plan-selection step. The legacy
`storefrontSignupAllowed` field retains its IU-step meaning during the transition.

An organization invitation is a separate, org-scoped path. Its recipient can create
an account and join the named organization even while public buyer signup is
waitlisted. The invited organization must itself be admitted to the current rollout.
The invitation does not create a second buyer organization, grant access to the wider
marketplace by itself, or replace any Terms of Service, account, or spend requirements
on the invited organization.

Seller [join links](/v2/storefront/join-links/overview) are different: they are
reusable links that create sponsored buyers scoped to one storefront.

***

## OAuth (Recommended for AI Agents)

When connecting through Claude Connectors or ChatGPT MCP Connectors, authentication is handled automatically via OAuth. Users log in with their Scope3 credentials and the agent receives a secure token.

* No API keys to create or manage
* Tokens are scoped to the authenticated user
* Works with Claude.ai (Team/Enterprise), Claude Desktop, and ChatGPT

See the [Built for Agents](/v2/setup/built-for-agents#connecting-ai-agents) guide for setup instructions.

### MCP protocol compatibility

The buyer and storefront MCP endpoints support both stateless MCP 2026-07-28
requests and the existing initialize/session lifecycle. MCP clients negotiate
the protocol automatically; users do not enable a setting or repeat OAuth
authorization to opt in. Existing connectors continue working unchanged.

Specialized Murph, creative, admin, TARS, and dynamic platform-storefront MCP
endpoints remain on the session lifecycle during the staged rollout.

***

## API Keys

For CLI tools, scripts, shared automation, and direct REST API integrations, use an
organization API key unless the integration specifically requires OAuth client
credentials.

### Getting Your API Key

1. Visit [interchange.io/user-api-keys](https://interchange.io/user-api-keys)
2. Sign up or log into your Interchange account as an organization admin
3. Select **Account API keys**
4. Create a key and select only the permissions the integration needs
5. Copy the key when WorkOS displays it

<Warning>
  **Keep your API key secure!** Don't commit it to version control or share it publicly. Use environment variables or secure key management systems.
</Warning>

### Org API Keys

Organization API keys are owned by the organization rather than an individual user.
WorkOS creates, stores, masks, and revokes the keys; Interchange resolves the
organization and applies its resource, entitlement, standing, governance, and spend
policies.

#### Permissions

Each org API key carries one or more permission scopes:

| Permission      | What it grants                          |
| --------------- | --------------------------------------- |
| `buyer:read`    | Read campaigns, advertisers, reports    |
| `buyer:write`   | Create and modify campaigns and tactics |
| `buyer:admin`   | Org settings, user management, delete   |
| `account:admin` | Billing, contracts, teams               |

**Principle of least privilege:** issue each key with only the permissions it needs.

#### Managing keys

```bash theme={null}
# List keys for your org
curl -X GET "https://api.interchange.io/api/v2/org-api-keys" \
  -H "Authorization: Bearer your_user_access_token_here"

# Create a key with read-only access
curl -X POST "https://api.interchange.io/api/v2/org-api-keys" \
  -H "Authorization: Bearer your_user_access_token_here" \
  -H "Content-Type: application/json" \
  -d '{"name": "reporting-bot", "permissions": ["buyer:read"]}'

# Revoke a key
curl -X DELETE "https://api.interchange.io/api/v2/org-api-keys/key_abc123" \
  -H "Authorization: Bearer your_user_access_token_here"
```

All three endpoints require an interactive human session with `buyer:admin`; an API
key or M2M token cannot create another credential.

#### Embedded key management widget

The Interchange **Account API keys** settings tab embeds the WorkOS API Keys widget.
The widget displays a key in full only when it is created; later views show a masked
value. Organization admins can inspect and revoke keys there. Organization keys can
select `buyer:read`, `buyer:write`, and `buyer:admin`; `account:admin` is not
delegatable through the widget.

Customers that still have a `scope3_` API key see a **Legacy API keys**
section below the WorkOS widget. Account administrators see both user keys and
older customer-scoped keys so working account-level legacy credentials remain visible during
migration; other users see only their own keys. Settings no longer offers creation,
editing, or secret reveal for those keys. Create an organization API key, update and
verify the integration that uses the legacy key, and then revoke it.
Existing legacy keys continue to authenticate until they expire or are revoked.

Applications embedding the same management surface can request a short-lived widget
session token:

```bash theme={null}
curl -X GET "https://api.interchange.io/api/v2/org-api-keys/widget-token" \
  -H "Authorization: Bearer your_user_access_token_here"
```

The response requires an interactive WorkOS user session and includes a short-lived
`token` for the WorkOS frontend widget. Never expose the WorkOS server API key to a
browser.

### Using Your API Key

Pass the key as a Bearer token in the `Authorization` header:

<Tabs>
  <Tab title="curl">
    ```bash theme={null}
    curl -X GET "https://api.interchange.io/api/v2/buyer/advertisers" \
      -H "Authorization: Bearer your_api_key_here" \
      -H "Content-Type: application/json"
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const response = await fetch(
      'https://api.interchange.io/api/v2/buyer/advertisers',
      {
        headers: {
          'Authorization': `Bearer ${process.env.SCOPE3_API_KEY}`,
          'Content-Type': 'application/json',
        },
      }
    );

    const { data } = await response.json();
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import requests
    import os

    response = requests.get(
        "https://api.interchange.io/api/v2/buyer/advertisers",
        headers={
            "Authorization": f"Bearer {os.environ['SCOPE3_API_KEY']}",
            "Content-Type": "application/json",
        },
    )

    data = response.json()["data"]
    ```
  </Tab>
</Tabs>

***

## Agent Registration

An agent that has no credential starts with
[`https://api.interchange.io/auth.md`](https://api.interchange.io/auth.md). The guide
is generated by WorkOS and describes anonymous registration, the optional user claim
ceremony, and assertion exchange.

Anonymous registrations receive a short-lived WorkOS access token and can reach only
the zero-spend Interchange sandbox. This bounded anonymous trial does not require an
organization to accept Terms of Service because the agent is not associated with a customer yet.
Before claim, the only customer-data API reads are
`GET|HEAD /api/v2/buyer/advertisers[/:id]`; all mutations, nested advertiser routes,
MCP calls, and money-moving routes are denied.
Access to customer data or write operations requires a `service_auth` claim completed
by the customer user; after claim, the customer must satisfy Terms of Service, account
grants, commercial entitlements, governance, and spend controls.

***

## M2M Applications

Use an M2M application when a deployed customer backend requires the OAuth 2.0
`client_credentials` flow and short-lived JWT access tokens. An organization admin can
manage applications through `/api/v2/m2m-applications`; creation returns the client
secret once, together with the WorkOS token endpoint and Interchange resource
indicator. The token endpoint is hosted on Interchange's AuthKit domain for the
environment. Store the secret in a secrets manager.

M2M applications support overlapping client secrets for rotation. Revoke the old
secret only after the new secret has successfully obtained and used an access token.
Deleting the application immediately disables its local Interchange customer association;
already-issued access tokens are rejected locally even if they have not expired.

***

## Legacy `scope3_` Keys

Existing `scope3_` keys remain accepted during the credential migration and can still
be revoked. They are compatibility credentials, not the target for new integrations.
Do not replace a working key until its WorkOS replacement has made a successful test
call. Interchange will publish any retirement date only after owners, usage telemetry,
customer communication, and rollback readiness meet the retirement gate.

***

## MCP Authentication

For AI agent integrations using the Model Context Protocol:

<Note>
  An MCP agent cannot retrieve an existing API key or M2M client secret, and it must
  not mint or carry a new long-lived secret in chat. For an organization API key, the
  agent directs a human organization admin to **Settings → API Access**. M2M does not
  have a management widget yet; a human admin or their developer uses the documented
  `/api/v2/m2m-applications` lifecycle with an interactive human session. The human
  copies the one-time secret directly into the workload's secret manager. The workload
  then uses the API key, or exchanges an M2M client secret for short-lived access
  tokens.
</Note>

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { Client } from '@modelcontextprotocol/sdk/client/index.js';
    import { HttpClientTransport } from '@anthropic-ai/mcp-client-http';

    const transport = new HttpClientTransport({
      url: 'https://api.interchange.io/mcp/buyer',
      headers: {
        'Authorization': `Bearer ${process.env.SCOPE3_API_KEY}`,
      },
    });

    const client = new Client({ name: 'my-agent', version: '1.0.0' });
    await client.connect(transport);

    const result = await client.callTool('health', {});
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from mcp.client.streamable_http_transport import StreamableHttpTransport
    from mcp.client import Client

    transport = StreamableHttpTransport(
        "https://api.interchange.io/mcp/buyer",
        auth="your_api_key_here",
    )

    async with Client(transport) as client:
        result = await client.call_tool("health")
    ```
  </Tab>
</Tabs>

***

## Base URLs

| Type                           | Production                                     |
| ------------------------------ | ---------------------------------------------- |
| Buyer REST                     | `https://api.interchange.io/api/v2/buyer`      |
| Storefront REST                | `https://api.interchange.io/api/v2/storefront` |
| Buyer MCP                      | `https://api.interchange.io/mcp/buyer`         |
| Canonical Storefront Agent URL | `https://interchange.io`                       |

<Note>
  Programmatic API endpoints and buyer MCP are served at `https://api.interchange.io`. The canonical storefront agent URL is `https://interchange.io`. Discovery endpoints under `/.well-known/*` (JWKS, brand.json, OAuth/OIDC metadata) return the same response on both `https://api.interchange.io` and `https://interchange.io`.
</Note>

***

## Versioning

REST and MCP endpoints come in two forms — pick based on whether you want to pin to a specific major version or auto-roll with the platform.

| Form                      | Example                          | Behavior                                                                                                     | When to use                                                                                            |
| ------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------ |
| **Versioned** (canonical) | `/api/v2/buyer`, `/mcp/v2/buyer` | Pinned to v2. Will keep serving v2 even after a future v3 ships.                                             | Production integrations, SDKs, anywhere a breaking change would silently break you.                    |
| **Unversioned** (alias)   | `/api/buyer`, `/mcp/buyer`       | 308-redirects to whatever major version is currently stable (today: v2). Auto-rolls when a new major is cut. | Quick demos, links you don't want to update, or environments where you actively want to follow latest. |

The same pattern applies to storefront endpoints (`/api/v2/storefront` vs `/api/storefront`, `/mcp/v2/storefront` vs `/mcp/storefront`).

The Base URLs table above lists the **versioned** form because it's what we recommend for any integration you don't plan to revisit on every major release.

***

## Terms of Service acceptance

Every organization must accept Scope3's Terms of Service before its
authenticated members can use most of the API surface. ToS acceptance applies to the
organization, not the individual. Accounts under a parent organization inherit
the parent's governing agreement; they do not accept separate account-level
terms. Once a direct parent-organization ADMIN accepts, the organization and
its accounts are unblocked.

**Only a direct ADMIN or SUPER\_ADMIN `UserPermission` on the organization that
owns the governing agreement is permitted to accept its ToS via
`POST /api/v2/accept-tos` (or the `accept_tos` MCP tool).**

* An account member who is not a direct admin of its parent organization
  cannot accept the parent's ToS. They must join the parent organization as an
  admin first.
* A direct member at a non-admin level (`BASIC`, `PREMIUM`) also cannot
  accept — only `ADMIN` / `SUPER_ADMIN` levels qualify.

Pending organization invitations remain available while ToS is outstanding.
Open the account selector, choose the pending invitation, and accept or decline
it. Accepting an admin invitation creates the direct organization membership
needed to review and accept the organization's ToS; the ToS prompt does not
block the invitation page.

### When updated terms are published

When updated Terms of Service appear in Interchange, the required action
depends on the kind of change:

* A patch that does not materially change the terms, or is wholly favorable to
  customers, is a notice-only update. Existing acceptance continues without an
  interruption.
* A material minor or major update requires an organization administrator to
  accept. Before the displayed deadline, eligible administrators see the
  review prompt and can choose **Review later**; other members can continue
  working during that review period.
* Once the deadline passes, account activity pauses until an eligible
  administrator accepts. Non-admin members then see a notice telling them to
  contact an administrator, while the account selector remains available.

Accepting a minor update keeps the existing commercial contract and any
negotiated pricing attached to it. A major update does not silently replace
custom commercial terms; Scope3 coordinates that change separately.

REST and MCP integrations can read the transition in the `tosUpdate` object on
current-user and account-switch responses. Its `action` is `notice`,
`acceptance_due`, or `acceptance_required`, with the target version, deadline,
terms URL, and change-summary URL. If Interchange cannot verify agreement
status, protected actions return a retryable service error rather than
proceeding without confirmed terms.

The user-info responses (`/auth/me`, `POST /api/v2/accounts/switch`,
`POST /api/v2/accounts/create-child`, and the `user_get_current` MCP
tool) include a `canAcceptTos` boolean reflecting this rule. When
`showTosBox: true` but `canAcceptTos: false`, the UI shows a blocking notice.
The global account selector remains available so the user can switch to an
unblocked organization or accept a pending organization invitation.

`/auth/me` also returns `contractBlockReason` when the active account cannot
transact, and omits it when the account is in good standing:

| `contractBlockReason`           | Meaning                                                                                                                                                                            |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `no_contract`                   | The account has no active contract with Scope3. Accepting the Terms of Service creates one.                                                                                        |
| `tos_not_accepted`              | The account is on standard terms it has not accepted — either it accepted an older version, or Scope3 set it up on standard terms and nobody at the account has accepted them yet. |
| `organization_contract_missing` | The account inherits its parent organization's contract, and the organization has no active one. An organization admin must accept on its behalf.                                  |

`showTosBox` answers "must this session be blocked"; `contractBlockReason`
answers "why can this account not transact". They differ for a Scope3 SuperAdmin
working inside a customer account: that session is deliberately not blocked
(`showTosBox: false`), but the reason is still reported so the operator sees the
state a real user of that account would hit.

See the [Adding an account](/v2/setup/buyer-onboarding#adding-a-child-account)
section of the Buyer Onboarding guide for the full account-creation flow.

***

## Next Steps

<CardGroup cols={3}>
  <Card title="Quick Start" href="/v2/quickstart" icon="rocket">
    Get up and running in minutes.
  </Card>

  <Card title="Built for Agents" href="/v2/setup/built-for-agents" icon="robot">
    Connect Claude, ChatGPT, Cursor, and more.
  </Card>

  <Card title="SSO Setup" href="/v2/setup/sso-setup" icon="lock">
    Configure single sign-on for your organization.
  </Card>
</CardGroup>
