BricqsBricqs

Gamification architecture

Bricqs is an event-driven engagement engine. Events come in, facts are produced, the rules engine decides what changes — points, tiers, badges, challenge progress, contest scores, webhooks. This page is the working mental model for everything you build on top of the platform.

Last updatedMay 2026

Key takeaways

Quick read
  • Everything is tenant-scoped. Tenants own participants, programs, rewards, and API keys.
  • Events are the universal input. POST one event, the rules engine fans it out to challenges, contests, points, streaks, and webhooks.
  • Facts are the immutable middle layer. They are how progression and contests stay consistent under retries.
  • Progression entities (points, tiers, badges, streaks) are passive calculators. They do not emit events; they react to facts.
  • The same event can update points, score a contest, and progress a challenge at the same time. You do not need to call three endpoints.

The model

Five core entities

Tenant

The brand or environment. Owns API keys, programs, participants, rewards. Every request is scoped to one tenant.

Participant

An end-user identity. Created automatically on first event or first explicit registration. Carries points, tier, streaks, challenge progress.

Event

Something a participant did. quiz_submitted, purchase_completed, custom.foo. Sent via REST or SDK.

Fact

An internal, deduplicated record of an event after validation. The rules engine reads facts; everything downstream operates on them.

Program

Anything that consumes facts: a challenge, a contest, a points rule, a streak, a leaderboard window. Configured once, evaluated continuously.

Event flow

From POST to progression

Every Bricqs integration moves through this sequence. Knowing the order helps debug everything.

text
Client (web, mobile, server)
  │
  │  POST /api/v1/ingest/events
  │  { participant_id, event_type, attributes, idempotency_key }
  │
  ▼
Ingestion (the event buffer)
  │  Validates schema, rate limits, dedupes by idempotency_key
  │
  ▼
Fact Bridge
  │  Persists Fact (immutable). Triggers ChallengeRulesEngine.
  │
  ├──▶ Challenge Rules Engine   updates objective progress, completes if threshold met
  ├──▶ Contest Scoring Service  scores entries, updates the in-memory ranked store
  ├──▶ Points Engine            grants points per earn rule
  ├──▶ Streak Service           extends or breaks streak based on grace
  └──▶ Outbound Webhooks        signs and delivers HMAC-signed payload

A single event can update progression, score a contest, advance a challenge, and trigger a webhook. You do not need to call multiple endpoints.

Separation of concerns

What lives where

The most common mistake is trying to make a passive entity emit events. Keep this table next to your build.

EntityRoleEmits events?Reads facts?
Engagement (quiz, spin, scratch)Active. The participant performed an action.Yes (e.g. quiz_submitted)No
ChallengeReactive. Watches facts to advance objectives.Sometimes (challenge_completed)Yes
ContestReactive. Scores facts inside a window.Sometimes (contest_completed)Yes
PointsPassive calculator. Earns and spends are derived from facts.NoYes
TierPassive calculator. Computed from cumulative points or value.NoYes
BadgePassive calculator. Awarded when condition is met.NoYes
StreakReactive. Advances on each qualifying fact in window.NoYes
WebhookOutbound. Delivers signed events to your stack.NoYes
Default rule:Rule of thumb: if the entity is something the user did, it emits. If it is a calculator that scores, awards, or completes, it reads facts.

A worked example

One event, four updates

A user finishes a fitness quiz with a perfect score. You POST one event. Behind the scenes, here is what changes.

POST /api/v1/ingest/events·json
{
  "participant_id": "p_8a3f",
  "event_type": "quiz_completed",
  "attributes": {
    "quiz_id": "q_fit_basics",
    "score": 100,
    "time_seconds": 42
  },
  "idempotency_key": "p_8a3f:q_fit_basics:2026-04-30"
}

Points engine

Earn rule fires: 'quiz_completed with score=100' grants 50 points. Participant balance updated atomically.

Challenge rules engine

30-day fitness challenge has objective 'finish 5 quizzes'. Counter increments to 3 of 5.

Contest scoring service

Quiz contest is active. Entry created, score 100 added to the ranked store, leaderboard recomputed.

Outbound webhook

If your tenant has a webhook for points.granted, an HMAC-signed POST goes to your endpoint within 60 seconds.

Idempotency

Why every event needs a key

Networks fail. Clients retry. Webhooks redeliver. Without an idempotency key, retries double-credit the user. With one, the second POST short-circuits at ingestion and the participant sees one fact, one points grant, one contest entry.

text
Recommended format:
  participant_id : event_subject : period

Examples:
  p_8a3f : q_fit_basics : 2026-04-30
  p_8a3f : checkout_complete : order_4271
  p_8a3f : streak_tick : 2026-04-30

Rules:
- Same key inside 24 hours = duplicate, ignored.
- Different attributes with same key = first write wins.
- 200 OK with duplicate: true on the response.

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.