VibeHost
Guides

Personal access tokens

Long-lived bearer tokens for CI and external integrations. Scoped per resource group, scoped per workspace.

PATs are how non-browser, non-OAuth callers authenticate against the VibeHost API. CI pipelines, custom scripts, integrations that can't run an OAuth dance — they all use PATs.

PATs are created and managed from the dashboard only. The PAT management API itself is browser-session-only (denyPAT: true), so a PAT cannot mint more PATs — limiting blast radius if one leaks.

Create a PAT

Open vibehost.com/account/tokensCreate token. The dashboard asks for:

  • Name — identifies the token in audit logs and the token list.
  • Scopes — pick the minimum (see below). Leave empty for full-access (equivalent to the dashboard session).
  • Resources — optionally restrict to specific app IDs.
  • Expiry — 30, 60, 90, 365 days, or never.

The plaintext token (vh_pat_…) is shown exactly once on creation. The server only stores sha256(plaintext); there is no recovery. Copy it to your secrets manager immediately.

Scopes

Scope names follow <resource>:<verb>. Pick the minimum. The full list (from packages/shared/src/pat-scopes.ts):

ScopeWhat it unlocks
apps:readRead app metadata, list deployments, read logs
apps:writeCreate / rename / delete apps
apps:deployUpload deploy artifacts, promote, rollback (the most common CI scope)
domains:readList custom domains
domains:writeAdd + verify + remove custom domains
env:readList environment variables
env:writeSet + remove environment variables
members:readList team + workspace members and per-app grants
members:writeInvite + remove members, add + remove per-app grants
billing:readRead current plan + usage
workspace:readRead workspace settings
workspace:writeUpdate workspace settings

Notes:

  • No billing:write — billing mutations (subscribe, change plan, cancel) go through Stripe-hosted checkout, which re-authenticates against Stripe directly. Long-lived API tokens shouldn't bypass that.
  • apps:deploy is a distinct scope from apps:write because deploying is the most common CI action and is materially different from create/rename/delete.
  • PATs created with empty scopes are full-access — equivalent to the dashboard session. Restrict by picking specific scopes.

A PAT for "GitHub Actions that deploys my-app to production" typically needs only apps:deploy + apps:read, restricted to that specific app. Less surface area = smaller blast radius if leaked.

Scoped PATs are env-gated during rollout. If SCOPED_PAT_ENFORCEMENT_ENABLED is off on your instance, the API returns SCOPED_PAT_DISABLED when you try to create a scoped (non-full-access) PAT. On api.vibehost.com this is enabled. Self-hosters flip the env var once they've audited their PAT-callable surface (see Hard Rule #14).

Resources

The "resources" field restricts a PAT to a specific set of resource IDs:

{
  "apps": ["app_abc123", "app_def456"]
}

A token with that resources field can only act on those two apps. Calls to other apps return 403 TOKEN_RESOURCE_MISMATCH.

v1 only enforces the apps key. domains and env keys are accepted in the schema for forward-compat but don't gate yet.

Workspace + team binding

Every PAT is bound to one workspace at issue time — the workspace you were in when you clicked Create. Calls to URLs under a different workspace return 403 TOKEN_WORKSPACE_MISMATCH.

Similarly, a PAT can optionally be team-bound. Calls to URLs under a different team return 403 TOKEN_TEAM_MISMATCH.

(These are the documented exceptions to Hard Rule #8 — the token holder already knows their token's bound scope, so the 403 code reveals nothing an attacker without the token could learn.)

Use a PAT

curl -H "Authorization: Bearer vh_pat_..." \
  https://api.vibehost.com/api/v1/workspaces/<id>/apps

Or with the CLI:

export VIBEHOST_TOKEN=vh_pat_...
vibehost app list

The CLI reads VIBEHOST_TOKEN if set; otherwise it uses the device-flow token in ~/.config/vibehost/config.json.

Rotation

PATs don't auto-rotate. Recommended:

  1. Create a new PAT with the same scopes + resources.
  2. Roll your secrets manager / CI to the new PAT.
  3. Revoke the old PAT after one deploy cycle confirms the new one works.

Revoking is dashboard-only too — open vibehost.com/account/tokens, click Revoke on the row. Revoked PATs immediately stop authenticating, but the row survives for audit (with deletedAt set).

Audit

Every PAT-authenticated request lands in the audit log with the PAT's id and name. View at vibehost.com/account/audit.

If you suspect a leak, revoke immediately, then review the audit log for unexpected actions.

See also

On this page