Every project in astilba belongs to an organization, and every request is scoped to one
org resolved from your credential — never from the request itself. Within an org, what you can
do depends on your role, and programmatic access uses org API tokens.
Organizations and roles
Authentication and organizations are handled by Better Auth.
You belong to one or more organizations; a freshly signed-in user’s active organization
defaults to their first membership, so they can immediately work in it.
Three roles matter for the parts astilba exposes today:
| Role | Can |
|---|
| owner | everything, including minting and revoking API tokens |
| admin | manage projects and translations; mint and revoke API tokens |
| member | read and edit translations; list tokens, but not mint or revoke |
Roles are enforced on the server. The dashboard hides controls you can’t use as a
convenience, but the API is the real gate — a request without the role is rejected
regardless of what UI made it.
API tokens
An org API token authenticates a non-interactive client — the CLI, CI, or
any HTTP caller. It carries the org it was minted in, so it reaches every project in that org
by slug (another org’s slug returns 404). It is sent as the x-api-key header; the CLI
reads it from ASTILBA_TOKEN (or --token).
Minting
Mint a token from the dashboard’s Tokens page (owner/admin only). The plaintext key is
shown exactly once — only its hash is stored, so it can never be displayed again. Copy it
immediately.
Programmatically, that’s POST /api/tokens, which requires a session cookie (you manage
tokens from the dashboard, not with another token). The raw Better Auth key routes
(/api/auth/api-key/*) are deliberately blocked so token management always goes through the
role-checked /api/tokens endpoints.
Using a token
export ASTILBA_URL=https://astilba.example.com
export ASTILBA_TOKEN=…
npx astilba pull --project web ./locales
Or as a raw header:
curl -H "x-api-key: $ASTILBA_TOKEN" \
https://astilba.example.com/api/projects/web
Revoking
Revoke from the Tokens page, or DELETE /api/tokens/:id (owner/admin, session-cookie).
Revocation is immediate. Mint a separate token per CI system or developer so you can revoke one
without disrupting the others.
Access-control matrix
| Operation | Endpoint | Who |
|---|
| List tokens | GET /api/tokens | any member |
| Mint a token | POST /api/tokens | owner / admin |
| Revoke a token | DELETE /api/tokens/:id | owner / admin |
| Read / edit translations | /api/projects/* | any member (session or token) |
See the Server HTTP API for the full endpoint list and status codes.