BricqsBricqs
Documentation

Points API

Award and deduct points, query balances, and page through transaction history. Awards trigger automatic tier evaluation; when a participant crosses a threshold the response includes the tier upgrade and any unlocked badges. Expiring credits are consumed FIFO before non-expiring credits.

Auth
All endpoints require an X-API-Key header. Production keys are prefixed bq_live_; sandbox keys bq_test_.
Scopes
Participant key Balance and transaction reads accept an API key with gamify:read (in the mint default) or a participant JWT pinned to its own participant.
Admin scope Award, deduct, and award-batch require the gamify:write scope, which is NOT in the mint default: grant it explicitly on the key your backend uses for value movement.
Base URLhttps://api.bricqs.co/api/v1/gamify

Endpoint inventory

MethodEndpointPurpose
POST/gamify/points/awardAward points to a participant. Idempotent. Returns new balance, tier upgrade, badges unlocked.
POST/gamify/points/deductDeduct points. Idempotent. Returns 400 if the available balance is insufficient.
POST/gamify/points/award-batchAward up to 100 participants in one request. Idempotent. Per-item failures captured in results.
GET/gamify/participants/{participant_id}/pointsCurrent balance, total earned (lifetime), total spent (lifetime).
GET/gamify/participants/{participant_id}/points/transactionsPaginated ledger entries (awards and deductions) for one participant.
POST/api/v1/gamify/points/award
Participant keyIdempotent

Credit a participant with points. Triggers tier evaluation and badge unlock checks. Safe to retry via the Idempotency-Key header; a second call with the same key returns the original transaction without double-awarding.

Headers
FieldTypeDescription
Idempotency-KeystrOptional. 1 to 255 chars matching ^[A-Za-z0-9_\-:.]{1,255}$. Recommended for every call. Descriptive keys ("order-ord_abc") give clean audit trails.
Request body
FieldTypeDescription
participant_idrequiredstrYour participant identifier. 1 to 255 characters. Auto-creates the participant on first interaction.
amountrequiredintPoints to award. Must be greater than 0 and at most 1,000,000.
reasonOptional[str]Free-form audit note (max 500 chars). Surfaces in transaction history and tier-change fact payloads.
metadataOptional[dict[str, Any]]Custom payload stored alongside the transaction (e.g. { order_id, amount_usd }). Returned by the transactions endpoint.
idempotency_keyOptional[str]Legacy body field (max 255 chars). The Idempotency-Key header is preferred; supplying both with different values returns 400 IDEMPOTENCY_KEY_MISMATCH.
expires_atOptional[datetime]When set, the credit expires at this timestamp. Expiring credits are consumed FIFO before non-expiring credits during deductions.
POST /api/v1/gamify/points/award
X-API-Key: bq_live_xxxxx
Content-Type: application/json
Idempotency-Key: order-ord_abc

{
  "participant_id": "user_123",
  "amount": 100,
  "reason": "Purchase completed",
  "metadata": {
    "order_id": "ord_abc",
    "amount_usd": 49.99
  }
}
Response fields
FieldTypeDescription
transaction_idstrUnique ledger id for this award.
participant_idstrEcho of the credited participant.
amountintPoints awarded.
new_balanceintParticipant's available balance after the award.
tier_upgradeOptional[TierUpgradeInfo]Populated when the award caused a tier change. Shape: { code, name, level, previous_code?, previous_level? }. null when no tier change occurred.
badges_unlockedlist[str]Badge codes unlocked by this award. Empty list when no badges fired. Default: []
{
  "transaction_id": "a1b2c3d4-e5f6-...",
  "participant_id": "user_123",
  "amount": 100,
  "new_balance": 1500,
  "tier_upgrade": {
    "code": "gold",
    "name": "Gold Tier",
    "level": 3,
    "previous_code": "silver",
    "previous_level": 2
  },
  "badges_unlocked": ["first_purchase"]
}
Errors
StatusCodeWhen it fires
400IDEMPOTENCY_KEY_INVALIDIdempotency-Key header is empty, longer than 255 chars, or contains characters outside [A-Za-z0-9_\-:.].
400IDEMPOTENCY_KEY_MISMATCHBoth the Idempotency-Key header AND a body idempotency_key were provided and they differ.
401AUTH_UNAUTHENTICATEDX-API-Key header missing, invalid, expired, or revoked.
403AUTH_FORBIDDENAPI key lacks the required scope for this operation (see the Auth callout), or the tenant is disabled.
429RATE_LIMIT_PARTICIPANT_EXCEEDEDPer-participant write rate cap exceeded. The Retry-After response header tells you when to retry.
POST/api/v1/gamify/points/deduct
Participant keyIdempotent

Debit a participant's available balance (e.g. reward redemption). FIFO-consumes any expiring credits first. Idempotent via the Idempotency-Key header.

Headers
FieldTypeDescription
Idempotency-KeystrOptional. 1 to 255 chars matching ^[A-Za-z0-9_\-:.]{1,255}$. Recommended for every redemption to make retries safe.
Request body
FieldTypeDescription
participant_idrequiredstrYour participant identifier. 1 to 255 characters.
amountrequiredintPoints to deduct. Must be greater than 0 and at most 1,000,000.
reasonOptional[str]Free-form audit note (max 500 chars).
metadataOptional[dict[str, Any]]Custom payload stored alongside the transaction.
idempotency_keyOptional[str]Legacy body field. Prefer the Idempotency-Key header.
POST /api/v1/gamify/points/deduct
X-API-Key: bq_live_xxxxx
Content-Type: application/json
Idempotency-Key: redemption-rdm_42

