BricqsBricqs
Documentation

Authentication

Bricqs has two credential types with a hard boundary between them: long-lived API keys that live only on your server, and short-lived participant tokens (JWTs) that are the only credential allowed in a browser or mobile app. The SDK enforces the boundary: it refuses to run with a bq_live_ or bq_test_ key client-side.

Auth
All endpoints require an X-API-Key header. Production keys are prefixed bq_live_; sandbox keys bq_test_.
Scopes
Participant key Participant tokens carry read:state and write:events by default: they read their OWN participant's data (requests for another participant_id return 403) and emit events pinned to their own identity.
Admin scope API keys are minted in the dashboard (Settings, API Keys). The default scopes are events:write plus gamify:read: emit events and read any participant's data. Add gamify:write at mint for value movement, and admin or gamify:admin for destination management and token minting.
Base URLhttps://api.bricqs.co/api/v1/gamify

Credential types

CredentialHeaderLivesDefault scopes
API key (bq_live_ / bq_test_)X-API-KeyServer only. Never in a bundle, never in a browser.events:write, gamify:read
Participant token (JWT)Authorization: BearerBrowser / mobile. Minted server-side, expires in minutes.read:state, write:events

The bq_test_ prefix resolves to your isolated test sibling tenant; bq_live_ to production data. Same API, fully separated data.

API-key scopes

Scopes are chosen when you mint the key. A default-minted key covers the standard integration loop (emit events, read state). Value movement is always an explicit grant.

ScopeGrantsIn default?
events:writeEmit events (POST /gamify/events and batch), generate referral codes.Yes
gamify:readRead any participant’s state, points, badges, tier, streaks, rewards, leaderboards, plan.Yes
gamify:writeValue movement: award/deduct points, assign tiers, award badges, record streaks, claim rewards, create/update participants.No, grant explicitly
admin / gamify:adminEverything, plus webhook destination management and participant-token minting.No, grant explicitly
POST/api/v1/auth/participant-token
Admin scope

Mint a short-lived participant JWT. Requires an ADMIN-scoped API key (a default key cannot mint tokens). Call it from your backend, never from the browser, and hand only the returned token to the client.

Request body
FieldTypeDescription
participant_idrequiredstrYour stable user identifier. Upserts the participant profile on mint.
display_nameOptional[str]Shown on leaderboards and feeds.
emailOptional[str]Stored on the participant profile.
external_idOptional[str]Secondary identifier from your system.
attributesOptional[dict]Custom metadata merged into the profile.
expires_in_minutesintToken TTL. Clamped server-side to 1..60. Default: 5
scopesOptional[list[str]]Token scopes. Omit for the default. Default: ["read:state", "write:events"]
// app/api/bricqs-token/route.ts (Next.js Route Handler)
import { mintParticipantToken } from '@bricqs/sdk-server';

export async function GET() {
  const { token, expiresAt } = await mintParticipantToken({
    adminApiKey: process.env.BRICQS_ADMIN_API_KEY!, // admin-scoped, server env only
    participantId: 'user_123',                      // your stable user ID
    expiresInMinutes: 30,
  });
  return Response.json({ token, expiresAt });
}
Response fields
FieldTypeDescription
tokenstrThe signed participant JWT. Pass to BricqsProvider as participantToken (or return it from a getToken callback).
participant_idstrEcho of the minted identity.
tenant_idstrYour tenant id.
expires_atdatetimeAbsolute expiry. Re-mint before this; there is no refresh token.
# The key is a standard bq_live_... key; what makes it "admin" is the
# admin (or gamify:admin) scope granted when it was created.
curl -X POST https://api.bricqs.co/api/v1/auth/participant-token \
  -H "X-API-Key: bq_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "participant_id": "user_123", "expires_in_minutes": 30 }'

Troubleshooting: 401 vs 403

401 means the credential itself is missing or invalid. 403 means the credential is valid but not allowed to do this. Every error body carries the standard envelope with a stable error.code and a request_id for support.

Errors
StatusCodeWhen it fires
401AUTH_UNAUTHENTICATEDNo credential supplied, or the participant JWT is expired. Re-mint the token.
401AUTH_API_KEY_INVALIDThe X-API-Key value is malformed, revoked, or belongs to no tenant.
403AUTH_FORBIDDENAPI key lacks the required scope for this route (gamify:write on value movement is the most common miss), OR a participant token requested another participant's data (pin mismatch).
403STREAM_PARTICIPANT_MISMATCHSSE stream opened for a participant_id that does not match the token subject.
403STREAM_SCOPE_MISSINGSSE stream opened with a token minted without read:state.

Rules that keep you safe

  • API keys are server environment variables. Never NEXT_PUBLIC_, never in source, never in a mobile binary.
  • The browser gets a participant token only. The SDK rejects bq_live_/bq_test_ values client-side by prefix, but do not rely on that as your only defense.
  • Mint tokens with the shortest TTL your UX tolerates (default 5 minutes, max 60) and refresh via a getToken callback.
  • Mint keys with the fewest scopes the service needs. One key per service makes rotation a per-service operation; keys show last_used_at in the dashboard so you can confirm cutover before revoking.
  • Value movement (gamify:write) belongs to backend services only; no integration path moves value from a browser.

Next steps