BricqsBricqs
Documentation

Gamification API

Server-to-server REST API for adding gamification to any application. Award points, unlock badges, manage tiers, track streaks, and run leaderboards — all via API key authentication.

Bricqs Gamify vs Bricqs Engage: The Gamification API (Bricqs Gamify) is for developers who want full control over the UI and need server-to-server integration. Bricqs Engage uses the visual builder and hosted runtime. Both share the same backend infrastructure.

Authentication

All Gamification API endpoints use API key authentication. Pass your key in the X-API-Key header.

curl -X POST https://api.bricqs.ai/api/v1/gamify/points/award \
  -H "X-API-Key: bq_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"participant_id": "user_123", "amount": 100, "reason": "Purchase completed"}'

Standard API Key

Used for participant-facing operations (awarding points, recording streaks, querying state). Any active API key works.

Admin API Key

Used for definition management (creating badges, tiers, leaderboards). Requires admin or gamify:admin scope on the API key.

Quick Start

A complete gamification flow in four API calls. Participants are auto-created on first interaction — no registration step needed.

1. Award points for an action
curl -X POST https://api.bricqs.ai/api/v1/gamify/points/award \
  -H "X-API-Key: bq_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "participant_id": "user_123",
    "amount": 250,
    "reason": "Completed onboarding",
    "idempotency_key": "onboarding_user123"
  }'

# Response
{
  "transaction_id": "a1b2c3d4-...",
  "participant_id": "user_123",
  "amount": 250,
  "new_balance": 250,
  "tier_upgrade": null
}
2. Award a badge
curl -X POST https://api.bricqs.ai/api/v1/gamify/badges/award \
  -H "X-API-Key: bq_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "participant_id": "user_123",
    "badge_code": "first_steps"
  }'

# Response
{
  "participant_id": "user_123",
  "badge_code": "first_steps",
  "badge_name": "First Steps",
  "rarity": "common",
  "earned_at": "2026-02-14T10:00:00Z",
  "already_earned": false
}
3. Record a streak activity
curl -X POST https://api.bricqs.ai/api/v1/gamify/streaks/record \
  -H "X-API-Key: bq_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "participant_id": "user_123",
    "streak_code": "daily_login"
  }'

# Response
{
  "streak_code": "daily_login",
  "new_count": 3,
  "longest_count": 14,
  "is_new_record": false,
  "already_recorded": false
}
4. Get unified participant state
curl https://api.bricqs.ai/api/v1/gamify/participants/user_123/state \
  -H "X-API-Key: bq_live_your_key"

# Response
{
  "participant_id": "user_123",
  "points": { "balance": 250, "total_earned": 250, "total_spent": 0 },
  "tier": { "code": "bronze", "name": "Bronze", "level": 1 },
  "badges": [{ "code": "first_steps", "name": "First Steps", "earned": true }],
  "streaks": { "current": 3, "longest": 14 },
  "challenges": { "active": 0, "completed": 0 },
  "rewards": { "total_claimed": 0 }
}

Points5 endpoints

Award and deduct points, query balances, and view transaction history. Points trigger automatic tier evaluation — if a participant crosses a tier threshold, the tier upgrade is included in the response.

MethodEndpointDescription
POST/gamify/points/awardAward points. Returns new balance and any tier upgrade.
POST/gamify/points/deductDeduct points. Returns 400 if insufficient balance.
POST/gamify/points/award-batchBatch award up to 100 participants at once.
GET/gamify/participants/{pid}/pointsGet current balance, total earned, and total spent.
GET/gamify/participants/{pid}/points/transactionsPaginated transaction history.

Award Points

Request
POST /api/v1/gamify/points/award

{
  "participant_id": "user_123",    // Required, 1-255 chars
  "amount": 100,                   // Required, 1-1,000,000
  "reason": "Purchase completed",  // Optional, max 500 chars
  "metadata": {                    // Optional, custom data
    "order_id": "ord_abc",
    "amount_usd": 49.99
  },
  "idempotency_key": "purchase_ord_abc"  // Optional, prevents duplicates
}
Response
{
  "transaction_id": "a1b2c3d4-e5f6-...",
  "participant_id": "user_123",
  "amount": 100,
  "new_balance": 1500,
  "tier_upgrade": {                // null if no tier change
    "code": "gold",
    "name": "Gold Tier",
    "level": 3,
    "previous_code": "silver",
    "previous_level": 2
  }
}

