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.
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 prefix | Scope | Use for | Where it lives |
|---|---|---|---|
| bq_live_admin_... | Admin | Configuration, reporting, server-side scoring, minting participant tokens. | Server only. Never in client code. |
| bq_live_part_... | Participant | End-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. |
Sending the key
Bearer header on every request
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"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.
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
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
Putting the admin key in NEXT_PUBLIC_ env. Now it is in the JS bundle.
Server-only env (BRICQS_ADMIN_KEY, no NEXT_PUBLIC_ prefix). Mint short-lived participant tokens for client code.
Reusing the same key across test and live. Test traffic pollutes production reports.
Use bq_test_ keys against the test tenant. Assert the env on every server boot.
Hardcoding the key in source. It ends up in git history.
Always read from env. Use a secret manager (AWS, Vault, Doppler). Add the key to your scrubbed-from-logs list.
Sharing one admin key across many services. When one leaks, all of them rotate.
One key per service. Tag keys by service name. Rotation becomes a per-service operation.
Ignoring 429s in clients. Spikes turn into outages because retries pile up.
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.
