Access tokens
VAIF Studio has two kinds of routes, and they take different credentials:
| Plane | Examples | Credential |
|---|---|---|
| Data plane: what your app calls | /v1/data/{projectId}/{table}, storage, function invokes, realtime, /projects/{projectId}/auth/* (your app’s users) |
A project API key (API keys), plus the app user’s access token as Authorization: Bearer when they are signed in |
| Control plane: managing projects | /projects/* administration, /schema-engine/*, /functions/* management, /billing/* |
A console access token: Authorization: Bearer <token> for a signed-in VAIF Studio user |
An API key sent to a control-plane route is refused with 403 SCOPE_INSUFFICIENT.
Get a console access token
Section titled “Get a console access token”With the CLI
Section titled “With the CLI”vaif login signs you in through the browser and saves the token in ~/.vaif/auth.json (the token field), readable only by you. The CLI refreshes it when it is close to expiring.
Without a browser
Section titled “Without a browser”For CI, scripts and AI agents, POST /auth/cli/login with { "email", "password" } returns a CLI token:
curl -X POST https://api.vaif.studio/auth/cli/login \ -H "Content-Type: application/json" \ --data '{"email":"you@example.com","password":"your-password"}'The answer is one of:
{ "ok": true, "accessToken", "refreshToken", "expiresIn", "user" }: you’re signed in.expiresInis the token’s lifetime in seconds.{ "ok": true, "mfaRequired": true, "challengeToken", "expiresInSeconds" }: your account has two-factor authentication. Send the code from your authenticator app toPOST /auth/mfa/verifywith{ "challengeToken", "code" }to get the token.
If your organization requires single sign-on for your email domain, a password sign-in is refused with 403; sign in with vaif login instead.
Give the token to the CLI in one of two ways:
- Set
VAIF_AUTH_TOKENin the environment. Every command uses it instead of~/.vaif/auth.json, and it is never saved, printed or refreshed. - Save it with
vaif login --token < token.txt.
See Console API for agents and CI for more.
Call the API
Section titled “Call the API”TOKEN=$(jq -r .token ~/.vaif/auth.json)PROJECT_ID="your-project-id"
# Run SQL against the project (several statements are fine)curl -X POST https://api.vaif.studio/schema-engine/query/$PROJECT_ID \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ --data '{"sql":"SELECT table_name FROM information_schema.tables WHERE table_schema = current_schema();"}'
# Apply a schema definitioncurl -X POST https://api.vaif.studio/schema-engine/apply \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ --data '{ "projectId": "'$PROJECT_ID'", "definition": { "schemaVersion": "1.0", "tables": [{ "name": "posts", "columns": [ { "name": "id", "type": "uuid", "primaryKey": true }, { "name": "title", "type": "text", "nullable": false } ] }] } }'POST /schema-engine/preview takes the same body as apply and shows the changes without making them.
With the SDK
Section titled “With the SDK”import { createVaifClient } from "@vaifstudio/client";
const vaif = createVaifClient({ baseUrl: "https://api.vaif.studio", accessToken: process.env.VAIF_ACCESS_TOKEN,});
// Your Verament sessions in a projectconst { sessions } = await vaif.copilot.listSessions("your-project-id");console.log(sessions.length);accessToken can also be a function that returns the current token, so a long-running process can refresh it.
Errors
Section titled “Errors”| Code | When | What to do |
|---|---|---|
TOKEN_MISSING |
No Authorization header |
Sign in |
TOKEN_INVALID |
Bad signature or malformed token | Sign in again |
TOKEN_EXPIRED |
The token expired | vaif login, or refresh |
SCOPE_INSUFFICIENT |
An API key on a control-plane route, or a token for another project | Use a console access token |
PROJECT_DEACTIVATED |
The project is deactivated | See Project deactivation |
RATE_LIMITED |
Too many requests | Wait Retry-After seconds |
The full list is in Error codes. @vaifstudio/client exports the codes as the VaifErrorCode type.