Deduct Points

POST /api/v1/gamify/points/deduct

{
  "participant_id": "user_123",
  "amount": 50,
  "reason": "Reward redemption"
}

// Response
{
  "transaction_id": "...",
  "participant_id": "user_123",
  "amount": 50,
  "new_balance": 1450
}

// Error: insufficient balance
// 400 Bad Request
{ "detail": "Insufficient points. Available: 30, requested: 50" }

Batch Award

POST /api/v1/gamify/points/award-batch

{
  "awards": [
    { "participant_id": "user_1", "amount": 100, "reason": "Weekly bonus" },
    { "participant_id": "user_2", "amount": 100, "reason": "Weekly bonus" },
    { "participant_id": "user_3", "amount": 50, "reason": "Referral bonus" }
  ]
}

// Response
{
  "processed": 3,
  "failed": 0,
  "results": [
    { "participant_id": "user_1", "transaction_id": "...", "new_balance": 500, "error": null },
    { "participant_id": "user_2", "transaction_id": "...", "new_balance": 350, "error": null },
    { "participant_id": "user_3", "transaction_id": "...", "new_balance": 200, "error": null }
  ]
}

Badges2 endpoints

Award badges to participants and query earned status. Badge awards are idempotent — awarding the same badge twice returns already_earned: true instead of an error.

MethodEndpointDescription
POST/gamify/badges/awardAward a badge (idempotent).
GET/gamify/participants/{pid}/badgesList all badges with earned/unearned status.
// Award a badge
POST /api/v1/gamify/badges/award

{
  "participant_id": "user_123",
  "badge_code": "power_user",
  "metadata": { "trigger": "10th_login" }
}

// Response
{
  "participant_id": "user_123",
  "badge_code": "power_user",
  "badge_name": "Power User",
  "icon": "https://cdn.example.com/badges/power.png",
  "rarity": "rare",
  "earned_at": "2026-02-14T10:00:00Z",
  "already_earned": false
}

// Award same badge again → idempotent
{
  "already_earned": true,
  "badge_code": "power_user",
  "earned_at": "2026-02-14T10:00:00Z",
  ...
}
List Badges with Filters
// All badges (earned and unearned)
GET /api/v1/gamify/participants/user_123/badges

// Only earned badges
GET /api/v1/gamify/participants/user_123/badges?earned_only=true

// Specific badges by code
GET /api/v1/gamify/participants/user_123/badges?badge_codes=power_user,first_steps

// Response
{
  "participant_id": "user_123",
  "badges": [
    {
      "code": "power_user",
      "name": "Power User",
      "description": "Log in 10 times",
      "icon": "https://...",
      "rarity": "rare",
      "earned": true,
      "earned_at": "2026-02-14T10:00:00Z"
    }
  ],
  "total": 8,
  "earned_count": 3
}

Tiers2 endpoints

Query the current tier for a participant and manually assign tiers. Automatic tiers are evaluated on every points award — when a participant crosses a threshold, the tier upgrade is returned in the points response.

MethodEndpointDescription
GET/gamify/participants/{pid}/tierCurrent tier, next tier, and tier history.
POST/gamify/tiers/assignManually assign a tier (overrides automatic).
// Get current tier
GET /api/v1/gamify/participants/user_123/tier

{
  "participant_id": "user_123",
  "current_tier": {
    "code": "gold",
    "name": "Gold",
    "level": 3,
    "color": "#FFD700",
    "achieved_at": "2026-02-01T10:00:00Z"
  },
  "next_tier": {
    "code": "platinum",
    "name": "Platinum",
    "points_required": 10000,
    "points_remaining": 8500
  },
  "tier_history": [
    { "code": "bronze", "achieved_at": "2026-01-01T..." },
    { "code": "silver", "achieved_at": "2026-01-15T..." },
    { "code": "gold", "achieved_at": "2026-02-01T..." }
  ]
}

// Manual tier assignment
POST /api/v1/gamify/tiers/assign

{
  "participant_id": "user_123",
  "tier_code": "platinum",
  "reason": "VIP promotion"
}

