BricqsBricqs

API auth and keys

Bricqs uses tenant-scoped API keys with two scopes: participant (for end-user actions) and admin (for configuration and reporting). This page covers the key model, environment separation, rate limits, and rotation.

Reading time6 minutes
Last updatedMay 2026

Key takeaways

Quick read
  • Two scopes: participant for end-user actions, admin for configuration and reporting.
  • Two environments: bq_test_ and bq_live_. Never mix.
  • Server-only. Never ship admin keys to the browser. Mint short-lived participant tokens for client code.
  • Rate limits are per-key. Default 1000 requests per minute per API key, 5000 per tenant.
  • Rotate quarterly or on personnel change. Old keys remain valid until you revoke them.

The model

Two scopes, two environments

Key prefixScopeUse forWhere it lives
bq_live_admin_...AdminConfiguration, reporting, server-side scoring, minting participant tokens.Server only. Never in client code.
bq_live_part_...ParticipantEnd-user actions when the SDK is not in use (mobile, partner platforms).Server only. Mint short-lived JWTs for client use.
bq_test_admin_...Admin (test)Same as live admin, against the test tenant.Server only.
bq_test_part_...Participant (test)Same as live participant, against the test tenant.Server only.
Default rule:There is no public, browser-safe API key. The browser uses short-lived participant tokens minted by your server.

Sending the key

Bearer header on every request

curl·bash
curl https://api.bricqs.co/api/v1/gamify/state/p_8a3f \
  -H "Authorization: Bearer bq_live_admin_aV7p..." \
  -H "X-Bricqs-Tenant: tenant_brand_xyz"
lib/bricqs.ts (server-only)·ts
const BRICQS_API = "https://api.bricqs.co/api/v1";

export async function bricqs<T>(
  path: string,
  init: RequestInit = {}
): Promise<T> {
  const res = await fetch(`${BRICQS_API}${path}`, {
    ...init,
    headers: {
      "Authorization": `Bearer ${process.env.BRICQS_ADMIN_KEY!}`,
      "X-Bricqs-Tenant": process.env.BRICQS_TENANT!,
      "Content-Type": "application/json",
      ...init.headers,
    },
    cache: "no-store",
  });
  if (!res.ok) throw new Error(`Bricqs ${res.status}: ${await res.text()}`);
  return res.json();
}

Participant tokens

Short-lived JWTs for client code

Browsers and mobile apps never see the raw API key. They use short-lived participant tokens minted server-side.

POST /auth/participant-token·bash
curl -X POST https://api.bricqs.co/api/v1/auth/participant-token \
  -H "Authorization: Bearer bq_live_admin_..." \
  -H "Content-Type: application/json" \
  -d '{
    "participant_id": "p_8a3f",
    "ttl_seconds": 3600,
    "scopes": ["read:state", "submit:events"]
  }'

# response
{
  "token": "eyJhbGciOi...",
  "expires_at": "2026-04-30T11:42:00Z"
}

The token is bound to one participant id. It can read their state and submit events on their behalf, nothing more.

Rate limits

What the limits are and how to handle them

Per-key limit

1000 requests per minute, sliding window. Returns 429 with a Retry-After header when exceeded.

Per-tenant limit

5000 requests per minute, aggregate across all keys. Designed to absorb spike events without saturating any single key.

Burst limit

100 requests per second per key. Useful headroom for fanout (sending events for many participants in a tight loop).

Ingestion specifics

POST /events has a higher limit and is preferred over multi-call sequences. Use batch endpoints when sending more than 50 events at once.

Backoff strategy

On 429: respect Retry-After, then exponential backoff with jitter (250ms, 500ms, 1000ms, capped at 5s). Most clients handle this automatically.

Headers to inspect

X-RateLimit-Remaining and X-RateLimit-Reset are returned on every response. Cheap to log; useful when debugging spikes.

Rotation

Rotate keys quarterly and on personnel change

text
Recommended cadence:
- Rotate quarterly as a baseline.
- Rotate immediately when an engineer with key access leaves the team.
- Rotate immediately if a key is suspected to have leaked.

Process:
1. Create a new key in the dashboard. The old key remains valid.
2. Roll the new key out across all environments and services.
3. Verify usage of the old key has dropped to zero (dashboard reports this).
4. Revoke the old key. The dashboard logs the revoke event.

Tip: Bricqs supports tagging keys (e.g. "ingestion-server", "scoring-worker").
Tags make it obvious which service is using which key during rotation.

Common mistakes

The mistakes that leak keys

01Mistake

Putting the admin key in NEXT_PUBLIC_ env. Now it is in the JS bundle.

Fix

Server-only env (BRICQS_ADMIN_KEY, no NEXT_PUBLIC_ prefix). Mint short-lived participant tokens for client code.

02Mistake

Reusing the same key across test and live. Test traffic pollutes production reports.

Fix

Use bq_test_ keys against the test tenant. Assert the env on every server boot.

03Mistake

Hardcoding the key in source. It ends up in git history.

Fix

Always read from env. Use a secret manager (AWS, Vault, Doppler). Add the key to your scrubbed-from-logs list.

04Mistake

Sharing one admin key across many services. When one leaks, all of them rotate.

Fix

One key per service. Tag keys by service name. Rotation becomes a per-service operation.

05Mistake

Ignoring 429s in clients. Spikes turn into outages because retries pile up.

Fix

Respect Retry-After. Exponential backoff with jitter. Most SDKs handle this automatically; verify your homemade clients do.

Developer FAQ

Common questions when integrating gamification with Bricqs.

Ready to ship?

Wire it up with the Bricqs SDK or API

Headless SDK for React UIs, REST API for any backend. Same engine behind both.

1 brief to align the room2 mechanics max in version one
What happens next
01
Pick the mechanic
Choose the smallest working system for the brief.
02
Launch without rebuilds
Configure rules and rewards in one place.