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
Two options for Google services:
| Credential | Services | How it works |
|---|---|---|
| Service Account | Sheets, Docs, Drive | Share files with a dedicated email |
| OAuth | Gmail, Calendar, personal Drive | Sign in with your Google account |
GitHub
| Credential | Services | How it works |
|---|---|---|
| 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) | Messages, Channels, Events | Use your own Slack app |
Discord
| Credential | Services | How it works |
|---|---|---|
| OAuth (BYOK) | Messages, Servers, Bot Events | Use your own Discord bot |
X.com (Twitter)
| Credential | Services | How it works |
|---|---|---|
| OAuth (BYOK) | Tweets, Users, Timelines | Use your own X Developer app |
Google Cloud Platform
| Credential | Services | How it works |
|---|---|---|
| GCP (BYOK) | Vertex AI, BigQuery, Cloud Storage, Pub/Sub | Connect your own GCP project |
Microsoft 365
| Credential | Services | How it works |
|---|---|---|
| OAuth (BYOK) | Outlook, OneDrive, Teams, Calendar | Use your own Azure app registration |
Notion
| Credential | Services | How it works |
|---|---|---|
| OAuth (BYOK) | Pages, databases, workspace content | Use your own Notion integration |
Salesforce
| Credential | Services | How it works |
|---|---|---|
| OAuth (BYOK) | Leads, accounts, opportunities, cases | Use your own Salesforce connected app |
| Credential | Services | How it works |
|---|---|---|
| OAuth (BYOK) | Posts, comments, subreddits, messages | Use your own Reddit app |
Claude Code
| Credential | Services | How it works |
|---|---|---|
| Subscription token | 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:
- Secrets passed with the task itself
- Your own login (
user) - The workspace default (
team) - The organization's (
org) - 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. 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 · 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) |
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, 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
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:
1# inf.yml2credentials:3 - key: google.sheets4 description: Read sales data from Google Sheets56 - key: slack.channels.write7 description: Send notifications to Slack89 - key: gcp.vertex_ai10 description: Use Vertex AI models (Gemini, etc.)1112 - key: x.tweet.write13 description: Post automated updates14 optional: trueWhen you run the app:
- We check if you have the required credential connected
- If not, you'll be prompted to connect it
- 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.
Connecting Credentials
Open Vaults in the web app (/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. MCP servers are also listed on the web app's Mcps page (/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)
- Open the credential from the list, or go directly to its detail page (for example
/credentials/google) - Click Connect
- When the provider lists OAuth capabilities, choose which permissions to grant (see Choosing permissions before sign-in)
- Complete the OAuth flow — you return to the page where you clicked Connect (see After OAuth in the web app)
- Done!
From the CLI, belt credentials connect google starts the OAuth flow. Google Sheets/Docs/Drive also offers a 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)
- Create an app in the service's developer portal
- Configure OAuth redirect URLs and permissions
- Click Configure and enter your credentials
- Click Connect to authorize
- Done!
GCP WIF Credentials
- Configure Workload Identity Federation in your GCP project
- Create a service account with required permissions
- Click Configure and enter your project details
- Click Connect to verify
- Done!
See the GCP Setup Guide 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:
1https://app.inference.sh/credentials/google2https://app.inference.sh/credentials/google-sa3https://app.inference.sh/credentials/gcpUse 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)
- 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 when the provider has capabilities, then starts OAuth with the provider's account picker (another_account on POST /credentials) 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), 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 (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 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, My MCP servers for MCP OAuth, or the vault 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
Next
→ Google Service Account
→ Google OAuth
→ Google Cloud Platform
→ Slack
→ Discord
→ X.com
→ Microsoft 365
→ Notion
→ Salesforce
→ Reddit
→ Claude Code subscription