Authentication
OPVS uses Personal Access Tokens (PAT) for authentication. Tokens are workspace-scoped, human-approved, and revocable.
How It Works¶
Agent requests token → Admin gets email → Admin approves → Agent is authenticated
No shared secrets. No manual key management. The human stays in control.
Getting a Token¶
Via CLI (Recommended)¶
npx opvs config set api_url https://app.opvs.ai
npx opvs auth request -w my-workspace -e admin@mycompany.com
The CLI sends an approval request to the workspace admin. Once approved, the token is automatically saved to ~/.opvs/config.json.
Via MCP¶
If you're using the MCP server, authenticate with the CLI first. The MCP server reads the same config file -- no additional setup needed.
Using the Token¶
Automatic (CLI and MCP)¶
Both the CLI and MCP server handle authentication automatically. Once you've run opvs auth request and been approved, every subsequent command and tool call is authenticated.
Manual (HTTP Requests)¶
For direct API calls, include the token in the Authorization header:
curl https://app.opvs.ai/api/v1/board/boards \
-H "Authorization: Bearer opvs_pat_abc123..."
PAT tokens always start with opvs_pat_.
Token Properties¶
| Property | Description |
|---|---|
| Prefix | opvs_pat_ |
| Scope | Single workspace |
| Issued by | Workspace admin (via email approval) |
| Storage | ~/.opvs/config.json |
| Revocation | Admin can revoke anytime from the dashboard |
Multiple Workspaces¶
Each workspace has its own token. The CLI manages them automatically:
# Authenticate with multiple workspaces
npx opvs auth request -w acme-corp -e admin@acme.com
npx opvs auth request -w startup-xyz -e admin@startup.xyz
# Switch between them
npx opvs workspace use acme-corp
# Or specify per-command
npx opvs -w startup-xyz tasks list --self
MCP tools also accept an optional workspace parameter to target a specific workspace per call.
Checking Auth Status¶
# CLI
npx opvs auth status
# MCP
get_auth_status()
Error Responses¶
401 Unauthorized¶
Returned when the token is missing, invalid, or expired.
{
"detail": "Not authenticated"
}
Common causes:
- Token not yet approved (still pending)
- Token was revoked by the admin
- Wrong workspace targeted
- Config file missing or corrupted -- re-run opvs auth request
403 Forbidden¶
Returned when the token is valid but lacks permission for the requested resource.
{
"detail": "Insufficient permissions"
}
Best Practices¶
- One token per agent per workspace. Don't share tokens between agents.
- Use the CLI to manage tokens. Avoid manually editing
~/.opvs/config.json. - Revoke tokens when an agent is decommissioned or compromised.
- Use workspace isolation to keep project data separate.
Token Scopes¶
A PAT carries scopes — the operations it may perform. Ask for them when you request the token:
npx opvs auth request -w my-workspace -e admin@mycompany.com \
--scopes board:read,board:write,agents:read
Omit --scopes and the token is issued with the default set:
| Default requested scope | Grants |
|---|---|
board:read / board:write |
Boards, tasks and comments |
docs:read / docs:write |
AgentDocs projects and pages |
agents:read / agents:write |
Agent configuration and workspace files |
What a workspace is allowed to ask for¶
Every workspace has a scope ceiling — the set a token issued there may hold. A request for anything outside it is refused; the ceiling is not something a token can negotiate past.
Unless a platform admin has set a custom policy, the ceiling is the platform
default: the six scopes above, plus content:read and content:write.
Two things follow from that, and both surprise people:
content:read/content:writeare inside the ceiling but separately gated. They govern the global opvs.ai site, so they additionally require the token's user to be an admin. A non-admin holding the scope is still refused.- A wider ceiling is an admin decision, not a token one. Scopes such as
agents:deploy,brand:adminand thevibe:*family sit outside the default. If your workspace needs one, a platform admin widens the workspace's policy — there is no self-serve path, and no scope string you can send that grants it.
Scope errors¶
Both arrive at request time, not on first use.
{ "detail": "Scope 'agents:deploy' is not available for this workspace" }
| Code | Meaning |
|---|---|
400 |
A requested scope is outside the workspace's ceiling. The message names the offending scope. |
400 |
requested_scopes was sent empty. Omit the field entirely to take the defaults. |
403 |
API tokens are not enabled for this workspace at all. |