Agents build and run; they never hold a production secret. Production values go from Vibiz straight into the app's host. Only a person, the owner, can read them, and only to paste them into a host outside Vibiz. Agents and laptops work against a separate development environment that holds none of production's data.
The keys
| Key | Looks like | Held by | Can |
|---|---|---|---|
| Agent key | vz_sk_…, access: agent | the CLI, the MCP server, CI | create projects, deploy, promote, run actions, send email, use AI, read usage, get the development env, everything in development. Never the production env, keys, removing a domain or live money |
| Owner key | vz_sk_…, access: owner | a person, rarely | all of the above, plus the production env, keys, removing domains, connecting hosts, live refunds and withdrawals |
| Console session | a cookie | a person signed in at app.vibiz.app | the access of their account: whoever opened the account is its owner |
| App key | vz_app_… (VIBIZ_APP_KEY) | the running app | its own project and environment only: env, AI, actions, email, events, payments for its users |
| Project AI key | vz_ai_… | the app (VIBIZ_AI_API_KEY) | the AI gateway, billed to the project |
New keys are agent keys unless an owner asks otherwise:
vibiz keys create growth-agent # an agent key, shown once
vibiz keys create ci --owner # an owner key (owner keys only)
vibiz keys revoke key_…curl https://app.vibiz.app/v1/api-keys -H "Authorization: Bearer $OWNER_KEY" \
-H 'content-type: application/json' -d '{"name":"growth-agent","access":"agent"}'
# → 201 { "id": "key_…", "secret": "vz_sk_…", "access": "agent", … } the secret is returned onceName a key per person or agent: usage breaks down by key (vibiz usage --by api_key).
Keys and environments
- Agent key (
vz_sk_…, accessagent): what the MCP server and the CLI usually hold. Builds and runs: projects, deploys, actions, AI, usage, the development env, everything in development. Never a production secret, never live money: production refunds, cancels, withdrawals, payment settings, keys, removing domains and connecting hosts answer403 owner_only. The fix forowner_onlyis a person: the owner does it in the console (or with an owner key), not a retry. - Owner key (access
owner): all of that plus production secrets, keys, removing domains and connecting hosts. Rarely given to agents. - App key (
vz_app_…,VIBIZ_APP_KEY): the running app's one secret, per environment.
Development env (vibiz_dev_env, vibiz dev): its own database branch with the app's tables and no production rows, its own sign-in (trusts http://localhost:3000), its own AI key, and VIBIZ_WEBHOOK_SECRET once a development webhook is set. write_to puts the values in an env file without showing them.
The project id: ./vibiz.json { "project_id": "prj_…" } in a linked app folder, or vibiz_project_status for the list. Read it instead of asking the user.
Environments
Every project has two environments. env (or --dev in the CLI) picks one; it defaults to production for owner keys and development for agent keys.
| production | development | |
|---|---|---|
| Database | the real one | a branch with the same tables and no rows |
| Sign-in | real users; trusts the live domains | its own users; trusts http://localhost:3000 |
| AI | the project's key | a second key, billed to the project |
| Payments | live money, 7-day hold | test mode, test cards, no hold, simulate |
| Company | a real filing, real fees | nothing filed, nothing charged, simulate |
| Who | owner for secrets and money | anyone on the account, agents included |
Hosting, analytics, replay and email have no development copy (a local run shouldn't count as visits or send mail from the live address).
vibiz dev # create it once and write .env.development.local (names printed, values not)
vibiz dev -- npm run dev # pass the values to a command, no file
vibiz dev --reset # throw the copy away; the next `vibiz dev` branches againOver HTTP: POST /v1/projects/:id/dev (create, 202), GET /v1/projects/:id/dev (status: none | provisioning | ready | failed), GET /v1/projects/:id/dev/env (the values, 409 until ready), DELETE /v1/projects/:id/dev.
Getting the production env to the app
- Vibiz hosting: automatic. Every key is pushed to the host and kept in sync.
- A connected host: the owner connects Vercel, Netlify, Render, Railway, Fly.io, Heroku, Cloudflare Workers or Pages, or GitHub Actions once (
vibiz hosts add <host> <app>); Vibiz writes the env there whenever it changes, rotations included. Vercel is verified live; the others are in beta. - One key, any host: put only
VIBIZ_APP_KEYin the host and load the rest at boot.
import { vibiz } from '@vibiz/app';
await vibiz.loadEnv(); // the app's env into process.enveval "$(curl -fsS -H "Authorization: Bearer $VIBIZ_APP_KEY" \
https://app.vibiz.app/v1/app/env?format=shell)" && exec node server.jsGET /v1/app/env?format=json|dotenv|shell|docker. Before any of these, the app's domain is added (vibiz domains add app.example.com --elsewhere; an agent key may, and sign-in then trusts it once its TXT record proves it or the owner confirms it) so sign-in and analytics accept it. The project needs no Vibiz hosting at all: any one service works alone (Use one service).
The app key
- One per project and environment, put in that environment's env with
VIBIZ_API_URL. A development key reads only the development env, and its events are not recorded. - It works only for its own project: account routes answer
401. - Rotate with
vibiz app-key rotate(production needs an owner). The new key is pushed to Vibiz hosting and every connected host; the old one keeps working for a day by default (--grace <seconds>,0ends it now). The new secret is never printed.
What agents can and can't do
| Agent key | Owner key | |
|---|---|---|
| Projects, deploys, actions, AI, email, usage | yes | yes |
| Development env values | yes | yes |
Production env values (GET /projects/:id/env) | names only (?names=1) | yes |
| Add the app's domains | yes (sign-in trusts one once its TXT record proves it) | yes |
| Create or revoke keys, remove domains, connect hosts | no | yes |
| Rotate the production app key | no | yes |
An agent hitting an owner route gets 403 forbidden with details.reason: "owner_only" and details.next_step, the console step to tell the person. Retrying with the same key never works.
Errors
| Code | Status | When | Next step |
|---|---|---|---|
unauthorized | 401 | missing, unknown or revoked key; an app key on an account route | check VIBIZ_API_KEY / VIBIZ_APP_KEY |
forbidden + owner_only | 403 | an agent key on an owner route | pass details.next_step to the owner |
dependency_not_ready | 409 | the development copy isn't ready yet | poll GET /projects/:id/dev |
not_found | 404 | the project isn't on this account | check ./vibiz.json |