Bridges
A bridge is a one-way or two-way mirror between a ScaiWave room
and a room / channel on an external chat platform. Foreign users
appear in the ScaiWave room as bridge participants (shadows of
their identity on the source platform); local users appear in the
foreign system as whatever the bridge mapping defines.
Supported platforms#
- Slack — first-class. Slack Events API → ScaiWave; ScaiWave events → Slack incoming webhook or Bolt app.
- Discord — webhook-based.
- Microsoft Teams — Graph-based incoming + outgoing webhook.
- Remote ScaiWave — for installations that need the bridge-shape instead of full federation.
The shape#
A bridge has:
- A direction:
in(foreign → ScaiWave only),out(ScaiWave → foreign only), orboth. - A transport: Slack / Discord / Teams / ScaiWave.
- A room mapping: which ScaiWave room ↔ which foreign channel.
- A shared secret for HMAC-signing the webhook payloads in both directions.
- An active / paused state. Admins can pause without deleting.
Setting one up#
- Admin creates the bridge with
POST /v1/admin/bridges, specifying the transport, the ScaiWave room id, and (for outgoing) the foreign webhook URL. - ScaiWave generates a shared HMAC secret and returns it. Configure the foreign side with this secret.
- Foreign system POSTs to
/v1/bridges/{bridge_id}/inboundwith HMAC headers; ScaiWave verifies and creates abridgeparticipant shadow for the foreign sender (if not already present), then creates the message event in the room. - Outgoing: every event in the room is routed through the bridge relay ARQ job, which POSTs the foreign system's webhook with the right transport's payload shape.
Identity model#
Foreign users are stored as shadow participants:
participant_type = bridge.local_id= sanitised slug of their foreign identifier.display_name= their foreign display name.avatar_url= mirrored from the foreign platform when available.
The original sender's identity is also embedded in
event.content._imported_sender for export/audit. Shadow participants
don't count toward your tenant's participant limit.
Federation vs. bridges#
| Federation | Bridges |
|---|---|
| Symmetric, end-to-end signed | Asymmetric, HMAC-signed webhooks |
| Both sides are ScaiWave | One side can be Slack/Discord/Teams/anything |
| Foreign users have a real account elsewhere | Foreign users are shadows |
| Per-room, opt-in | Per-room, opt-in |
| No transformation | Format translation per platform |
| First-class member experience | Best-effort feature mapping (e.g. Slack threads ≈ ScaiWave threads) |
Choose federation when both sides are ScaiWave; bridges otherwise.
Failures#
- Slack rate-limit / 429 — outgoing relay backs off exponentially; message is retried up to 3 times before being marked failed in the audit log.
- HMAC mismatch — inbound message is rejected with 401 and logged for admin review.
- Foreign side unreachable — relay queues; messages drain when the foreign side comes back. Admin alert after 1 hour of failure.
Where to go next#
- Tutorial: Build an integration bridge.
- API: Bridges.