Permissions (Scopes)
Every API key, and every app you connect to your Nosana account, carries a set of permissions, also called scopes. A request can only do what its permissions allow. A key that can view your credits can't post a job or spend them.
When you sign in to Nosana Deploy yourself, you aren't limited: your own session always has every permission.
Available permissions
| Permission | Allows | API keys | Apps & MCP |
|---|---|---|---|
credits:read | View your credit balance, transactions and spending history | ✓ | ✓ |
inference:use | Run LLM inference (spends credits) | ✓ | — |
jobs:read | Read the status, results and endpoints of jobs you've run | ✓ | ✓ |
jobs:write | Create, extend and stop jobs (spends credits) | ✓ | ✓ |
deployments:read | View your deployments | ✓ | ✓ |
deployments:write | Create, update and delete your deployments (spends credits) | ✓ | ✓ |
wallet:sign | Sign messages with your Nosana wallet key | ✓ | ✓ |
api-keys:manage | Create, view and revoke your API keys | ✓ | — |
oauth-apps:manage | Manage the OAuth apps you own | ✓ | — |
Three permissions are for API keys only:
inference:use: the inference endpoints only accept API keys.api-keys:manageandoauth-apps:manage: an app that could create API keys could keep access to your account after you disconnect it.
WARNING
wallet:sign lets its holder sign messages as your wallet. The SDK uses it to reach your running jobs directly on their node, and that includes stopping them (see Manage an Active Job). Only grant it to keys and apps you trust with that. To read job data without it, use jobs:read (Read Job Data).
To build a permission picker of your own, fetch the current list from GET https://api.nosana.com/auth/scopes. No key is needed. Each entry's oauthGrantable flag tells you whether apps can use it.
API keys
Choose a key's permissions when you create it:
- In the dashboard, tick Read and Write for each resource in the Create API Key dialog (see Get API Key).
- With the SDK or over HTTP, pass a
scopesarray:
const created = await client.api.user.apiKeys.create({
name: 'read-only-monitoring',
scopes: ['credits:read', 'jobs:read', 'deployments:read'],
});
console.log('New key:', created.key);Good to know:
- No
scopesmeans everything you have. A key created withoutscopesgets every permission of whoever creates it. - A key restricted to LLM models (
llmModels) gets onlyinference:useby default. - A key can't hand out more than it has. A key with
api-keys:managecan only create keys with permissions it holds itself (403otherwise). An unknown scope name is a400. - Permissions can't be changed later. To change them, create a new key and revoke the old one.
- Keys created before permissions existed have full access.
To see what a key can do, call client.api.auth.validateApiKey(key) (POST /auth/validate-api-key). Its response includes the key's scopes.
Apps and MCP
Apps that use Connect with Nosana, and AI assistants connected to the MCP server, act on your behalf with an access token. That token carries only the permissions you approved:
- When an app is registered (Account → Connected Apps), its owner chooses the most it can ever ask for.
- When someone signs in, the app asks for some or all of those permissions. By default the Connect SDK asks for everything the app was registered with. Pass
scopesto ask for less (see Choose what your app can do). - The consent screen lists what the app is asking for. The user approves or declines the whole request.
When a permission is missing
A request without the permission it needs is rejected with 403 Forbidden:
{
"message": "Insufficient scope. This endpoint requires: jobs:write.",
"code": "INSUFFICIENT_SCOPE"
}The WWW-Authenticate header names the missing permission in a machine-readable form:
WWW-Authenticate: Bearer error="insufficient_scope", scope="jobs:write"To fix it, create a key that includes the permission, or sign in to the app again and approve the permission it asks for.