Leaderboards2 endpoints

Query leaderboard rankings and individual participant positions. Rankings are computed on-the-fly from the points/scoring data.

MethodEndpointDescription
GET/gamify/leaderboards/{code}Top rankings with optional time period filter.
GET/gamify/leaderboards/{code}/rank/{pid}Individual rank, score, and percentile.
// Get top 10 rankings
GET /api/v1/gamify/leaderboards/top_scorers?limit=10&period=monthly

{
  "leaderboard_code": "top_scorers",
  "period": "monthly",
  "entries": [
    { "rank": 1, "participant_id": "user_456", "score": 5000, "change": "up" },
    { "rank": 2, "participant_id": "user_123", "score": 4500, "change": "same" },
    { "rank": 3, "participant_id": "user_789", "score": 4200, "change": "new" }
  ],
  "total_participants": 1250
}

// Get individual rank
GET /api/v1/gamify/leaderboards/top_scorers/rank/user_123

{
  "participant_id": "user_123",
  "rank": 2,
  "score": 4500,
  "total_participants": 1250,
  "percentile": 99.8
}
Period options: all_time, yearly, monthly, weekly, daily. If omitted, uses the leaderboard definition's default time window.

Streaks2 endpoints

Track consecutive activity streaks (daily logins, weekly workouts, etc.). The API handles period calculation, grace periods, and automatic resets.

MethodEndpointDescription
POST/gamify/streaks/recordRecord streak activity. Auto-increment or reset based on period.
GET/gamify/participants/{pid}/streaksAll streak statuses for a participant.
// Record a streak activity
POST /api/v1/gamify/streaks/record

{
  "participant_id": "user_123",
  "streak_code": "daily_login",
  "timestamp": "2026-02-14T08:15:00Z"  // Optional, defaults to now
}

// Day 1 response
{ "streak_code": "daily_login", "new_count": 1, "longest_count": 1,
  "is_new_record": true, "already_recorded": false }

// Same day again → idempotent
{ "streak_code": "daily_login", "new_count": 1, "longest_count": 1,
  "is_new_record": false, "already_recorded": true }

// Next day → increments
{ "streak_code": "daily_login", "new_count": 2, "longest_count": 2,
  "is_new_record": true, "already_recorded": false }

// Get all streaks
GET /api/v1/gamify/participants/user_123/streaks

{
  "participant_id": "user_123",
  "streaks": [
    {
      "code": "daily_login",
      "name": "Daily Login",
      "current_count": 7,
      "longest_count": 21,
      "last_recorded_at": "2026-02-14T08:15:00Z",
      "period": "daily"
    }
  ]
}

Rewards3 endpoints

List available rewards, claim them, and query claimed history. Rewards can optionally deduct points as a cost.

MethodEndpointDescription
GET/gamify/rewardsList available rewards. Filter by ?reward_type=coupon.
POST/gamify/rewards/{reward_id}/claimClaim a reward. Optionally deduct points.
GET/gamify/participants/{pid}/rewardsList all rewards claimed by participant.
// List available rewards
GET /api/v1/gamify/rewards?reward_type=coupon

{
  "rewards": [
    {
      "id": "rwd_uuid",
      "name": "10% Off Coupon",
      "type": "coupon",
      "description": "10% discount on next purchase",
      "points_cost": 500,
      "available_codes": 45,
      "max_claims_per_user": 1
    }
  ],
  "total": 1
}

// Claim a reward (with points deduction)
POST /api/v1/gamify/rewards/rwd_uuid/claim

{
  "participant_id": "user_123",
  "points_deduction": true
}

// Response
{
  "claim_id": "claim_uuid",
  "participant_id": "user_123",
  "reward_name": "10% Off Coupon",
  "reward_type": "coupon",
  "code_value": "SAVE10-ABC123",
  "points_deducted": 500,
  "new_balance": 1000
}
Reward types: coupon, voucher, physical, digital, points_multiplier

Events3 endpoints

Emit custom events from your application. Events are processed synchronously and can trigger challenge evaluations, badge unlocks, and other automated actions based on your configured rules.

