Events ingestion
Events are the only entry point for action data. POST one event, the rules engine fans it out to challenges, contests, and progression. This page covers the three ingestion endpoints, idempotency, batching, and retries.
Key takeaways
Quick read- Three endpoints: single (async), batch (async), sync (slower but returns evaluation results).
- Always include an idempotency_key. Retries should not double-credit.
- Soft validation: unknown event types and attributes are accepted with a warning, never rejected.
- Batch up to 500 events per request. Above that, stream them serially.
- Sync is for client-driven flows that need an immediate response (challenge advanced, points granted). Async is the default.
Endpoints
Three ways to send events
POST /ingest/events
Async single event. Default. Returns 202 immediately; the rules engine processes it within 100 to 500ms.
POST /ingest/events/batch
Async batch. Up to 500 events. Returns 202 with per-event idempotency status.
POST /ingest/events/sync
Synchronous. Returns the rules engine evaluation (challenges advanced, points granted) in the response. Higher latency; use sparingly.
Single event
The default path
One event, one POST. The rules engine processes it asynchronously. Most integrations use this.
curl -X POST https://api.bricqs.co/api/v1/ingest/events \
-H "Authorization: Bearer bq_live_admin_..." \
-H "X-Bricqs-Tenant: tenant_brand_xyz" \
-H "Content-Type: application/json" \
-d '{
"participant_id": "p_8a3f",
"event_type": "purchase_completed",
"attributes": {
"amount": 1250,
"currency": "INR",
"category": "skincare",
"items": ["sku_42", "sku_71"]
},
"occurred_at": "2026-04-30T10:42:00Z",
"idempotency_key": "p_8a3f:order_4271",
"source": "checkout-service"
}'
# response
HTTP/1.1 202 Accepted
{
"event_id": "evt_01HW...",
"duplicate": false
}Idempotency
The single most important field
Networks fail. Clients retry. Without an idempotency key, a flaky network can double-credit the user. With one, every retry is safe.
Recommended format: <participant_id>:<event_subject>:<period>
Examples:
p_8a3f:order_4271 one-shot purchase
p_8a3f:streak_tick:2026-04-30 daily streak (one per day)
p_8a3f:q_fit_basics:2026-04-30 quiz attempt (one per day per quiz)
p_8a3f:referral:user_invited:p_91x referral signup
Behavior:
Same key inside 24 hours = duplicate, ignored. Returns 200 with duplicate: true.
Different attributes with same key = first write wins. Following requests are dropped.
No key supplied = no dedup. Strongly discouraged.Batch
Up to 500 events in one POST
Use batch when ingesting historical data, replaying from a queue, or fanning out across many participants in tight loops.
curl -X POST https://api.bricqs.co/api/v1/ingest/events/batch \
-H "Authorization: Bearer bq_live_admin_..." \
-H "X-Bricqs-Tenant: tenant_brand_xyz" \
-H "Content-Type: application/json" \
-d '{
"events": [
{
"participant_id": "p_8a3f",
"event_type": "lesson_completed",
"attributes": { "lesson_id": "l_001" },
"idempotency_key": "p_8a3f:l_001"
},
{
"participant_id": "p_91xx",
"event_type": "lesson_completed",
"attributes": { "lesson_id": "l_002" },
"idempotency_key": "p_91xx:l_002"
}
// up to 500 events
]
}'
# response
HTTP/1.1 202 Accepted
{
"accepted": 487,
"duplicates": 13,
"results": [
{ "idempotency_key": "p_8a3f:l_001", "event_id": "evt_01HW...", "duplicate": false },
{ "idempotency_key": "p_91xx:l_002", "event_id": null, "duplicate": true }
// ...
]
}Sync
When the client needs an immediate result
The default async path is fast (100 to 500ms processing) but the client does not see the rules-engine outcome in the response. Use sync when the UI needs to know what changed.
curl -X POST https://api.bricqs.co/api/v1/ingest/events/sync \
-H "Authorization: Bearer bq_live_admin_..." \
-H "X-Bricqs-Tenant: tenant_brand_xyz" \
-H "Content-Type: application/json" \
-d '{
"participant_id": "p_8a3f",
"event_type": "quiz_completed",
"attributes": { "quiz_id": "q_fit_basics", "score": 100 },
"idempotency_key": "p_8a3f:q_fit_basics:2026-04-30"
}'
# response (synchronous evaluation)
HTTP/1.1 200 OK
{
"event_id": "evt_01HW...",
"results": {
"points_granted": 50,
"tier_changed": null,
"challenge_progress": [
{
"challenge_id": "fitness_30day",
"objective_id": "complete_5_quizzes",
"from": 2,
"to": 3,
"completed": false
}
],
"badges_earned": [],
"contest_score_delta": [
{ "contest_id": "april_quiz_cup", "delta": 100, "new_rank": 12 }
]
}
}Sync responses include the rules-engine outcome. Latency: 200 to 800ms typical, depending on how many programs the event triggers.
Retry policy
What to do when ingestion fails
Status codes you will see:
202 Accepted Async path. Event queued, rules engine will process.
200 OK Sync path or duplicate. Body has details.
400 Bad Request Schema error. Do NOT retry; fix the payload.
401 Unauthorized Bad key. Do NOT retry; fix auth.
429 Too Many Rate limited. Retry with Retry-After.
500/502/503/504 Server error. Retry with exponential backoff.
Retry strategy for 429 and 5xx:
attempt 1 wait 250ms + jitter
attempt 2 wait 500ms + jitter
attempt 3 wait 1000ms + jitter
attempt 4 wait 2000ms + jitter
attempt 5+ wait 5000ms + jitter, log a warning
Always include the idempotency_key. Retries are safe.Common mistakes
What goes wrong on first integration
Sending events without idempotency keys. Network blips double-credit users.
Always include idempotency_key. Use deterministic format: participant_id : subject : period.
Multiple events to multiple endpoints when one event would do. Wasteful and inconsistent.
One event per user action. The rules engine fans it out to challenges, contests, and progression. You almost never need to call points and challenges directly.
Using sync everywhere. Higher latency; the user feels it.
Default to async. Use sync only on screens where the client needs the rules-engine result immediately (a 'congratulations' moment with a live points total).
Batching infrequently used event types. Mixing 50 schemas in one batch makes failures hard to triage.
Group by event_type when batching. One quiz_completed batch, one purchase_completed batch. Easier to debug.
Ignoring the duplicate flag in the response. Clients re-celebrate the same action.
Check duplicate. If true, suppress the celebration UI. The points and progress did not change.
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.
