Webhooks v0 Overview
Legacy /v0 Webhooks API (Alpha). Prefer v1 Webhooks for new integrations.
Legacy (
/v0). New integrations should use v1 Webhooks (https://api.ro.am/v1). This Alpha surface remains supported for existing callers but is frozen — see Previous Versions and the Migration Guide.
The Roam HQ Events API (Alpha) delivers real-time notifications to your application via webhooks. Subscribe to events and receive HTTP callbacks when things happen in your Roam workspace.
OpenAPI Spec: webhooks.json
Configuring Webhooks
You can configure webhooks in two ways:
- Static: In Roam Administration > Developer > API Client, add webhook URLs directly to your app configuration
- Dynamic: Use the subscription endpoints below to manage webhooks programmatically
Destination URLs may be up to 1024 characters (static config and
webhook.subscribe). Longer values are rejected with HTTP 400 /
invalid_parameter.
Subscription Endpoints
| Endpoint | Method | Description |
|---|---|---|
/webhook.subscribe | POST | Create or update a webhook subscription |
/webhook.unsubscribe | POST | Remove a webhook subscription |
Available Events
| Event | Description |
|---|---|
chat:message:dm | Direct message received by your app |
chat:message:channel | Channel message in a group where your app is a member |
chat:message:mention | Message that @mentions your app |
chat:message:reaction | Emoji reaction added to a message |
recording:saved | Meeting recording is ready for download |
transcript:started | Magic Minutes has started on a meeting |
transcript:saved | Meeting transcript (Magic Minutes) is available |
lobby:booked | New booking created for a lobby |
user:status:update | User checked in or out of the Roam |
onair.event.created | On-Air event is created |
onair.event.updated | On-Air event is updated |
onair.event.canceled | On-Air event is canceled |
onair.guest.rsvp | Guest RSVP status changed |
onair.guest.added | Guest(s) added to an event |
magicast.created | A magicast is created and ready |
Access Models
Webhooks support both Organization access and Personal access. The same events are available in both modes, but the scope differs:
- Organization access: Webhooks deliver events for all activity across the workspace (e.g. all messages in public groups, all meeting transcripts).
- Personal access: Webhooks deliver only events involving the authenticated user (e.g. only your DMs, only your meeting transcripts).
See the Access Models guide for details on choosing the right model.
Webhook Payload Format
All webhooks are delivered as POST requests with JSON payloads. Your endpoint should return a 2xx status to acknowledge receipt.
Delivery retries
Delivery is best-effort with bounded in-memory retries:
- Up to 4 HTTP attempts (1 initial + 3 retries) for transient
failures: network/transport errors, HTTP
5xx, and HTTP429. - Each attempt must return a 2xx within 3 seconds or it counts as failed.
- The retries are near-immediate (about a second), then about +1 minute, then about +5 minutes — roughly a six-minute window end to end, matching Slack's Events API ladder.
- Retries carry
Roam-Retry-Num(1,2, or3) andRoam-Retry-Reason(transport,http_5xx, orhttp_429); the initial attempt carries neither.webhook-idis identical on every attempt of the same event — de-duplicate on it. Retry-Afteron a429or503is honored in place of the next wait, capped at 5 minutes.- Non-retryable client errors (
4xxother than 429) fail immediately. - Pending retries are held in memory only: a Roam process restart drops them, and a bounded pending-retry set sheds them under extreme load.
- If all attempts fail, the event is dropped for that delivery; the subscription is kept — repeated failures never auto-disable it — and the next event is attempted fresh. This is not a durable outbox — design endpoints to be idempotent and available.
Signature Verification
Webhooks are signed using the Standard Webhooks specification. Each request includes three headers for verification:
| Header | Description |
|---|---|
webhook-id | Unique identifier for this webhook delivery |
webhook-timestamp | Unix timestamp (seconds) when the webhook was sent |
webhook-signature | HMAC-SHA256 signature of the payload |
Your Webhook Signing Secret is available in Roam Administration > Developer > API Client.
Every API client type that can receive webhooks is issued a signing secret:
API Key, OAuth, and Personal Access Token apps all get a
whsec_… secret (one secret per app, shared by every install — Slack-style).
OAuth apps previously shipped without a secret and delivered unsigned payloads;
new and backfilled OAuth clients now sign deliveries the same way as API Key
clients.
Always verify the Standard Webhooks headers; reject deliveries that fail
signature verification.
To verify a webhook:
- Concatenate:
{webhook-id}.{webhook-timestamp}.{payload} - Compute HMAC-SHA256 using your signing secret (base64-decoded)
- Compare with the signature in
webhook-signatureheader
We recommend using the standard-webhooks client libraries for verification:
import { Webhook } from "standardwebhooks";
const wh = new Webhook(signingSecret);
const payload = wh.verify(requestBody, requestHeaders);
Delivery Behavior
- Timeout: Webhook requests timeout after 3 seconds. Ensure your endpoint responds quickly.
- Retries: Webhooks are not automatically retried. If your endpoint returns a non-2xx status or times out, the delivery is logged but not reattempted.
- Order: Webhooks are delivered asynchronously and may arrive out of order.
For reliable processing, we recommend:
- Acknowledge webhooks immediately with a 200 response
- Process webhook data asynchronously in a background job
- Use the
webhook-idheader for idempotency
Filtering
Some events support filters to limit notifications:
lobby:booked: Filter bylobbyIdto receive bookings for specific lobbies onlychat:message:reaction: Filter bycodesto only fire when a message carries a matching reaction. This gates delivery only — the payload still contains the message's fullreactionslist, so inspectreactions[].codein your handler to act on specific reaction typesonair.event.created,onair.event.updated,onair.event.canceled,onair.guest.added: Filter byeventIdto receive notifications for a specific event onlyonair.guest.rsvp: Filter byeventIdand/orstatusto receive notifications for a specific event or RSVP status
Authentication
Authorization: Bearer YOUR_TOKEN
Base URL
https://api.ro.am/v0
Have questions? Contact us via Roam Support Chat or email developer@ro.am.
Terms of Service
https://ro.am/terms