MethodEndpointDescription
POST/gamify/eventsEmit a single event (synchronous processing).
POST/gamify/events/batchBatch emit up to 100 events.
GET/gamify/participants/{pid}/eventsQuery event history with filters.
// Emit a custom event
POST /api/v1/gamify/events

{
  "participant_id": "user_123",
  "event_name": "purchase_completed",
  "properties": {
    "amount": 49.99,
    "currency": "USD",
    "product_id": "prod_abc"
  },
  "timestamp": "2026-02-14T10:00:00Z",
  "idempotency_key": "purchase_ord_001"
}

// Response
{
  "event_id": "evt_uuid",
  "fact_id": "fact_uuid",
  "status": "processed"
}

// Query event history with filters
GET /api/v1/gamify/participants/user_123/events?event_name=purchase_completed&page=1&page_size=20

{
  "participant_id": "user_123",
  "events": [
    {
      "id": "evt_uuid",
      "event_name": "purchase_completed",
      "properties": { "amount": 49.99, "currency": "USD" },
      "occurred_at": "2026-02-14T10:00:00Z"
    }
  ],
  "total": 156,
  "page": 1,
  "page_size": 20
}

Participants4 endpoints

Register participants explicitly, get rich profiles with all gamification data, update profile attributes, and query unified state. Participants are also auto-created on first interaction with any other endpoint.

MethodEndpointDescription
POST/gamify/participantsCreate/register a participant with profile data. Idempotent.
GET/gamify/participants/{pid}Rich profile with points, tier, badges, streaks, rewards.
PATCH/gamify/participants/{pid}Update display name, avatar, or custom attributes.
GET/gamify/participants/{pid}/stateUnified state with selectable sections.

Create Participant

POST /api/v1/gamify/participants

{
  "participant_id": "user_123",        // Required, your app's user ID
  "display_name": "Jane Doe",          // Optional
  "avatar_url": "https://example.com/avatar.png",  // Optional
  "attributes": {                      // Optional, custom metadata
    "plan": "premium",
    "signup_source": "referral"
  }
}

// Response (201 Created)
{
  "participant_id": "user_123",
  "display_name": "Jane Doe",
  "avatar_url": "https://example.com/avatar.png",
  "attributes": { "plan": "premium", "signup_source": "referral" },
  "points": { "balance": 0, "total_earned": 0, "total_spent": 0 },
  "tier": null,
  "badges": [],
  "streaks": null,
  "rewards_claimed": 0,
  "total_events": 0,
  "is_active": true,
  "created_at": "2026-02-14T10:00:00Z"
}

// Idempotent — calling again updates display_name/avatar/attributes

Get Participant Profile

Returns a rich profile with points breakdown, current tier with next-tier progress, earned badges, best streak, and rewards count.

GET /api/v1/gamify/participants/user_123

{
  "participant_id": "user_123",
  "display_name": "Jane Doe",
  "avatar_url": "https://example.com/avatar.png",
  "attributes": { "plan": "premium" },
  "points": { "balance": 1500, "total_earned": 5000, "total_spent": 3500 },
  "tier": {
    "code": "gold", "name": "Gold", "level": 3, "color": "#FFD700",
    "achieved_at": "2026-02-01T10:00:00Z",
    "next_tier": { "code": "platinum", "name": "Platinum",
                   "points_required": 10000, "points_remaining": 8500 }
  },
  "badges": [
    { "code": "first_steps", "name": "First Steps", "rarity": "common",
      "earned": true, "earned_at": "2026-01-15T..." }
  ],
  "streaks": { "current": 7, "longest": 21, "last_activity_at": "2026-02-14T..." },
  "rewards_claimed": 3,
  "total_events": 156,
  "first_seen_at": "2026-01-01T...",
  "last_seen_at": "2026-02-14T...",
  "is_active": true
}

Update Participant

PATCH /api/v1/gamify/participants/user_123

{
  "display_name": "Jane Smith",
  "attributes": { "plan": "enterprise", "team_id": "team_42" }
}

// Returns full profile (same shape as GET)

Unified State

Lightweight endpoint that returns selected gamification sections without full profile data.

// Full state
GET /api/v1/gamify/participants/user_123/state

// Partial state (only specific sections)
GET /api/v1/gamify/participants/user_123/state?include=points,tier,badges

