Skip to content

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:

curl https://api.bnerd.cloud/accounts/me \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..."

Browser / dashboard clients

When you log in via the dashboard, the API also sets two cookies:

  • _hq_session — an HttpOnly; Secure cookie carrying the session JWT, inaccessible to JavaScript (XSS-safe).
  • _hq_csrf — a readable Secure cookie 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:

curl https://api.bnerd.cloud/projects \
  -H "Authorization: Bearer bnerd_tok_..."

Creating a token

  1. Go to Account (top-right menu) → SettingsAPI Tokens (/account/tokens).
  2. Enter a Token name and the Scopes your automation needs, comma-separated (e.g. dns:read, rgw_users:*). At least one scope is required.
  3. Click Create token.
  4. 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:

curl https://api.bnerd.cloud/accounts/me \
  -H "Authorization: Bearer $TOKEN"

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 token
  • PATCH /invite/{token}/accept — accept an invitation by token
  • PATCH /invite/{token}/decline — decline an invitation by token
  • GET /invitations/details?token=... — look up invitation details

All other endpoints return 401 Unauthorized when no valid token is provided.