BricqsBricqs
Documentation

Events API

Emit custom events from your application. Events are processed synchronously, persisted as facts, and fed through the rules engine to trigger challenge evaluations, badge unlocks, tier transitions, and outbound webhooks. Use the history endpoint to read back a participant’s emitted events with filters and pagination.

Auth
All endpoints require an X-API-Key header. Production keys are prefixed bq_live_; sandbox keys bq_test_.
Scopes
Participant key Browser/mobile callers use a participant JWT (Authorization: Bearer) with the write:events scope for emission and read:state for history; the token is pinned to its own participant_id.
Admin scope Server callers use X-API-Key. Emission requires the events:write scope and the history read requires gamify:read; both are included in the mint default, so a default-minted key covers this whole page.
Base URLhttps://api.bricqs.co/api/v1/gamify

Endpoint inventory

MethodEndpointPurpose
POST/gamify/eventsEmit a single event. Idempotent.
POST/gamify/events/batchEmit up to 100 events in one request. Per-item idempotency via body keys.
GET/gamify/participants/{participant_id}/eventsPaginated event history with filters.
POST/api/v1/gamify/events
Participant keyIdempotent

Emit a single custom event for a participant. The event is persisted as a fact and evaluated synchronously; it may trigger badge unlocks, tier transitions, and outbound webhooks as downstream effects. The response body is narrow: event_id, fact_id, status, and rewards_granted (rules-engine action outcomes only; challenge/tier detail is read from state, webhooks, or SSE). Safe to retry: with an Idempotency-Key header a second call returns the same event_id and fact_id with status duplicate (rewards_granted empty), and when no key is supplied the server synthesizes one from the event's identity, so accidental retries of an identical request still deduplicate.

Headers
FieldTypeDescription
Idempotency-KeystrOptional. 1 to 255 chars matching ^[A-Za-z0-9_\-:.]{1,255}$. Recommended for every call so retries never produce duplicate facts.
Request body
FieldTypeDescription
participant_idrequiredstrYour participant identifier. 1 to 255 characters. Auto-creates the participant on first interaction.
event_namerequiredstrEvent name to emit. 1 to 100 characters. Use snake_case (purchase_completed, video_watched).
propertiesdict[str, Any]Free-form event payload. Read by challenge evaluators and forwarded to outbound webhooks. Default: {}
timestampOptional[datetime]Event occurrence time. Defaults to server time (UTC). Naive datetimes are stored as UTC.
idempotency_keyOptional[str]Legacy body idempotency key (max 255 chars). The Idempotency-Key header is preferred; when both are supplied they must match.
POST /api/v1/gamify/events
X-API-Key: bq_live_xxxxx
Content-Type: application/json
Idempotency-Key: purchase_ord_001

{
  "participant_id": "user_42",
  "event_name": "purchase_completed",
  "properties": {
    "amount": 49.99,
    "currency": "USD",
    "product_id": "prod_abc"
  },
  "timestamp": "2026-02-14T10:00:00Z"
}
Response fields
FieldTypeDescription
event_idOptional[str]Identifier of the persisted event record.
fact_idOptional[str]Identifier of the fact emitted into the rules pipeline.
statusstrProcessing status. Default: "processed"
rewards_grantedlist[dict[str, Any]]Outcomes of rules-engine actions this event fired (rule-granted points, badges, rewards). Empty when no rule matched, and always empty on duplicates. Challenge progress and tier transitions are NOT reported here; read them from state, webhooks, or SSE. Default: []
{
  "event_id": "01HZ...",
  "fact_id": "01HZ...",
  "status": "processed",
  "rewards_granted": []
}
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_UNAUTHENTICATEDNo credential, or the API key / participant JWT is invalid, expired, or revoked (also AUTH_API_KEY_INVALID).
403AUTH_FORBIDDENAPI key lacks the events:write scope, a participant JWT emits for a different participant_id, or the tenant is disabled.
429RATE_LIMIT_PARTICIPANT_EXCEEDEDPer-participant rate cap exceeded (default 100 events/min, plan-configurable). The Retry-After response header tells you when to retry.
POST/api/v1/gamify/events/batch
Participant key

