BricqsBricqs

API: webhooks

Bricqs delivers outbound events to your backend. Reward issuance, challenge completion, contest results, drop-off triggers. Each delivery is HMAC-signed and retried with exponential backoff.

Reading time7 minutes
Last updatedMay 2026

Key takeaways

Quick read
  • Subscribe per event_type and per tenant. Each subscription has its own URL and secret.
  • Every payload is HMAC-SHA256 signed with the subscription secret. Always verify before acting.
  • Retry policy: 5 attempts with exponential backoff over ~30 minutes. After that, the delivery is marked failed.
  • Idempotency on your side: dedupe by event_id. The same event can be redelivered.
  • Sub-1s response is required. Do work asynchronously after a 200; webhooks should not wait on your CRM.

Subscribe

Create a webhook subscription

POST /api/v1/admin/webhooks·bash
curl -X POST https://api.bricqs.co/api/v1/admin/webhooks \
  -H "Authorization: Bearer bq_live_admin_..." \
  -d '{
    "url": "https://api.your-app.com/bricqs/webhooks",
    "events": [
      "challenge.completed",
      "reward.issued",
      "contest.completed",
      "challenge.drop_off_at_72h"
    ],
    "secret": "wh_secret_..."
  }'

Generate the secret yourself or let Bricqs return one. Either way, store it server-side; never ship it to the browser.

Payload

Shape and headers

text
Headers:
  X-Bricqs-Signature: sha256=hex(hmac_sha256(secret, raw_body))
  X-Bricqs-Event:     challenge.completed
  X-Bricqs-Delivery:  d_01HW...
  X-Bricqs-Tenant:    tenant_brand_xyz
  Content-Type:       application/json

Body:
  {
    "id": "evt_01HW...",
    "type": "challenge.completed",
    "occurred_at": "2026-04-30T10:42:00Z",
    "tenant_id": "tenant_brand_xyz",
    "data": {
      "challenge_id": "fitness_30day_apr",
      "participant_id": "p_8a3f",
      "completed_at": "2026-04-30T10:42:00Z",
      "reward": { "id": "rwd_42", "type": "voucher", "value": 500 }
    }
  }

Verify

Always check the signature

app/api/bricqs/webhooks/route.ts (Next.js)·ts
import crypto from "crypto";

export async function POST(req: Request) {
  const raw = await req.text();
  const signature = req.headers.get("x-bricqs-signature") ?? "";

  const expected =
    "sha256=" +
    crypto
      .createHmac("sha256", process.env.BRICQS_WEBHOOK_SECRET!)
      .update(raw)
      .digest("hex");

  if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
    return new Response("Invalid signature", { status: 401 });
  }

  const event = JSON.parse(raw);

  // 1. Acknowledge fast (sub-1s)
  await queueForProcessing(event);

  // 2. Return 200 immediately
  return new Response("ok");
}

Use timingSafeEqual to avoid timing-attack leaks. Acknowledge inside 1 second; do real work in a queue.

Retries

What happens when you fail

text
Bricqs retries any non-2xx response.

Schedule:
  attempt 1   immediate
  attempt 2   ~1 minute later
  attempt 3   ~3 minutes later
  attempt 4   ~10 minutes later
  attempt 5   ~30 minutes later
  give up     mark delivery failed, expose in dashboard

Retry-Safe headers:
  X-Bricqs-Delivery is unique per delivery attempt
  event.id is the same across retries; dedupe by event.id

Manual replay:
  POST /admin/webhooks/:id/redeliver/:event_id
  Useful when fixing a downstream bug.

Event types

The most-used events

text
Lifecycle:
  challenge.completed
  challenge.drop_off_at_72h
  challenge.drop_off_at_168h
  contest.completed
  contest.disqualification

Rewards:
  reward.issued
  reward.claimed
  reward.expiring_in_7_days

Progression:
  tier.upgraded
  badge.earned
  streak.milestone_hit

Points:
  points.granted (only for direct grants; earn-rule grants are silent)
  points.expired

The full list is in the dashboard. New events ship monthly; subscriptions
default to ignore unknown types so you do not break on rollouts.

Common mistakes

What goes wrong

01Mistake

Verifying the parsed JSON instead of the raw body. Signature fails on every payload.

Fix

Read the raw body once, verify against it, then parse. Frameworks that auto-parse JSON break this; opt out for the webhook route.

02Mistake

Doing CRM and email work inside the webhook handler. Timeouts cause retries.

Fix

Queue the work, return 200, process async. Bricqs retries non-2xx; you want every delivery to succeed first try.

03Mistake

Using a single secret across many subscriptions.

Fix

One secret per subscription. Rotation becomes per-subscription, not all-or-nothing.

04Mistake

Ignoring redelivered events. CRM gets the same upgrade email twice.

Fix

Dedupe by event.id in your handler. The event.id is stable across redelivery.

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.