Skip to main content
Browsary exposes multiple authentication layers so humans can use cookies in the dashboard while services rely on scoped API keys. Several endpoints also demand email verification or completed two-factor authentication (2FA). Use this page as your decision tree before jumping into the reference.

Session cookies

  • CreatePOST /api/auth/login with { email, password, remember }. When remember is true, a long-lived JWT is written to the token cookie. Otherwise the cookie lasts for the current browser session.
  • Check statusGET /api/auth returns status plus the decoded JWT payload when signed in. Responses include email_not_verified and 2fa_required states so you can prompt users accordingly.
  • InvalidateGET /api/auth/logout wipes the cookie.

Email verification workflow

Some endpoints call auth({ requireEmailVerification: true }), which means unverified accounts will be rejected with HTTP 400. Use the following flow:
  1. POST /api/auth/verify/request while signed in. Optionally include returnUrl to control where the CTA in the email sends users.
  2. Users receive a JWT-backed link. Send the token to POST /api/auth/verify/submit.
  3. On success, the API replies with { status: "ok", token } and refreshes the token cookie.

Password reset workflow

  1. POST /api/auth/reset/request with { email, returnUrl? }. Browsary emails a short-lived JWT.
  2. POST /api/auth/reset/submit with { token, password, confirmPassword }. The response mirrors the login response and refreshes the cookie.

Two-factor authentication

All 2FA endpoints require an email-verified session.
EndpointPurpose
POST /api/auth/2fa/enable/requestReturns { status: "2fa_setup", url, secret }. url is a TOTP URI you can encode as a QR code.
POST /api/auth/2fa/enable/submitConfirms the authenticator by sending { token } (the current TOTP). Response refreshes the cookie.
POST /api/auth/2fa/verifyCalled after login when the API reported 2fa_required.
POST /api/auth/2fa/resetRevokes the previous secret after the user proves ownership with the current TOTP code.

API keys

  • Endpoints – CRUD lives under /api/api-keys and /api/api-keys/{id}.
  • Delivery – send keys via x-api-key or Authorization: ApiKey <value>. Authorization: Bearer <value> also works if your tooling only supports bearer schemes.
  • ScopesaccessType controls what the key can see:
    • full: inherits the owner’s permissions.
    • projects: allow list of project IDs or slugs provided via projectIds.
    • custom: supply explicit permission strings (e.g. marketing.pipelines.read).
  • Lifecycle – the API only shows the full secret on creation; subsequent reads expose metadata plus the prefix.
Remember that the project middleware re-evaluates permissions on every call. If you revoke a key, its future project requests fail automatically.

External provider linking

OpenID Connect providers defined in OPENID_PROVIDERS unlock an external account linking flow:
  1. GET /api/auth/external/providers lists supported providers (google, github, etc.).
  2. Signed-in users call GET /api/auth/external/{provider}/init, which redirects them to the provider and stores PKCE state in cookies.
  3. The provider calls back into GET /api/auth/external/{provider}/redirect. Browsary either links the provider to the signed-in user, logs in the existing linked account, or redirects to /auth/external-register/<token> to finish onboarding.
  4. Use GET/DELETE /api/auth/external/{provider} to inspect or unlink accounts.

Shared-secret integrations

Some system-level endpoints use dedicated middleware instead of user identity:
  • Coordinator – all /api/coordinator/<token>/* routes require token === process.env.COORDINATOR_TOKEN.
  • External sessions/api/external-session and /api/external-session/{id}/capture require Authorization: Bearer <EXTERNAL_TOKEN> or a ?token= query string.
Treat these secrets like infrastructure credentials—rotate them when compromised and never embed them in public clients.