BricqsBricqs
Documentation

Webhooks

Bricqs delivers progression events (badges, tiers, points, streaks, milestones, challenges, contests, referrals, rewards) and engagement activity events to HTTPS endpoints you register. Every delivery is HMAC-signed, retried on failure, logged, and manually replayable. The machine-readable list of subscribable events and their payload schemas is published at https://api.bricqs.co/.well-known/events.json.

Auth
All endpoints require an X-API-Key header. Production keys are prefixed bq_live_; sandbox keys bq_test_.
Scopes
Admin scope All destination-management endpoints require admin auth: a dashboard session or an API key carrying the admin or gamify:admin scope. Deliveries themselves are outbound; your consumer needs no Bricqs credential, only the destination secret for signature verification.
Base URLhttps://api.bricqs.co/api/v1/gamify

Endpoint inventory

MethodEndpointPurpose
GET/gamify/webhooksList destinations.
POST/gamify/webhooksCreate a destination. Returns the signing secret.
GET/gamify/webhooks/{destination_id}Read one destination.
PATCH/gamify/webhooks/{destination_id}Update url, events, retries, timeout, active state. The URL is re-validated against SSRF rules.
DELETE/gamify/webhooks/{destination_id}Delete a destination.
POST/gamify/webhooks/{destination_id}/testSend a signed test delivery (X-Bricqs-Event: ping).
GET/gamify/webhooks/{destination_id}/logsDelivery history (status, attempts, response codes).
POST/gamify/webhooks/{destination_id}/deliveries/{log_id}/replayReplay one delivery.
POST/gamify/webhooks/{destination_id}/replayBulk replay; returns a job id.
GET/gamify/webhooks/{destination_id}/replay-jobs/{job_id}Bulk replay job status.
POST/api/v1/gamify/webhooks
Admin scope

Register an HTTPS endpoint for event delivery. The response includes the generated signing secret: store it server-side. There is no secret-rotation endpoint; to rotate, delete the destination and create a new one.

Request body
FieldTypeDescription
namerequiredstrDisplay name, 1 to 100 characters. Names prefixed [system] are reserved and rejected.
urlrequiredstrHTTPS endpoint URL. Validated against SSRF rules (no private ranges).
eventsrequiredlist[str]Event types to subscribe to. Every entry must exist in the published catalog (events.json); unknown names are rejected.
engagement_idOptional[str]Scope delivery to one engagement. Omit for all.
custom_headersdictExtra headers added to every delivery (for your own auth). Default: {}
retry_countintRetries after the initial attempt, 0 to 5. Default: 3
timeout_secondsintPer-attempt response timeout, 3 to 60. Default: 10
# Standard bq_live_... key carrying the admin (or gamify:admin) scope.
curl -X POST https://api.bricqs.co/api/v1/gamify/webhooks \
  -H "X-API-Key: bq_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "crm-progression-sink",
    "url": "https://api.your-app.com/bricqs/webhooks",
    "events": ["badge.earned.v1", "tier.changed.v1", "reward.claimed.v1"]
  }'
Errors
StatusCodeWhen it fires
401AUTH_UNAUTHENTICATEDNo admin credential supplied.
403AUTH_FORBIDDENCredential lacks the admin / gamify:admin scope.
422VALIDATION_INVALID_VALUEUnknown event name, non-HTTPS or SSRF-blocked URL, reserved [system] name prefix, or out-of-range retry/timeout.

Delivery contract

Every delivery is an HTTPS POST to your destination URL with these headers and a canonical JSON envelope. The same envelope (same id) also appears on the participant’s live SSE stream, so the two transports are correlatable.

Delivery headers
FieldTypeDescription
X-Bricqs-Signaturestrt={unix_timestamp},v1={hex}. HMAC-SHA256 over the string "{timestamp}.{raw_body}" with the destination secret.
X-Bricqs-EventstrEvent name (ping for test deliveries).
X-Bricqs-TimestampstrUnix timestamp used in the signature.
X-Bricqs-Delivery-IdstrStable across retries of the same delivery. Use this as your dedupe key.
Envelope body
FieldTypeDescription
idstrevt_-prefixed event id. Equals X-Bricqs-Delivery-Id.
eventstrEvent name, exactly as in the catalog.
timestampstrISO 8601 emission time (UTC).
tenant_idstrYour tenant id.
engagement_idOptional[str]Set when the event is engagement-scoped.
participant_idOptional[str]The affected participant.
datadictEvent payload. Schema per event in events.json. Can be {} on retries/replays (see non-guarantees).

Retry schedule

A delivery succeeds only on an HTTP 2xx response within timeout_seconds. Anything else (timeout, 4xx, 5xx) schedules a retry with this backoff:

attempt 1   immediate
attempt 2   +30 seconds
attempt 3   +5 minutes
attempt 4   +30 minutes
(total attempts = retry_count + 1; retry_count default 3, max 5)

After the final attempt the delivery is EXHAUSTED (terminal).
Recovery is manual: the replay endpoints above.

Subscribable events

The catalog at https://api.bricqs.co/.well-known/events.json is the contract: 25 events with JSON payload schemas. Versioned progression events (badge.earned.v1, tier.changed.v1, points.awarded.v1, streak.continued.v1, challenge.completed.v1, contest.prize_allocated.v1, referral.converted.v1, reward.claimed.v1, reward.points_expired.v1, and more) plus legacy engagement activity events (activity.completed, quiz.completed, ...).

Each catalog entry carries a status: active events fire today; deferred events (currently reward.expired.v1 and game.completed) are subscribable and schema-published but have no emitter yet. Do not block an integration waiting on a deferred event.

Non-guarantees

  • No ordering. Deliveries are not ordered, within or across participants. Retries make out-of-order arrival normal; process idempotently and order on the envelope timestamp if you need a sequence.
  • Replay payloads can be redacted. Retried and replayed deliveries can carry "data": {}. Treat the envelope as a trigger and re-fetch state via GET /api/v1/gamify/state/{participant_id}.
  • No secret rotation endpoint. Rotate by deleting and recreating the destination (two destinations can point at the same URL during the cutover).
  • Exhausted is terminal. Nothing re-sends automatically after the retry schedule; use the replay endpoints.

Next steps