Skip to content
Real-time gateway healthy

External system plane

Integration Center

External systems provision, orchestrate, embed, and receive events through OAuth2 machine contracts — never by replaying host links.

Docs
OAuth2 clients6tenant-bound
Webhooks healthy12/12All delivering
Events today8,214+412last hour
Approved embeds4origins allowlisted

OAuth2 clients

Tenant-bound machine contracts
SAMA–SCB
OAuth2 clients
ClientControl profileScopesAuthStatusActions
Town Hall Eventscli_townhall · cli_9f2a… provisioner poll.session.createpoll.session.schedule client-credentials Active
Academy LMScli_lms · cli_3b7c… provisioner dynamic_author poll.session.createpoll.question.authorpoll.results.read client-credentials Active
Meeting Orchestratorcli_meet · cli_a1d4… orchestrator poll.session.activatepoll.question.controlpoll.results.read mTLS Active
Insights Warehousecli_bi · cli_6e08… observe_only poll.results.readpoll.event.subscribe client-credentials Active
Command Bridge (exceptional)cli_bridge · cli_0c55… full_live_control poll.session.commandpoll.question.control mTLS Suspended
Clients authenticate machine-to-machine and are bound to one tenant. Client secrets are stored only as keyed hashes and never returned after rotation.

Control profiles

Least-privilege presets bound at registration

observe_only

Read aggregate results and subscribe to events. No write path to sessions.

poll.results.readpoll.event.subscribe
Safe default

provisioner

Create and schedule sessions ahead of time. Cannot activate or drive a live session.

poll.session.createpoll.session.schedulepoll.results.read
Recommended for event & meeting systems

orchestrator

Activate sessions and drive question flow in step with an external meeting timeline.

poll.session.activatepoll.question.control
Explicit tenant approval

dynamic_author

Author questions programmatically from an allowlisted schema. Cannot change governance.

poll.question.authorpoll.session.create
Restricted · schema allowlist

full_live_control

Issue unsafe live commands: pause, close, finalize. Reserved for certified bridges.

poll.session.commandpoll.question.control
Exceptional · security & architecture approval
No profile may change locked governance fields (anonymity, residency, retention) after joins open.

Webhooks are signed with an HMAC over the payload plus a timestamp and event id, retried with exponential backoff, and dead-lettered after exhaustion. High-frequency raw vote events are NOT delivered as webhooks — consumers receive throttled aggregates or pull the results API.

Webhook catalog

Delivered event types
poll.session.*Lifecycle of a session
createdlobby_openedstartedpausedclosedfinalized
poll.question.*Question flow
createdactivatedclosed
poll.results.*Aggregate outcomes
revealedupdated throttled
OperationalModeration & health
poll.qa.moderation.changedpoll.capacity.warningpoll.session.degraded

Signed webhook example

poll.results.revealed
# Headers
X-Basirah-Signature: sha256=t=1752670800,v1=9f2a3c…d41b
X-Basirah-Timestamp: 1752670800
X-Basirah-Event-Id: evt_4f7c22a9

{
  "eventId": "evt_4f7c22a9",
  "sessionId": "poll-8842",
  "sequence": 1042,
  "aggregateVersion": 57,
  "eventType": "poll.results.revealed",
  "occurredAt": "2026-07-16T14:41:00Z",
  "data": {
    "questionId": "q_03",
    "totalResponses": 3088
  }
}
Verify the HMAC and reject timestamps older than 5 minutes to prevent replay.

Approved embed origins

CSP frame-ancestors allowlist
https://events.sama.sahttps://portal.academy.sa

A per-tenant, per-session Content-Security-Policy frame-ancestors directive is generated at activation, so only allowlisted origins may frame the participant and stage views.

Embeddable views

Participant viewVote and see aggregate results inside the host page.
Stage viewLarge-format results for projection and streaming.
postMessage schema validationEvery cross-frame message is validated against a versioned schema.
Host control embeddingDisabled by default — host commands are never framed by third parties.

Generated CSP

poll-8842
# Per-tenant, per-session · SAMA–SCB
Content-Security-Policy:
  frame-ancestors
    'self'
    https://events.sama.sa
    https://portal.academy.sa;
Tokens are never placed in iframe query params after activation.

Session command contract

Unsafe live commands
# POST /v1/sessions/poll-8842/commands
Idempotency-Key: cmd_7b19e0c4
If-Match: "aggregateVersion:57"
X-Correlation-Id: corr_a3f1…

{
  "commandId": "cmd_7b19e0c4",
  "expectedVersion": 57,
  "requestedAt": "2026-07-16T14:42:10Z",
  "reason": "host requested pause",
  "payload": {
    "command": "session.pause"
  }
}

A stale expectedVersion returns 409 SESSION_VERSION_CONFLICT. Responses return the new aggregateVersion plus the latest event sequence so the caller can reconcile.

SessionRealtimeEvent envelope

Delivered to subscribers
{
  "eventId": "evt_4f7c22a9",
  "sessionId": "poll-8842",
  "sequence": 1043,
  "aggregateVersion": 58,
  "eventType": "poll.session.paused",
  "occurredAt": "2026-07-16T14:42:11Z",
  "correlationId": "corr_a3f1…",
  "data": {
    "pausedBy": "cli_meet"
  }
}

Every event carries a monotonic sequence and the aggregateVersion it produced, so consumers detect gaps, order events deterministically, and reconcile against a command response.