Authentication¶
The b'nerd API supports two authentication methods: Bearer tokens (for CLI, Terraform, and scripted access) and session cookies (for browser / dashboard clients). Both grant access to the same API surface.
JWT bearer tokens (interactive sessions)¶
JWT tokens are short-lived and tied to a specific user account. Use them for interactive sessions in the CLI, or scripts that can refresh tokens.
Obtain a token¶
# 1. Create an account (first-time only)
curl -X POST https://api.bnerd.cloud/create-account \
-H "Content-Type: application/json" \
-d '{
"login": "you@example.com",
"name": "Your Name",
"password": "...",
"password-confirm": "...",
"organization_name": "ACME Corp"
}'
# => {"success":"An email has been sent to you with a link to verify your account"}
# 2. Verify your email, then log in
curl -X POST https://api.bnerd.cloud/login \
-H "Content-Type: application/json" \
-d '{"login": "you@example.com", "password": "..."}' -i
# => Authorization: eyJhbGciOiJIUzI1NiJ9...
The Authorization response header contains your JWT. Use it in subsequent requests:
Browser / dashboard clients¶
When you log in via the dashboard, the API also sets two cookies:
_hq_session— anHttpOnly; Securecookie carrying the session JWT, inaccessible to JavaScript (XSS-safe)._hq_csrf— a readableSecurecookie with a random CSRF token for double-submit protection.
The dashboard reads _hq_csrf and sends it as X-CSRF-Token on every mutating request (POST, PUT, PATCH, DELETE). You do not need to manage these cookies manually — the browser and dashboard handle them automatically.
Static API tokens (machine-to-machine)¶
Static tokens are long-lived, org-scoped tokens intended for CI/CD pipelines, the Terraform provider, and automated scripts. They do not expire on their own and are created and revoked through the dashboard or API.
Static tokens carry the same Bearer prefix:
Creating a token¶
- Go to Account (top-right menu) → Settings → API Tokens (
/account/tokens). - Enter a Token name and the Scopes your automation needs, comma-separated (e.g.
dns:read, rgw_users:*). At least one scope is required. - Click Create token.
- Copy the token value from the dialog — it is shown only once and cannot be retrieved after you close the dialog.
Alternatively, create a token via the API (requires an active JWT/cookie session):
curl -X POST https://api.bnerd.cloud/tokens \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{"token": {"name": "ci-deploy", "scopes": ["dns:read", "projects:read"]}}'
# 201 → data.token contains the raw value (shown once only)
Revoking a token¶
In the dashboard, go to Account → Settings → API Tokens, find the token by name and last-4 characters, and click Revoke.
Via the API:
curl -X DELETE https://api.bnerd.cloud/tokens/$TOKEN_ID \
-H "Authorization: Bearer $JWT"
# 204 No Content
Scoping¶
Static tokens are scoped to an organization. Requests made with a static token operate as if the token owner's permissions apply within that organization. Fine-grained write operations (e.g. quota and lock changes on RGW users) still require admin-level permissions on the organization — a static token issued for a member-role account cannot escalate privileges.
Which token to use¶
| Situation | Auth method | CSRF required |
|---|---|---|
| Dashboard (browser) | Session cookie (automatic) | Yes — handled by dashboard |
b'nerd CLI (bnerd) | JWT bearer (bnerd auth login) | No |
| Terraform provider | Static API token | No |
| CI/CD pipelines | Static API token | No |
| Scripted automation | Static API token | No |
Bearer-authenticated requests (CLI, provider, static tokens) are never subject to CSRF checks. Only cookie-authenticated mutations require X-CSRF-Token.
For the full technical contract — token claims, CSRF rules, error codes — see API: Authentication & Tokens.
Multi-organization accounts¶
An account can belong to more than one organization. If you have been invited into a second (or third) organization and accepted the invitation, you need to tell the API which organization each request targets:
# List projects in a specific organization
curl "https://api.bnerd.cloud/projects?organization_id=$ORG_ID" \
-H "Authorization: Bearer $TOKEN"
The ?organization_id query parameter is mandatory for any account that holds more than one membership. Requests without it are rejected with 403 Forbidden — the server never silently picks one for you. Accounts with a single membership can omit the parameter.
Switching active organization¶
Use GET /accounts/me to see all your memberships and determine the current context:
The response includes memberships[] (all organizations you belong to) and current_organization_id (the org resolved for this request). Switch by supplying a different ?organization_id on the next request.
The dashboard org-switcher and bnerd org switch (CLI) persist your active organization choice client-side and inject the parameter automatically on every request.
Joining an additional organization¶
An organization admin sends an invitation to your email address. The accept flow does not require authentication:
# 1. Inspect the invitation
curl "https://api.bnerd.cloud/invite/{token}"
# 2. Accept — your account gains a new membership immediately
curl -X PATCH "https://api.bnerd.cloud/invite/{token}/accept"
After accepting, GET /accounts/me returns the new membership in memberships[].
Unauthenticated endpoints¶
A small number of endpoints are public (no token required):
GET /invite/{token}— show an invitation by tokenPATCH /invite/{token}/accept— accept an invitation by tokenPATCH /invite/{token}/decline— decline an invitation by tokenGET /invitations/details?token=...— look up invitation details
All other endpoints return 401 Unauthorized when no valid token is provided.