# Credentials Overview

> Managed connections to external services.

**URL:** https://inference.sh/docs/credentials/overview
**Last updated:** 2026-10-31

---

Managed connections to external services.

---

## Overview

Credentials are managed connections to external services. Instead of manually copying tokens, you authenticate through OAuth or service-specific flows.

---

## Available Credentials

### Google

Two options for Google services:

| Credential | Services | How it works |
|-------------|----------|--------------|
| **[Service Account](/docs/credentials/google-service-account)** | Sheets, Docs, Drive | Share files with a dedicated email |
| **[OAuth](/docs/credentials/google-oauth)** | Gmail, Calendar, personal Drive | Sign in with your Google account |

### GitHub

| Credential | Services | How it works |
|-------------|----------|--------------|
| **[GitHub App](/docs/credentials/github-app)** | Repositories, pull requests, issues, checks; triggers on repository events | Install the inference shell GitHub App on your account or organization |

### Slack

| Credential | Services | How it works |
|-------------|----------|--------------|
| **[OAuth (BYOK)](/docs/credentials/slack)** | Messages, Channels, Events | Use your own Slack app |

### Discord

| Credential | Services | How it works |
|-------------|----------|--------------|
| **[OAuth (BYOK)](/docs/credentials/discord)** | Messages, Servers, Bot Events | Use your own Discord bot |

### X.com (Twitter)

| Credential | Services | How it works |
|-------------|----------|--------------|
| **[OAuth (BYOK)](/docs/credentials/x)** | Tweets, Users, Timelines | Use your own X Developer app |

### Google Cloud Platform

| Credential | Services | How it works |
|-------------|----------|--------------|
| **[GCP (BYOK)](/docs/credentials/gcp)** | Vertex AI, BigQuery, Cloud Storage, Pub/Sub | Connect your own GCP project |

### Microsoft 365

| Credential | Services | How it works |
|-------------|----------|--------------|
| **[OAuth (BYOK)](/docs/credentials/microsoft)** | Outlook, OneDrive, Teams, Calendar | Use your own Azure app registration |

### Notion

| Credential | Services | How it works |
|-------------|----------|--------------|
| **[OAuth (BYOK)](/docs/credentials/notion)** | Pages, databases, workspace content | Use your own Notion integration |

### Salesforce

| Credential | Services | How it works |
|-------------|----------|--------------|
| **[OAuth (BYOK)](/docs/credentials/salesforce)** | Leads, accounts, opportunities, cases | Use your own Salesforce connected app |

### Reddit

| Credential | Services | How it works |
|-------------|----------|--------------|
| **[OAuth (BYOK)](/docs/credentials/reddit)** | Posts, comments, subreddits, messages | Use your own Reddit app |

### Claude Code

| Credential | Services | How it works |
|-------------|----------|--------------|
| **[Subscription token](/docs/integrations/claude-code-subscription)** | `anthropic/claude-code-*` models for agents | Paste a `claude setup-token` token from your Claude Pro or Max plan |

---

## Credential Types

| Type | Description | Example |
|------|-------------|---------|
| **OAuth** | Sign in and authorize access | Google OAuth |
| **OAuth (BYOK)** | Use your own app credentials | Slack, Discord, X.com |
| **Service Account** | Dedicated email you share resources with | Google Service Account |
| **Cloud (BYOK)** | Connect your own cloud provider project | GCP Vertex AI, BigQuery |

### Per-user vs workspace connections

Some OAuth providers use **managed credentials** configured by the platform (`has_managed: true` on `GET /credentials/configs`). The `grant` field on that config controls whether connections are shared or personal:

| `grant` | Who connects | Button label |
|---------|--------------|--------------|
| *(omitted)* | One OAuth account for the whole workspace | **connect {name}** |
| `credentials` | Each workspace member connects their own account | **connect your {name} account** |
| `token` | Platform provides ready-to-use access for the workspace | **connect {name}** |

When `grant` is `credentials`, your connection is scoped to you (`scope: "user"` in the API). Apps and agents run with your authorized account, not a shared workspace account. Other members must connect separately from **vaults → credentials**.

The credentials list shows the connected account in its **account** column. A user-scoped connection is disconnected from its detail page with **disconnect your account**, and the confirmation explains that only your personal account is affected.

#### Platform-managed keys at run time

When your workspace has not connected a required provider, a run may receive a platform key for that gap only. Platform keys are credentials with API `scope: "platform"`: vendor keys inference.sh operates, not personal logins of the platform workspace or its members.

