# Keys and scopes

Every API request is authenticated by a key or a user token. The key decides the tenant, the environment and what the request may do.

| Type | Prefix | Sent as | Use |
|---|---|---|---|
| Secret | `vk_live_`, `vk_test_` | `Authorization: Bearer` | Server calls with full access to enabled products |
| Restricted | `rk_live_`, `rk_test_` | `Authorization: Bearer` | Server calls with chosen scopes |
| Publishable | `vpk_live_`, `vpk_test_` | `Vabu-Publishable-Key` | Browsers and apps |
| User token | JWT | `Authorization: Bearer` | A customer or staff member |

## Scopes

Scopes have the form `{product}:{read|write}`, for example `events:read` or `streams:write`. The scope `platform:*` covers keys, webhooks and integrations. A secret key has every scope for the products you have enabled. A restricted key has only the scopes you choose.

A request without the scope gets a `403` `permission_error`. A request for a product that is off gets `403` `product_not_enabled`.

## Principals per endpoint

Each endpoint states which principals it allows. The API reference shows this under each operation.

| Principal | Meaning |
|---|---|
| `secret` | A secret key |
| `restricted:<scope>` | A restricted key that has the scope |
| `publishable` | A publishable key |
| `customer` | A signed-in customer token |
| `member:<permission>` | A staff member with the permission |
| `operator` | Vabu platform staff, on the operator API |

## Which credentials each endpoint takes

Not every endpoint takes every credential. This is how the families split today. Each operation in the [API reference](https://docs.vabu.live/api.md) also lists its own principals.

| Endpoint family | Secret key | Restricted key | Publishable key | Signed-in user | Test mode |
|---|---|---|---|---|---|
| API keys and webhook endpoints | Yes | `platform:read` or `platform:write` | No | Team members with the right role | Yes |
| Customers (`/v1/customers`) | Yes | `customers:read` or `customers:write` | No | Team members with the right role | Yes |
| Access: entitlements and checks | Yes | `access:read` or `access:write` | No | No | Yes |
| Access: open, heartbeat and end a session | Yes | `access:write` (heartbeat and end also take `streams:write`) | Yes, with a [customer token](https://docs.vabu.live/concepts/customer-tokens.md) | No | Yes |
| Streams (`/v1/streams/...`) | Yes | `streams:read` or `streams:write` | Only `POST /v1/streams/playback_tokens`, with a customer token | No | Yes, on a simulated network |
| Public reads: `GET /v1/events`, `GET /v1/events/{event}`, `GET /v1/plus/contents`, `GET /v1/plus/contents/{content}` | Yes | `events:read` or `streams:read` | Yes | Not needed | Yes |
| Vabu ID sign-in (`/auth/v1/...`) | Not needed | Not needed | Optional, to sign in as your customer | Some routes need the access token | Yes |
| Everything else: booking, orders, tickets, organizer, creator, tenant staff and merch routes | Live keys, as before | Live keys, as before | No | Yes, with `X-Tenant-Code` | Not yet |

For the last row, a request is made by a signed-in person (a Vabu ID or Payd ID token) with the tenant in the `X-Tenant-Code` header, or in `Vabu-Tenant` for a Vabu ID token. Some of these routes, such as browsing events and starting a checkout, need only the tenant header and no token. Test keys and publishable keys are refused on routes that do not list them, with `403 test_mode_unavailable` or `403 insufficient_permissions`. The product pages say which routes need what.

## Lifecycle

- **Create.** The full key is shown once. Vabu OS keeps a hash and an 8-character prefix.
- **Track.** Each key records its last use, its creator, an optional expiry and an optional IP allowlist.
- **Roll.** Rolling creates a new key and sets an expiry on the old one: immediately, or up to 7 days later.
- **Revoke.** Revoking takes effect at once, and the change is audited. Your tenant owners get an email if a key was reported as leaked.

Keys are cached for up to 60 seconds for speed, and revocation clears that cache right away.
