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

# Register source credentials

> Register credentials for an inventory source so it reports connected

`POST /api/v2/buyer/storefronts/{storefrontId}/sources/{sourceId}/credentials`

Registers credentials for an external AdCP inventory source within a storefront. Once registered, the storefront's rolled-up connection state can report `connected: true` when all required source credentials are present, and discovery and media buys can flow through it. For OAuth sources, the response carries an `oauth.authorizationUrl` the buyer must visit to finish consent.

<Note>
  Check the parent storefront first. If it reports `requiresCredentials: true`,
  use the capabilities endpoint to find active external AdCP source IDs with
  `requiresCredentials: true`, then compare with the credentials list to avoid
  registering duplicates. Sources with `requiresCredentials: false` do not need
  this step. If `requiresCredentials` is `null`, the endpoint cannot determine the
  source's credential requirement; do not infer that registration is required from
  the capability row alone.
</Note>

## Request

<CodeGroup>
  ```bash API key theme={null}
  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": "acme-brand-account",
      "auth": {
        "type": "api_key",
        "token": "<SOURCE_API_KEY>"
      }
    }'
  ```

  ```bash JWT theme={null}
  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": "acme-brand-account",
      "auth": {
        "type": "jwt",
        "privateKey": "<PRIVATE_KEY>",
        "issuer": "acme-issuer",
        "subject": "acme-subject",
        "keyId": "acme-key-1",
        "scope": "adcp:read adcp:write",
        "tokenEndpointUrl": "https://idp.example.com/oauth/token",
        "audienceUrl": "https://agent.premium-ctv.example.com"
      }
    }'
  ```
</CodeGroup>

<Warning>
  Auth tokens grant AdCP access on your behalf. Store them in a managed secret
  vault, never log or commit them, and use placeholders like `<SOURCE_API_KEY>`
  in documentation and sample requests.
</Warning>

## Parameters

| Field                                                                                       | In   | Type    | Required | Notes                                                                                  |
| ------------------------------------------------------------------------------------------- | ---- | ------- | -------- | -------------------------------------------------------------------------------------- |
| `storefrontId`                                                                              | path | integer | Yes      | Storefront ID                                                                          |
| `sourceId`                                                                                  | path | string  | Yes      | Inventory source ID within the storefront                                              |
| `accountIdentifier`                                                                         | body | string  | Yes      | Unique account identifier at the source (1–255)                                        |
| `auth`                                                                                      | body | object  | No       | Source credentials. Required for API key / JWT sources; omit for OAuth sources         |
| `auth.type`                                                                                 | body | enum    | —        | `api_key` (also `bearer`, `apikey`) or `jwt`                                           |
| `auth.token`                                                                                | body | string  | —        | Required when `type` is `api_key`                                                      |
| `auth.privateKey`, `issuer`, `subject`, `keyId`, `scope`, `tokenEndpointUrl`, `audienceUrl` | body | string  | —        | Required when `type` is `jwt`. Optional: `algorithm` (`ES256`, `RS256`), `environment` |
| `marketplaceAccount`                                                                        | body | boolean | No       | Admin-only. When `true`, creates a marketplace account instead of a client account     |

## Response

`201 Created`. For API key / JWT sources, the credential is active immediately:

```json theme={null}
{
  "id": "722",
  "accountIdentifier": "acme-brand-account",
  "status": "ACTIVE",
  "registeredBy": "user@acme.com",
  "createdAt": "2026-06-01T10:00:00Z"
}
```

For OAuth sources, the response includes an `oauth` block — visit `authorizationUrl` to complete consent, then refresh the storefront to confirm `connected: true`:

```json theme={null}
{
  "id": "723",
  "accountIdentifier": "acme-brand-account",
  "status": "PENDING",
  "registeredBy": "user@acme.com",
  "createdAt": "2026-06-01T10:00:00Z",
  "oauth": {
    "authorizationUrl": "https://idp.example-publisher.com/oauth/authorize?client_id=...&state=pending_abc123",
    "storefrontId": 42,
    "sourceId": "src_main",
    "sourceName": "Premium CTV — Direct"
  }
}
```

| Field               | Type           | Notes                                                                                         |
| ------------------- | -------------- | --------------------------------------------------------------------------------------------- |
| `id`                | string         | Credential record ID                                                                          |
| `accountIdentifier` | string         | The buyer's account identifier at the source                                                  |
| `status`            | string         | Credential status (`ACTIVE`, or `PENDING` for OAuth)                                          |
| `registeredBy`      | string \| null | Who registered the credential                                                                 |
| `createdAt`         | string         | ISO 8601 timestamp                                                                            |
| `oauth`             | object         | Present only for OAuth sources — `authorizationUrl`, `storefrontId`, `sourceId`, `sourceName` |

## Errors

* `400 VALIDATION_ERROR` — missing `accountIdentifier`, or `auth` missing required fields for the source's auth type.
* `401 UNAUTHORIZED` — missing or invalid bearer token.
* `404 NOT_FOUND` — the storefront or source does not exist or is not visible to the caller.

See [Errors](/v2/reference/errors) for the full error contract.

## Related

<CardGroup cols={2}>
  <Card title="Storefront tasks" href="/v2/buyer/storefronts/tasks" icon="list-check">
    All storefront operations
  </Card>

  <Card title="Get storefront" href="/v2/buyer/storefronts/tasks/get-storefront" icon="magnifying-glass">
    Confirm connected: true after registering
  </Card>

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

  <Card title="Storefront object guide" href="/v2/object-guides/storefront" icon="store">
    OAuth flow and the seller side
  </Card>
</CardGroup>