// Response
{
  "participant_id": "user_123",
  "points": { "balance": 1500, "total_earned": 5000, "total_spent": 3500 },
  "tier": { "code": "gold", "name": "Gold", "level": 3 },
  "badges": [
    { "code": "first_steps", "earned": true, "earned_at": "..." },
    { "code": "power_user", "earned": false, "earned_at": null }
  ],
  "streaks": { "current": 7, "longest": 21 },
  "challenges": { "active": 2, "completed": 5 },
  "rewards": { "total_claimed": 3 }
}
Include parameter: Comma-separated list of sections to return. Options: points, tier, badges, streaks, challenges, rewards. Omit to return all sections.

Admin EndpointsAdmin Key Required

Create, update, and delete gamification definitions (badges, tiers, leaderboards, streaks, rewards). These endpoints require an API key with admin or gamify:admin scope.

ResourceEndpointsOperations
Badges/gamify/admin/badgesList, Create, Get, Update, Delete
Tiers/gamify/admin/tiersList, Create, Get, Update, Delete
Leaderboards/gamify/admin/leaderboardsList, Create, Get, Update, Delete
Streaks/gamify/admin/streaksList, Create, Get, Update, Delete
Rewards/gamify/admin/rewardsList, Create, Get, Update, Delete
Participants/gamify/admin/participantsList (search/filter/sort), Delete/Anonymize

All admin resources follow the same CRUD pattern:

# List with pagination and filters
GET  /api/v1/gamify/admin/badges?page=1&page_size=50&is_active=true

# Create
POST /api/v1/gamify/admin/badges
{
  "code": "streak_master",
  "name": "Streak Master",
  "description": "Maintain a 30-day streak",
  "icon_url": "https://cdn.example.com/badges/streak.png",
  "category": "achievement",
  "rarity": "epic",
  "display_order": 10
}

# Get by ID
GET  /api/v1/gamify/admin/badges/{badge_id}

# Update (partial)
PATCH /api/v1/gamify/admin/badges/{badge_id}
{ "name": "Updated Name", "rarity": "legendary" }

# Delete (soft-delete)
DELETE /api/v1/gamify/admin/badges/{badge_id}

Tier Definition Example

POST /api/v1/gamify/admin/tiers

{
  "code": "platinum",
  "name": "Platinum",
  "level": 4,
  "color": "#E5E4E2",
  "criteria_config": { "min_points": 10000 },
  "award_type": "automatic",
  "benefits": ["priority_support", "2x_points"],
  "display_order": 4
}

Streak Definition Example

POST /api/v1/gamify/admin/streaks

{
  "code": "daily_login",
  "name": "Daily Login Streak",
  "description": "Log in every day to build your streak",
  "period": "daily",
  "grace_period_hours": 24,
  "display_order": 1
}

Reward Definition Example

POST /api/v1/gamify/admin/rewards

{
  "name": "Premium Gift Card",
  "type": "voucher",
  "description": "Redeemable for premium items",
  "points_cost": 1000,
  "max_claims_per_user": 1,
  "total_inventory": 100,
  "is_active": true
}

Participant Management

# List participants with search, filter, and sort
GET /api/v1/gamify/admin/participants?search=jane&sort_by=total_points&sort_order=desc

{
  "items": [
    {
      "participant_id": "user_123",
      "display_name": "Jane Doe",
      "total_points": 5000,
      "available_points": 1500,
      "current_tier": "gold",
      "total_events": 156,
      "is_active": true
    }
  ],
  "total": 1, "page": 1, "page_size": 50
}

# Anonymize a participant (soft-delete, clears PII)
DELETE /api/v1/gamify/admin/participants/user_123?anonymize=true

# Hard delete a participant and all their data
DELETE /api/v1/gamify/admin/participants/user_123

Common Patterns

Idempotency

Points awards and events support idempotency_key to prevent duplicate processing. Badge awards and streak recordings are naturally idempotent (same badge/period returns success without duplication).

// First call — processes normally
POST /api/v1/gamify/points/award
{ "participant_id": "user_123", "amount": 100,
  "idempotency_key": "purchase_ord_001" }
→ { "transaction_id": "txn_abc", "new_balance": 100 }

