BricqsBricqs
Documentation

API Reference

REST API endpoints, authentication methods, rate limits, metering, and usage quotas. All SDK methods map to these endpoints — this reference documents what happens under the hood.

Base URL

https://api.bricqs.ai/api/v1

All API endpoints are relative to this base URL. Self-hosted deployments use your custom domain.

Authentication

The Bricqs API uses two authentication methods depending on the endpoint type.

API Key Authentication

Used by the React SDK, Headless SDK, and server-side integrations. Pass your API key in the X-API-Key header.

# API Key header
curl -X GET https://api.bricqs.ai/api/v1/public/eligibility \
  -H "X-API-Key: bq_live_your_key_here" \
  -H "Content-Type: application/json"
Key format: bq_live_ (production) or bq_test_ (testing) followed by 32 hex characters. Keys are hashed server-side — the plaintext is shown once on creation.

Session-Based (Anonymous)

Public endpoints for participant-facing operations (activities, points, badges) use session-based identification. No API key required — the session ID is passed as a query parameter or in the request body.

# Session-based request
curl -X POST https://api.bricqs.ai/api/v1/activities/{activityId}/complete-with-actions \
  -H "Content-Type: application/json" \
  -d '{"session_id": "sess_abc123", "engagement_id": "eng_uuid", ...}'

Rate Limits & API Metering

All API endpoints are rate-limited to ensure fair usage and platform stability. Limits are enforced at three levels: per-IP, per-API key, and per-tenant.

ScopeDefault LimitWindowNotes
Per IP100 requests60 secondsApplies to all endpoints. Prevents single-client abuse.
Per API Key1,000 requests60 secondsCustomizable per key in Settings. Aggregates all IPs using that key.
Per Tenant (Public)200 requests60 secondsPublic-facing endpoints. Plan-tier dependent.
Burst (Ingestion)100 requests1 secondEvent ingestion endpoints only. Prevents burst spikes.

Rate Limit Headers

Every API response includes rate limit information in the headers:

HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 987
X-RateLimit-Reset: 1707700800

# When rate limited:
HTTP/1.1 429 Too Many Requests
Retry-After: 45
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1707700800
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current window.
X-RateLimit-RemainingRemaining requests in the current window.
X-RateLimit-ResetUnix timestamp (seconds) when the window resets.
Retry-AfterSeconds to wait before retrying (only on 429 responses).

Plan-Based Usage Limits

API quotas scale with your plan. Rate limits, participant caps, and API key allocations increase with each tier.

FeatureStarterGrowthScaleEnterprise
Participants / month5,00025,000100,000Unlimited
API requests / minute2001,0005,000Custom
API keys21050Unlimited
Event ingestion / day10,000100,0001,000,000Custom
Headless SDK-IncludedIncludedIncluded
Concurrent engagements31050Unlimited
Headless SDK availability: The Headless SDK (custom UI hooks) is available on Growth plans and above. Starter plans can use the Script Tag, iframe, and React SDK (iframe-based) integrations.

Endpoint Reference

All endpoints called by the SDK. Public endpoints use session-based auth; protected endpoints require an API key.

ActivitiesPublic

MethodEndpointDescription
POST/activities/{activityId}/validateServer-side validation (spin wheel result calculation, quiz scoring). Used by useSpinWheel.spin().
POST/activities/{activityId}/complete-with-actionsComplete activity and execute all on-completion actions atomically (points, badges, rewards). Returns ActionResults.
GET/activities/{activityId}/eligibilityCheck participation limits (max attempts, cooldown period).
POST/activities/facts/emitEmit a custom fact. Set trigger_challenge_evaluation: true to update challenge progress.

PointsPublic

MethodEndpointDescription
POST/points/balanceGet current points balance for a session. Used by usePoints().
POST/points/transactionsGet points transaction history.

BadgesPublic

MethodEndpointDescription
GET/public/badges/statusGet badge earned/unearned status for a session. Supports filtering by badge_codes. Used by useBadges().

ChallengesPublic