Each platform key has an access list that decides which other workspaces' runs may use it: which apps and functions, store-reviewed versions only, on inference.sh **cloud** infrastructure only. Private infrastructure and unreviewed app versions never get a platform key.

A run resolves each credential in this order:

1. Secrets passed with the task itself
2. Your own login (`user`)
3. The workspace default (`team`)
4. The organization's (`org`)
5. A platform key, if its access list admits the run

When no platform key admits the run, the requirement stays unmet and the run is refused as missing it (HTTP **412**, for example "add your {name} key to use this app"). Add your own key for that provider.

### Multiple accounts on one provider

You can connect more than one account for the same OAuth provider (for example two Google mailboxes on one workspace). The first connection becomes the **default**; apps and agents that do not name an account use the first connected default on the ladder: your personal login, then the workspace's, then the org's and platform keys. A disconnected or expired personal login does not block a connected workspace key. Connect another account from the provider page with **connect another account**, or use `another_account: true` on [`POST /credentials`](/docs/api/rest/credentials#connect-a-credential). MCP servers are different: each server URL is its own connection under the provider `mcp` (the server URL is its `account_identifier`), not another account on a shared slug.

The platform tracks each login by the provider's stable **account id** (not just the email or handle shown in the UI). Account lists and disconnect confirmations show the label; API calls that name a specific login use `account_id` when one is known. Reconnecting after you change your display name updates the label on the same login instead of creating a duplicate; signing in as a different person with a similar label still adds a separate account.

→ [Credentials API — managed credentials and grant type](/docs/api/rest/credentials#managed-credentials-and-grant-type) · [Multiple accounts per provider](/docs/api/rest/credentials#multiple-accounts-per-provider)

### Credential scope

The **vaults → credentials** table has a **scope** column that shows who can use each connected credential:

| App label | API `scope` | Meaning |
|-----------------|-------------|---------|
| **only you** | `user` | Only you can use this credential |
| **workspace** | `team` | Shared with everyone in this workspace |
| **org** | `org` | Shared with all workspaces in the organization |
| **everyone** | `platform` | A platform key inference.sh provides. Other workspaces' runs use it only when its access list admits them ([platform keys at run time](#platform-managed-keys-at-run-time)) |

There is no separate **agent** scope. Agents use the same vault logins and resolution order as apps.

Scope is chosen when you connect. Admins and the connecting user can change it later from the **scope** badge on the vault **credentials** tab (or on an MCP server's **sharing** dialog). Inherited org and platform credentials stay read-only in member workspaces.

Workspace admins, org admins, and platform admins get a scope choice at connect time:

- Clicking **Connect** on an OAuth provider opens a **choose who can use this credential** dialog with the options the role allows.
- Adding an **API key** shows a **who can use it** selector with the same options.

Other members connect with the provider's default scope: `user` for MCP servers and per-user OAuth (`grant: "credentials"`), `team` otherwise.

On the [credential detail page](#credential-detail-page), an inherited credential (`org` or `platform` scope) shows a **managed by platform** or **managed by your organization** banner. **disconnect** is hidden because the workspace does not own it. When the provider config has `allows_byok: true`, the banner offers **use your own key** so the workspace can override the shared credential with its own.

→ [Credentials API: connection scope](/docs/api/rest/credentials#connection-scope)

### What is BYOK?

**Bring Your Own Key (BYOK)** means you create your own app/bot in the service's developer portal and use those credentials. This gives you:

- **Isolated events** — only receive events from your workspaces/servers
- **Full control** — configure permissions, webhooks, and triggers yourself
- **Your rate limits** — not shared with other users
- **Custom branding** — your bot name and avatar
- **Your billing** — for cloud providers like GCP, use your own quotas and billing

---

## Security

| Feature | Benefit |
|---------|---------|
| **Token encryption** | OAuth tokens encrypted at rest |
| **Auto-refresh** | We handle token expiration |
| **Granular permissions** | Request only the scopes you need |
| **Revocable** | Disconnect anytime from **vaults** |

---

## Using in Apps

Apps declare credential requirements:

```yaml
# inf.yml
credentials:
  - key: google.sheets
    description: Read sales data from Google Sheets

  - key: slack.channels.write
    description: Send notifications to Slack

  - key: gcp.vertex_ai
    description: Use Vertex AI models (Gemini, etc.)

  - key: x.tweet.write
    description: Post automated updates
    optional: true
```

When you run the app:

1. We check if you have the required credential connected
2. If not, you'll be prompted to connect it
3. Once connected, credentials are injected automatically

In a multi-function app, a function can declare only the credentials it uses. The connect prompt then asks for just the access that function needs. See [Per-function credentials](/docs/extend/credentials#per-function-credentials).

---

## Connecting Credentials

Open **Vaults** in the web app ([`/vaults`](https://app.inference.sh/vaults)), select the **default** vault, and open the **credentials** tab.

This tab manages OAuth, BYOK, and service-account credentials (Google, Slack, GCP, and similar). Workspace admins can click **add credential** to connect an OAuth account, save an API key, add an environment variable, or add an MCP server. **MCP server** opens the add dialog on [`/my/mcps?add=1`](https://app.inference.sh/my/mcps?add=1). MCP servers are also listed on the web app's **Mcps** page ([`/my/mcps`](https://app.inference.sh/my/mcps)) and under **Explore → MCP servers**, and `belt mcp connect <slug>` connects one from the CLI. After you connect an MCP server, it appears in `belt credentials list` and on this page alongside catalog credentials (`GET /credentials/configs` returns the merged catalog and connection state, including connected MCP rows).

### Standard OAuth (Google)

1. Open the credential from the list, or go directly to its [detail page](#credential-detail-page) (for example `/credentials/google`)
2. Click **Connect**
3. When the provider lists OAuth **capabilities**, choose which permissions to grant (see [Choosing permissions before sign-in](#choosing-permissions-before-sign-in))
4. Complete the OAuth flow — you return to the page where you clicked **Connect** (see [After OAuth in the web app](#after-oauth-in-the-web-app))
5. Done!

From the CLI, `belt credentials connect google` starts the OAuth flow. Google Sheets/Docs/Drive also offers a [service account](/docs/credentials/google-service-account) connection; connect it in the web app at `/credentials/google-sa` or with `belt credentials connect google-sa`.

### BYOK Credentials (Slack, Discord, X.com)

1. Create an app in the service's developer portal
2. Configure OAuth redirect URLs and permissions
3. Click **Configure** and enter your credentials
4. Click **Connect** to authorize
5. Done!

### GCP WIF Credentials

1. Configure Workload Identity Federation in your GCP project
2. Create a service account with required permissions
3. Click **Configure** and enter your project details
4. Click **Connect** to verify
5. Done!

See the [GCP Setup Guide](/docs/credentials/gcp) for detailed instructions.

### Credential detail page

Each credential type has its own detail page at `/credentials/{slug}`. Open it from the credentials tab or link directly:

```
https://app.inference.sh/credentials/google
https://app.inference.sh/credentials/google-sa
https://app.inference.sh/credentials/gcp
```

Use the `slug` from `GET /credentials/configs` (for example `google` for Google OAuth, `google-sa` for the Sheets/Docs/Drive service account, `gcp` for GCP WIF/BYOK, `slack` for Slack). Provider names are globally unique — Google OAuth uses `google`, the managed service account uses `google-sa`, and GCP WIF uses `gcp`.

**When not connected**, the page shows setup steps and a connect button — **connect your {name} account** when the provider uses per-user managed OAuth (`grant: "credentials"`, for example **connect your X account**), otherwise **connect {name}**.

**When disconnected** (a key login whose keys are not saved yet), the detail page shows the setup steps for the missing keys. An agent run that needs a provider you have not connected asks in the chat; it does not add an empty row to the vault. The credentials list shows each login's status (`disconnected`, `expired`, `error`) so you can spot broken connections without opening each provider.

**When connected**, the page lists every login you can use for that provider (one row per account). The default account is listed first; when there are several, it shows a **default** badge and a short note that apps and agents use the default unless they name another account.

Each account row shows:

- **Identifier and display name** (for example email or username)
- **Who can use it** — change scope from the row when you manage the connection (same options as [Credential scope](#credential-scope))
- **When it was connected**
- **Permissions** — granted OAuth scopes (the first six; a **+N** badge folds the rest)

Use the row menu (⋯) to **make default** (non-default accounts only), **reconnect** (expired or errored accounts), **add permissions** on that account, **copy account** (the `account_identifier` value), or **disconnect**. Inherited platform or org credentials hide the menu. Disconnect confirms whether you are removing a personal or workspace account; if you disconnect the current default while other accounts remain, the confirmation names which account becomes the new default.

When the provider distinguishes accounts (each login has an `account_identifier`), **connect another account** opens the [permission picker](#choosing-permissions-before-sign-in) when the provider has capabilities, then starts OAuth with the provider's account picker (`another_account` on [`POST /credentials`](/docs/api/rest/credentials#connect-a-credential)) so you can sign in with a different login without replacing the first. The button appears only for OAuth providers that are not inherited and already have at least one connected account.

#### Choosing permissions before sign-in

For OAuth providers that list **capabilities** ([`GET /credentials/capabilities`](/docs/api/rest/credentials#capabilities-catalog)), **connect {name}** and **connect another account** open a dialog before the provider's consent screen, with a checkbox per capability. Sign-in scopes are always included; more can be granted later with **add permissions** on an account row. On a first connect the capabilities start unchecked. For another account, the ones the existing account holds start checked. **Reconnect** skips the dialog and re-authorizes with the account's current scopes, and providers with no capabilities go straight to OAuth.

#### Permission grant links

A link can ask for specific permissions: `https://app.inference.sh/credentials/google?grant=https://www.googleapis.com/auth/gmail.send`. Repeat `grant` for each scope. A value may be the provider's own scope name or one of its [`scope_aliases`](/docs/api/rest/auth-providers#authorize-and-token-oauth2) (`gmail.send`); the page resolves aliases to the provider's names before comparing with the login's `scopes`. If every requested scope is already granted, the page says so instead of opening the grant. Add `close=1` to close the tab once the sign-in lands, for a page opened in a new window.

On **vaults → credentials**, the **account** column shows the login runs use (the one [`GET /credentials/configs`](/docs/api/rest/credentials#credential-configs) puts first in `accounts`). When more than one login exists for a provider, a **+N more** link opens that provider's detail page for the full list.

**When expired or errored**, if token refresh fails or credentials are revoked, the page shows a warning badge (`expired` or `error`) and a banner:

- **Credentials expired** — reconnect to restore access (refresh token missing or expired, for example after you revoked access in the provider's settings)
- **Connection error** — the platform could not refresh credentials (provider outage, invalid grant, or similar)

When the API returns an `error_message`, it appears in the banner. Click **reconnect** to start the OAuth flow again. It is the same flow as connecting, with previously granted scopes included in the OAuth consent screen. Account info and permissions stay visible so you can see what was previously connected. The credential id in the API and in agent configs that reference it does not change — reconnect refreshes tokens and scopes on the same row. Use **disconnect** to remove the broken connection entirely.

Apps and agents that require an expired, errored or missing credential fail at validation (`POST /credentials/check`, or **412** from `POST /run` or an agent message) with a reconnect or setup prompt; they do not run with empty credentials. In the web app, a refused run opens a setup dialog whose credential entries link to the provider's credential page (**set up {name} in credentials**), which returns you to the run once the provider is set up.

### After OAuth in the web app

When you start OAuth from a page in the web app (vault, a credential detail page, **Explore → MCP servers**, **My MCP servers**, an app setup step, or a missing-permissions prompt), authorization sends you back to that same URL — including any query string (for example `/my/mcps?add=1`).

Finish authorization within about **10 minutes**. The API's OAuth state and PKCE verifier expire then, and a late callback fails with **400** `invalid_grant` ("authorization link expired — try again"): start connect again. When a flow has no starting page to return to, you land on a default page: the provider's [credential detail page](#credential-detail-page), [**My MCP servers**](https://app.inference.sh/my/mcps) for MCP OAuth, or the [vault](https://app.inference.sh/vaults) when there is no provider-specific page.

If the provider opens the consent screen in another browser tab or window, you can finish authorization there: the flow is kept in the browser's storage, shared across tabs, so the callback completes and returns you to your starting page.

The CLI does not use this browser return URL; `belt credentials connect` and `belt mcp connect` finish in the terminal (or print a URL in non-interactive mode).

Use direct links in setup flows, emails, or custom UIs when you know which credential type a user needs to connect or manage. Look up `slug` from `GET /credentials/configs`. → [Credentials API — check requirements](/docs/api/rest/credentials#check-requirements-pre-flight)

---

## Next

→ [Google Service Account](/docs/credentials/google-service-account)  
→ [Google OAuth](/docs/credentials/google-oauth)  
→ [Google Cloud Platform](/docs/credentials/gcp)  
→ [Slack](/docs/credentials/slack)  
→ [Discord](/docs/credentials/discord)  
→ [X.com](/docs/credentials/x)  
→ [Microsoft 365](/docs/credentials/microsoft)  
→ [Notion](/docs/credentials/notion)  
→ [Salesforce](/docs/credentials/salesforce)  
→ [Reddit](/docs/credentials/reddit)  
→ [Claude Code subscription](/docs/integrations/claude-code-subscription)
