Skip to content
B2B · Authentication

Bearer keys

Every B2B call carries a Bearer key in the Authorization header. Keys map to a tenant, a rate-limit tier, and an audit log. No anonymous access to the gated catalog routes from outside our own origin.

Header shape

Authorization: Bearer rxk_<32-char-suffix>

Keys are prefixed rxk_ for grep-ability across logs + source repos. The opaque suffix is generated server-side from a CSPRNG. Treat the key as a credential — never check it into git, never expose it client-side.

What 'authenticated' means here

The gate (requireB2BOrSession) accepts four kinds of callers — only the first is in scope for partners:

  • B2B bearer (you): Authorization: Bearer rxk_…. Middleware validates the key, attaches your tenant context, and runs rate-limit accounting. Route handlers see readB2BContext(req) populated.
  • Better-Auth session cookie: our own consumer web + mobile apps. Not a path partners use.
  • First-party SSR shared secret: X-Rarix-Internal-Key header for server-to-server fetches between apps/web and apps/api. Not a path partners use.
  • Same-origin anonymous: logged-out users browsing rarix.app public pages, native mobile RN fetch. Not a path partners use (cross-origin without a bearer 401s).

401 challenge

Missing / invalid bearer + cross-origin request → 401 with a standard challenge:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="rarix", scope="v1"
Content-Type: application/json

{
  "error": "unauthenticated",
  "message": "This endpoint requires either a Bearer rxk_... API key or a logged-in session. Mint a B2B key at /v1/admin/b2b-keys."
}

The WWW-Authenticate header is the RFC-7235 challenge so curl + standard HTTP clients print the right hint. The body is JSON for app-level inspection.

Key rotation

Rotation today is manual — email b2b@rarix.appwith the key ID (the prefix-stripped first 8 chars of the suffix) and we’ll mint a replacement and revoke the old one. Self-serve rotation is on the v2 roadmap.

What's audited

Every B2B-authenticated request lands in an audit log row keyed on (api_key_id, tenant_name, route, status, timestamp). Audit logs are partner-readable via GET /v1/admin/b2b-keys/:id/audit (your own keys only). Used for usage analytics + abuse detection.