MethodEndpointDescription
GET/public/challengesGet active challenge for an engagement. Returns objectives, milestones, and enrollment status.
POST/public/challenges/{id}/enrollEnroll a participant in a challenge. Used by useChallenge.enroll().
GET/public/challenges/{id}/progressGet challenge progress for a session (objective completion, milestones reached).
GET/public/challenges/{id}/leaderboardGet challenge leaderboard rankings.

LeaderboardsPublic

MethodEndpointDescription
GET/public/leaderboards/{code}Get progression leaderboard by code. Computed on-the-fly. Used by useLeaderboard().

RewardsPublic

MethodEndpointDescription
GET/public/rewards/claimedGet all rewards claimed by a session. Used by useRewards().

EligibilityAPI Key Required

MethodEndpointDescription
GET/public/eligibilityEvaluate trigger rules (URL, time, frequency, user attributes). Used by useEligibility().
POST/public/impressionsRecord an impression for frequency cap tracking.
GET/public/engagements/{id}/embed-urlResolve the runtime embed URL for an engagement.

Event IngestionAPI Key Required

MethodEndpointDescription
POST/ingest/eventsAsync event ingestion (<50ms response). Event queued to Redis Stream for background processing.
POST/ingest/events/batchBatch event ingestion (up to 100 events per request).
POST/ingest/events/syncSynchronous event processing. Returns event_id and fact_id. Best for testing and debugging.
Example — Async Event Ingestion
curl -X POST https://api.bricqs.ai/api/v1/ingest/events \
  -H "X-API-Key: bq_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "event_name": "purchase_completed",
    "participant_id": "user_123",
    "properties": {
      "amount": 49.99,
      "currency": "USD",
      "product_id": "prod_abc"
    },
    "timestamp": "2026-02-14T10:30:00Z"
  }'

# Response (< 50ms)
{
  "accepted": true,
  "message_id": "1707900600000-0"
}
Example — Batch Ingestion
curl -X POST https://api.bricqs.ai/api/v1/ingest/events/batch \
  -H "X-API-Key: bq_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {"event_name": "page_view", "participant_id": "user_123", "properties": {"page": "/products"}},
      {"event_name": "add_to_cart", "participant_id": "user_123", "properties": {"product_id": "prod_abc"}},
      {"event_name": "purchase_completed", "participant_id": "user_123", "properties": {"amount": 49.99}}
    ]
  }'

EngagementsPublic

MethodEndpointDescription
GET/sites/{tenantSlug}/{siteSlug}Get published engagement by slug. Returns full site definition including components and canvas.

API Key Management Endpoints

Manage API keys programmatically. These endpoints require JWT authentication (Builder admin login).

MethodEndpointDescription
POST/events/api-keysCreate a new API key. Returns the plaintext key (shown once).
GET/events/api-keysList all API keys for the tenant (key prefixes only, not full keys).
PATCH/events/api-keys/{id}Update key name, scopes, or rate limit.
DELETE/events/api-keys/{id}Revoke (soft-delete) an API key. Takes effect immediately.

Error Responses

All API errors follow a consistent format:

// Error response format
{
  "detail": "Human-readable error message"
}

// Common HTTP status codes
400 Bad Request      — Invalid parameters or request body
401 Unauthorized     — Missing or invalid API key
403 Forbidden        — API key doesn't have required scope
404 Not Found        — Resource doesn't exist
409 Conflict         — Duplicate action (e.g., already enrolled)
429 Too Many Requests — Rate limit exceeded (check Retry-After header)
500 Internal Error   — Server error (please report)

SDK Error Handling

The SDK handles common error scenarios automatically. For custom error handling:

// React SDK
<BricqsEngagement
  id="YOUR_UUID"
  onError={(error) => {
    if (error.status === 429) {
      showToast('Please wait a moment and try again');
    } else if (error.status === 404) {
      showToast('This engagement is no longer available');
    } else {
      console.error('Bricqs error:', error);
    }
  }}
/>

// Headless SDK
const quiz = useQuiz({ engagementId: '...', activityId: '...', config });
// Errors are caught during submit()
try {
  await quiz.submit();
} catch (error) {
  // Handle submission errors
  console.error('Submit failed:', error);
}

Next Steps