// Second call with same key — returns cached result
POST /api/v1/gamify/points/award
{ "participant_id": "user_123", "amount": 100,
  "idempotency_key": "purchase_ord_001" }
→ { "transaction_id": "txn_abc", "new_balance": 100 }  // Same result

Participant Registration

Participants are automatically created on their first interaction with any endpoint — no registration step required. Optionally, use POST /gamify/participants to pre-register participants with a display name, avatar, and custom attributes. The participant_id is your application's user identifier (string, 1-255 chars).

Pagination

List endpoints support pagination via page and page_size query parameters.

GET /api/v1/gamify/participants/user_123/points/transactions?page=2&page_size=20

{
  "transactions": [...],
  "total": 156,      // Total across all pages
  "page": 2,         // Current page
  "page_size": 20    // Items per page (max 100)
}

Automatic Tier Evaluation

Every points award automatically evaluates tier thresholds. If the participant qualifies for a higher tier, the tier_upgrade field is populated in the response. No separate API call needed.

Error Handling

All errors return a consistent JSON format with an appropriate HTTP status code.

// Error response format
{
  "detail": "Human-readable error message"
}

// Common status codes
401 Unauthorized     — Missing or invalid API key
403 Forbidden        — API key lacks required scope (admin endpoints)
404 Not Found        — Badge code, tier code, or participant not found
400 Bad Request      — Insufficient points, invalid parameters
422 Unprocessable    — Request validation failed (missing required fields)
429 Too Many Requests — Rate limit exceeded
ScenarioStatusDetail
Deduct more than available400Insufficient points. Available: 30, requested: 50
Unknown badge code404Badge definition not found: unknown_badge
Missing admin scope403API key requires 'admin' scope
No reward codes left400No available reward codes
Max claims exceeded400Maximum claims per participant exceeded

Integration Example

A typical server-side integration that awards points on purchase and checks for tier upgrades.

Node.js / Express
const BRICQS_API = 'https://api.bricqs.ai/api/v1/gamify';
const API_KEY = process.env.BRICQS_API_KEY;

const headers = {
  'X-API-Key': API_KEY,
  'Content-Type': 'application/json',
};

// After a purchase is completed
app.post('/api/purchase/complete', async (req, res) => {
  const { userId, orderId, amount } = req.body;

  // 1. Award points based on purchase amount
  const pointsRes = await fetch(`${BRICQS_API}/points/award`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      participant_id: userId,
      amount: Math.floor(amount),  // 1 point per dollar
      reason: `Purchase #${orderId}`,
      metadata: { order_id: orderId, amount },
      idempotency_key: `purchase_${orderId}`,
    }),
  });
  const points = await pointsRes.json();

  // 2. Record daily activity streak
  await fetch(`${BRICQS_API}/streaks/record`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      participant_id: userId,
      streak_code: 'daily_purchase',
    }),
  });

  // 3. Check for tier upgrade
  if (points.tier_upgrade) {
    // Trigger your own notification
    await sendPushNotification(userId,
      `Congratulations! You've reached ${points.tier_upgrade.name}!`
    );
  }

  res.json({
    points_earned: points.amount,
    new_balance: points.new_balance,
    tier_upgrade: points.tier_upgrade,
  });
});
Python / FastAPI
import httpx

BRICQS_API = "https://api.bricqs.ai/api/v1/gamify"
HEADERS = {
    "X-API-Key": os.environ["BRICQS_API_KEY"],
    "Content-Type": "application/json",
}

@app.post("/api/purchase/complete")
async def complete_purchase(order: Order):
    async with httpx.AsyncClient() as client:
        # Award points
        resp = await client.post(
            f"{BRICQS_API}/points/award",
            headers=HEADERS,
            json={
                "participant_id": order.user_id,
                "amount": int(order.total),
                "reason": f"Purchase #{order.id}",
                "idempotency_key": f"purchase_{order.id}",
            },
        )
        result = resp.json()

        # Record streak
        await client.post(
            f"{BRICQS_API}/streaks/record",
            headers=HEADERS,
            json={
                "participant_id": order.user_id,
                "streak_code": "daily_purchase",
            },
        )

    return {
        "points_earned": result["amount"],
        "new_balance": result["new_balance"],
        "tier_upgrade": result.get("tier_upgrade"),
    }

Next Steps