Operations: data fabric
Bricqs is built around a small set of standard fields, deliberate PII handling, and per-tenant access controls. This page covers what data lives where, how PII is masked, how GDPR exports and erasure work, and how to wire outbound data flows safely.
Key takeaways
Quick read- Eleven standard fields cover the canonical PII surface: email, name parts, mobile, country code, DOB, gender, city, postal code, external_id.
- Masking is policy-based and enforced server-side on read. Clients cannot bypass it.
- Every PII read produces an audit log row. Required for GDPR and SOC 2.
- GDPR erasure nullifies fields; it does not delete events. Audit trails stay intact.
- Outbound webhooks support per-event redaction so PII never leaves your tenant unintentionally.
Standard fields
The canonical PII surface
Every participant has these fields. Profile-enrichment routines auto-coalesce values from form submissions, surveys, and explicit upserts.
Standard fields (canonical IDs):
email
first_name
last_name
full_name
mobile_number
country_code
date_of_birth
gender
city
postal_code
external_id
Custom fields:
Anything else (preference flags, behavioural attributes).
Marked PII at field-definition time if applicable.Masking
What clients see by default
| Field | Default mask | Full read requires |
|---|---|---|
| a***@domain.com | scope: read:pii | |
| mobile_number | Last 4 digits | scope: read:pii |
| first_name / last_name | First 2 chars + *** | scope: read:pii |
| full_name | Initials only | scope: read:pii |
| date_of_birth | Year only | scope: read:pii |
| city / postal_code | Visible | (no extra scope) |
| external_id | Visible | (no extra scope) |
Audit log
Every PII access is logged
pii_access_log row format:
id UUID
tenant_id UUID
actor_type "admin" | "system" | "webhook"
actor_id admin user id, system component, or webhook subscription id
participant_id whose PII was read
fields_accessed JSON array of canonical field names
row_count 1 (single read) or N (bulk export)
export_format "json" | "csv" | null
ip_address INET
occurred_at timestamptz
The pii_access_log is recorded server-side (there is no public query endpoint
today); surface it via your own database access or warehouse pipeline. Required
for GDPR and SOC 2 audits. Retain for at least 12 months by default; longer per
your DPA.GDPR export
Article 15 (right of access)
There is no participant export endpoint today. Erasure exists; export does
not. To satisfy an access request, assemble the bundle yourself:
profile + progression GET /api/v1/gamify/state/{participant_id}?include=...
reward history from your captured reward.claimed.v1 webhook stream
events you sent from your own event store / warehouse
Keep a copy of what you send Bricqs; that plus the state read is the record of
access. Do not promise self-serve export from Bricqs until the endpoint ships.Roadmap item, not shippable today. Build the access bundle from the state API plus your own captured stream.
GDPR erasure
Article 17 (right to be forgotten)
# Hard delete:
curl -X DELETE https://api.bricqs.co/api/v1/gamify/admin/participants/p_8a3f \
-H "X-API-Key: bq_live_..." # admin-scoped key
# Anonymize instead (nulls PII, keeps ledger for audit):
curl -X DELETE "https://api.bricqs.co/api/v1/gamify/admin/participants/p_8a3f?anonymize=true" \
-H "X-API-Key: bq_live_..."Anonymize nullifies PII while retaining events/facts, so aggregate analytics and contest leaderboards stay intact (the participant becomes a 'deleted user'). The operation records per-table rowcounts as audit evidence. Required pattern for most jurisdictions.
Outbound
Stream events to your CDP or warehouse
curl -X POST https://api.bricqs.co/api/v1/gamify/webhooks \
-H "X-API-Key: bq_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "cdp-sink",
"url": "https://api.your-app.com/bricqs/webhooks",
"events": ["challenge.completed.v1", "reward.claimed.v1"]
}'
# Note: Bricqs does not redact PII per-field on outbound webhooks. If your
# sink must not receive PII, filter it in your receiver before forwarding, or
# subscribe only to events that do not carry it. Deliveries are HMAC-signed;
# verify the signature in your receiver.Subscribe a receiver per system. When a system does not need full PII, the participant_id in the payload is enough to look up the user in your authoritative store; filter the rest in your receiver.
CDP and warehouse
Sync to your data layer
Outbound webhooks
Real-time. HMAC-signed. The primary integration point for triggering CRM and ESP workflows and for feeding a warehouse via your own sink.
Your own pipeline
Land the webhook stream in your warehouse (Snowflake, BigQuery) with a receiver you own. There are no built-in scheduled exports today.
Inbound events
Push CDP-driven or warehouse-derived signals back in via the standard ingest API as events. There are no prebuilt reverse-ETL connectors today.
Direct read API
GET /api/v1/gamify/admin/participants lists participants; per-participant state via GET /api/v1/gamify/state/{id}. Rate-limited; not intended for bulk loads.
Common mistakes
What goes wrong
Granting read:pii to all admin keys. Audit logs balloon; insider risk grows.
Issue read:pii only to keys that actually need it (CSV export tools, support consoles). Most ops scripts can run on masked data.
Treating erasure as a delete. Aggregate metrics break.
Erasure nullifies PII fields; it does not remove events. Contest history and leaderboards stay intact under 'deleted user'.
Sending full PII over webhooks to systems that do not need it.
Bricqs does not redact per-field on outbound webhooks. Filter PII in your receiver, or subscribe only to events that do not carry it; the receiving system gets participant_id and reads its own store if it needs more.
Ignoring the audit log retention requirement.
Archive pii_access_log to your warehouse for the term required by your DPA. The Bricqs default retention is 12 months; longer needs explicit configuration.
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.