{
  "participant_id": "user_123",
  "amount": 50,
  "reason": "Reward redemption"
}
Response fields
FieldTypeDescription
transaction_idstrUnique ledger id for this deduction.
participant_idstrEcho of the debited participant.
amountintPoints deducted.
new_balanceintParticipant's available balance after the deduction.
tier_upgradeOptional[TierUpgradeInfo]Always null on deductions (tiers track lifetime earnings, not available balance).
badges_unlockedlist[str]Always empty on deductions. Default: []
{
  "transaction_id": "b7c8d9e0-...",
  "participant_id": "user_123",
  "amount": 50,
  "new_balance": 1450
}
Errors
StatusCodeWhen it fires
400insufficient_pointsAvailable balance is below the requested amount. Body: { detail: "Insufficient points. Available: X, requested: N" }.
400IDEMPOTENCY_KEY_INVALIDIdempotency-Key header is empty, too long, or contains illegal characters.
400IDEMPOTENCY_KEY_MISMATCHHeader and body idempotency keys disagree.
401AUTH_UNAUTHENTICATEDX-API-Key header missing or invalid.
403AUTH_FORBIDDENAPI key lacks the required scope for this operation (see the Auth callout), or the tenant is disabled.
429RATE_LIMIT_PARTICIPANT_EXCEEDEDPer-participant write rate cap exceeded.
POST/api/v1/gamify/points/award-batch
Participant keyIdempotent

Award points to up to 100 participants in a single request. Each item is processed independently; an individual failure does not roll back the rest. The endpoint itself never raises on per-item validation errors (failures appear inside results[].error).

Request body
FieldTypeDescription
awardsrequiredlist[BatchAwardItem]1 to 100 award items. Each item has the same shape as POST /points/award minus expires_at.
BatchAwardItem
FieldTypeDescription
participant_idrequiredstr1 to 255 characters.
amountrequiredintGreater than 0, at most 1,000,000.
reasonOptional[str]Max 500 chars.
metadataOptional[dict[str, Any]]Custom payload.
idempotency_keyOptional[str]Per-item idempotency. Recommended when retrying a batch.
POST /api/v1/gamify/points/award-batch
X-API-Key: bq_live_xxxxx
Content-Type: application/json

{
  "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 fields
FieldTypeDescription
processedintNumber of items that succeeded.
failedintNumber of items whose results[].error is non-null.
resultslist[BatchAwardResult]One entry per input item, in the same order. Shape: { participant_id, transaction_id?, new_balance?, error? }. On success error is null; on failure transaction_id and new_balance are null and error describes the cause.
{
  "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 }
  ]
}
Errors
StatusCodeWhen it fires
401AUTH_UNAUTHENTICATEDX-API-Key header missing or invalid. Per-item failures never raise at the request level; they appear in results[].error.
403AUTH_FORBIDDENAPI key lacks the required scope for this operation (see the Auth callout), or the tenant is disabled.
GET/api/v1/gamify/participants/{participant_id}/points
Participant key

Returns the participant's current available balance and lifetime totals. lifetime is never decremented by redemptions (it ranks tier and leaderboard progress); only balance moves on deduct.

Path parameters
FieldTypeDescription
participant_idrequiredstrYour participant identifier. 1 to 255 characters.
GET /api/v1/gamify/participants/user_123/points
X-API-Key: bq_live_xxxxx
Response fields
FieldTypeDescription
participant_idstrEcho of the requested participant id.
balanceintAvailable points (lifetime earned minus lifetime spent, plus any expirations).
lifetimeintTotal points ever awarded. Used for tier evaluation and leaderboards. Never decremented.
redeemedintTotal points ever deducted.
{
  "participant_id": "user_123",
  "balance": 1500,
  "lifetime": 5000,
  "redeemed": 3500
}
Errors
StatusCodeWhen it fires
401AUTH_UNAUTHENTICATEDX-API-Key header missing or invalid.
403AUTH_FORBIDDENAPI key lacks the required scope for this operation (see the Auth callout), or the tenant is disabled.
GET/api/v1/gamify/participants/{participant_id}/points/transactions
Participant key

Paginated ledger of all awards and deductions for one participant, newest first.

Path parameters
FieldTypeDescription
participant_idrequiredstrYour participant identifier.
Query parameters
FieldTypeDescription
pageint1-indexed page number. Must be >= 1. Default: 1
page_sizeintItems per page. Must be between 1 and 100. Default: 50
GET /api/v1/gamify/participants/user_123/points/transactions?page=1&page_size=20
X-API-Key: bq_live_xxxxx
Response fields
FieldTypeDescription
participant_idstrEcho of the requested participant id.
transactionslist[PointsTransactionEntry]Page of ledger entries. Each entry: { id, amount, reason?, transaction_type?, created_at }.
totalintTotal transactions across all pages for this participant.
pageintEcho of the requested page.
page_sizeintEcho of the requested page size.
{
  "participant_id": "user_123",
  "transactions": [
    {
      "id": "txn_abc",
      "amount": 100,
      "reason": "Purchase completed",
      "transaction_type": "award",
      "created_at": "2026-02-14T10:00:00Z"
    },
    {
      "id": "txn_xyz",
      "amount": -50,
      "reason": "Reward redemption",
      "transaction_type": "deduct",
      "created_at": "2026-02-13T18:22:00Z"
    }
  ],
  "total": 156,
  "page": 1,
  "page_size": 20
}
Errors
StatusCodeWhen it fires
401AUTH_UNAUTHENTICATEDX-API-Key header missing or invalid.
403AUTH_FORBIDDENAPI key lacks the required scope for this operation (see the Auth callout), or the tenant is disabled.
422validation_errorpage is below 1, or page_size is outside the 1 to 100 range.
Related
← Back to Gamification API