# Credentials

> Managed connections to external services: OAuth accounts, API keys, and MCP servers.

**URL:** https://inference.sh/docs/secrets/credentials
**Last updated:** 2026-10-15

---

Managed connections to external services: OAuth accounts, API keys, and MCP servers.

---

## Credentials vs. secrets

The [vault](https://app.inference.sh/vaults) holds both, and they solve different problems:

| | Credentials | Environment secrets |
|--|-------------|---------------------|
| What | Managed connections (OAuth sign-ins, provider API keys, MCP authorizations) | Raw encrypted key-value pairs |
| Lifecycle | The platform refreshes tokens and tracks status | You paste and rotate values yourself |
| Best for | Google, Slack, Atlassian, model providers, MCP servers, and API keys for any service | Values that belong to no service |

Both live inside a workspace's vaults. Every workspace has a default vault, and workspaces can create more to organize connections by project or environment.

The credentials tab groups them by **company**, the organization behind the service. Under Google you see each way to connect: your account sign-in (`google`), a service account (`google-sa`), a Gemini API key (`google-gemini`). Each of those is an **auth provider**, named by its credential slug, the key apps and MCP servers ask for.

---

## Connection scope

Every credential has a scope that decides who can use it:

| Scope (API) | Who can use it | Who can create it |
|-------------|----------------|-------------------|
| **only you** (`user`) | Only you, in the workspace where you connected it | Anyone |
| **workspace** (`team`) | Everyone in the workspace | Workspace admins |
| **org** (`org`) | Every workspace in the organization | Org admins |

MCP server authorizations default to **only you** (`user`) scope: connecting Atlassian, for example, authorizes *your* account, and results follow *your* permissions in the external service. Another member can never act through your personal connection; the runtime refuses it.

Shared (workspace or org) connections are the fallback for service accounts: connect once with `--as team` or `--as org` from the CLI, or from the connection page as an admin. When both exist, a personal connection takes precedence over a shared one.

After connect, workspace admins (and the connecting user for their own connections) can change scope from the vault **credentials** tab or with [`PUT /credentials/{provider}/scope`](/docs/api/rest/credentials#change-connection-scope). MCP connections pass `?identifier=<server_url>`.

Several OAuth accounts can coexist for the same provider. The first login is the default; run-time resolution and `GET /credentials/{provider}` without `identifier` use your personal login when you have one, otherwise the workspace default. API lookups that name an account accept the stable `account_id` or the display label (`account_identifier`); prefer `account_id` when both are on the credential row. On the vault **credentials** tab, the default account appears in the table; open the provider page (or follow **+N more**) to see every login, change the default, or **connect another account**. See [Multiple accounts per provider](/docs/api/rest/credentials#multiple-accounts-per-provider) and [Credential detail page](/docs/credentials/overview#credential-detail-page).

One boundary worth knowing: a personal connection belongs to you **in that workspace**. Switching to another workspace means connecting again there. Your live grants never leak across workspaces.

---

## OAuth applications (client id and secret)

Many OAuth providers sign users in through an **OAuth application** you register with the service (client id, client secret, and sometimes signing secrets or bot tokens). That app is separate from anyone's connected account: the platform stores app keys on an app row, and each member's login is a different credential.

Before the first connect, a workspace may need its own app keys when neither the organization nor the platform has configured one yet. **Workspace admins** add or update the app from the provider page in the vault (or with [`PUT /credentials/{provider}/app`](/docs/api/rest/credentials#configure-oauth-app)). Other members who try to connect before an app is ready are asked to contact a workspace admin. When several apps exist, logins use the workspace's app first, then the organization's, then the platform's. The provider page shows which one applies.

A provider whose app is set up but that nobody has connected yet shows in the vault as **OAuth app set up, not connected yet**, with a connect button. This includes MCP servers: once a server's OAuth app or a login exists, the server appears in the credentials tab, and connect takes you to the server's page.

---

## Connecting

- **Web**: open the service under [connectors](https://app.inference.sh/mcps) or the [vault](https://app.inference.sh/vaults) and click connect; OAuth happens in your browser. When authorization finishes, you return to the page where you started (path and query string), including if consent opened in another tab. Finish within about 10 minutes, or start connect again — see [After OAuth in the web app](/docs/credentials/overview#after-oauth-in-the-web-app).
- **CLI**: `belt credentials connect <provider>` for OAuth, API-key providers, and service accounts; `belt mcp connect <slug>` for MCP servers; `belt secrets set … --provider` or `belt secrets attach` when you already have the value in the vault. `belt creds` is an alias for `belt credentials`.

Apps declare the credentials they need under `credentials:` in their `inf.yml`, keyed by credential slug, with capabilities for OAuth access. At run time the platform injects the matching credential, choosing by scope and precedence: your own, then the workspace's, then the org's. If nothing is connected, the run tells you what to connect, or asks for the API key right there. See [Declaring credentials](/docs/extend/credentials).

---

## API keys for providers we don't list

Adding an API key doesn't require the platform to know the provider. In **add credential → API key**, type the provider's name. The picker offers to add it as your own provider, and you can give its website. The key is saved as a credential for that provider, with its logo taken from the website.

Apps that declare the provider under `credentials:` find the key there, and so does every later key for the same provider.

## Attaching an existing secret

A key saved as a plain secret can become a provider's credential without re-entering it. On the vault's **secrets** tab, the link icon opens **attach to a provider**: pick or type the provider and choose who can use it. The secret keeps its key name, so apps read it the same way.

From the CLI, link without re-entering the value:

```bash
belt secrets attach GRAFANA_API_KEY grafana
belt secrets attach GRAFANA_URL grafana --as team    # two keys, one credential
belt secrets attach ACME_API_KEY acme --provider-name "Acme CRM" --provider-website acme.com
```

The broken-link icon on an attached secret detaches it back to a plain secret. CLI: `belt secrets detach <key>`. API: `PUT /secrets/{key}/provider` in the [Secrets API](/docs/api/rest/secrets#attach-a-secret-to-a-provider).

---

## Disconnecting

**Disconnect your account** removes your OAuth tokens (or service-account material) and deletes the credential row. It does not touch the OAuth **app** credentials (`client_id`, `client_secret`, signing secrets, and similar keys from the provider's BYOK form): those live on a separate app row, for example a platform-managed Slack app or keys you saved for an [auth provider](/docs/api/rest/auth-providers) of your own. Remove an app with [`DELETE /credentials/{provider}/app`](/docs/api/rest/credentials#remove-app), which is refused while logins still use it. Reconnecting after expiry updates the same credential row: new tokens and scopes, same id and vault membership, and the OAuth **app** keys on the app row stay in place.

---

## Security

Credentials are encrypted at rest, never logged, injected only at runtime into apps that declare them, and revocable at any time from the vault. Revoking on our side does not revoke the grant at the provider — do both when offboarding.

---

## API and SDK references

- [Credentials REST API](/docs/api/rest/credentials): connect, list, and check requirements.
- [JavaScript SDK: credential types](/docs/api/sdk-javascript#generated-types-for-rest-integrations): `CredentialDTO`, `CredentialConfigDTO`, and related constants in `@inferencesh/sdk`
- [Python SDK: generated types](/docs/api/sdk-python#generated-types-inferenceshtypes): `CredentialDTO`, `CredentialConfigDTO`, `CredentialGrant`, `CredentialScope`