Emit up to 100 events in a single request. Each event is processed independently; per-item failures are reported in the results array without failing the whole request. Use the body-level idempotency_key on each event for retry safety (the request-level Idempotency-Key header is not honoured here; keyless items get server-synthesized keys). Every batched event counts against the same per-participant rate limit as the single endpoint: over-limit events are marked rate_limited individually, and for participant-JWT callers any event whose participant_id differs from the token subject is marked forbidden, while the rest of the batch continues.

Request body
FieldTypeDescription
eventsrequiredlist[EmitEventRequest]Array of 1 to 100 events. Each entry uses the same shape as POST /events. Set idempotency_key per item for retry safety.
POST /api/v1/gamify/events/batch
X-API-Key: bq_live_xxxxx
Content-Type: application/json

{
  "events": [
    {
      "participant_id": "user_42",
      "event_name": "purchase_completed",
      "properties": { "amount": 49.99 },
      "idempotency_key": "purchase_ord_001"
    },
    {
      "participant_id": "user_42",
      "event_name": "loyalty_signup",
      "properties": { "channel": "email" },
      "idempotency_key": "signup_user_42"
    }
  ]
}
Response fields
FieldTypeDescription
processedintCount of events that completed successfully.
failedintCount of events that returned an error.
resultslist[EmitEventResponse]Per-item results in submission order. Statuses: processed, error (null event_id/fact_id), rate_limited (participant over cap), forbidden (JWT caller, participant_id mismatch).
{
  "processed": 2,
  "failed": 0,
  "results": [
    {
      "event_id": "01HZ...",
      "fact_id": "01HZ...",
      "status": "processed",
      "rewards_granted": []
    },
    {
      "event_id": "01HZ...",
      "fact_id": "01HZ...",
      "status": "processed",
      "rewards_granted": []
    }
  ]
}
Errors
StatusCodeWhen it fires
401AUTH_UNAUTHENTICATEDNo credential, or the API key / participant JWT is invalid, expired, or revoked.
403AUTH_FORBIDDENAPI key lacks the events:write scope, or the tenant is disabled.
422VALIDATION_INVALID_VALUEevents array is empty or exceeds 100 entries, or an item fails schema validation (validation_error envelope with a VALIDATION_* code).
GET/api/v1/gamify/participants/{participant_id}/events
Participant key

Paginated event history for a participant, with optional filters by event_name and date range.

Path parameters
FieldTypeDescription
participant_idrequiredstrYour participant identifier.
Query parameters
FieldTypeDescription
event_nameOptional[str]Filter to events with this exact name.
from_dateOptional[str]Inclusive lower bound, ISO date (YYYY-MM-DD).
to_dateOptional[str]Inclusive upper bound, ISO date (YYYY-MM-DD).
pageint1-indexed page number. Default: 1
page_sizeintItems per page. Max 100. Default: 50
GET /api/v1/gamify/participants/user_42/events?event_name=purchase_completed&page=1&page_size=20
X-API-Key: bq_live_xxxxx
Response fields
FieldTypeDescription
participant_idstrEcho of the requested participant id.
eventslist[EventHistoryEntry]Page of events. Each entry: id, event_name, properties (default {}), occurred_at.
totalintTotal events matching the filters across all pages.
pageintEcho of the requested page.
page_sizeintEcho of the requested page size.
{
  "participant_id": "user_42",
  "events": [
    {
      "id": "01HZ...",
      "event_name": "purchase_completed",
      "properties": { "amount": 49.99, "currency": "USD" },
      "occurred_at": "2026-02-14T10:00:00Z"
    }
  ],
  "total": 156,
  "page": 1,
  "page_size": 20
}
Errors
StatusCodeWhen it fires
401AUTH_UNAUTHENTICATEDNo credential, or the API key / participant JWT is invalid, expired, or revoked.
403AUTH_FORBIDDENAPI key lacks the gamify:read scope (in the mint default; only custom-scoped keys can lack it), or a participant JWT requested another participant's history.
Related
← Back to Gamification API