Skip to main content

API Versioning

The Roam API is versioned by date so we can evolve response and webhook payload shapes over time without breaking existing integrations. Your integration is pinned to a single version and never changes shape underneath you — you adopt new versions deliberately, when you're ready.

This page explains how versions work and what you need to do. If you're moving from the v0 Alpha API, start with the Migration Guide: v0 to v1 first — that's a one-time, larger jump. This page is about the ongoing, incremental versions within v1.

How versions are named

Versions are dates, in YYYY-MM-DD form. The current version is:

2026-08-20

/v1 in the base URL (https://api.ro.am/v1) is the API generation — a stable namespace that won't churn. The dated version is the revision within it that controls the exact shape of responses and webhook payloads. We will not mint a /v2 URL for routine shape changes; those ship as new dated versions.

v0 is the previous generation (https://api.ro.am/v0). It is frozen and not part of the dated-version scheme. See the Migration Guide.

Your integration's version

Every integration (API key, OAuth app, or Personal Access Token) has a default version, set once when the integration is created and pinned there:

  • New integrations are created on the latest version available at that time.
  • Existing integrations stay on the version they were created with.
  • Your version never advances automatically. A new Roam API version shipping does not change your integration's behavior. You upgrade when you choose to.

This is the key guarantee: code written against the version you're on keeps working, byte-for-byte, until you decide to move.

You can confirm which version a response was rendered with — every API response includes a header matching the version that shaped the body. For a client on the current default:

Roam-Version: 2026-08-20

(Older integrations still pinned to earlier versions receive those pins — for example Roam-Version: 2026-07-23 or the baseline 2026-06-01 — and the corresponding shapes.)

Overriding the version per request

To try a different version for a single request without changing your default, send the Roam-Version request header. Example — force the baseline shape while your client default is newer:

curl https://api.ro.am/v1/chat.history?chatId=88bebce7-6cbb-4666-96f9-5c02d73e6661 \
-H "Authorization: Bearer $ROAM_TOKEN" \
-H "Roam-Version: 2026-06-01"

Or target the current version explicitly:

curl https://api.ro.am/v1/chat.history?chatId=88bebce7-6cbb-4666-96f9-5c02d73e6661 \
-H "Authorization: Bearer $ROAM_TOKEN" \
-H "Roam-Version: 2026-08-20"

Resolution order for a REST request:

  1. The Roam-Version request header, if present.
  2. Otherwise, your integration's pinned default version.
  3. If neither is set (pre-versioning clients), the baseline version 2026-06-01.

Sending an unsupported version returns 400 with the list of supported versions.

Most integrations never send the header — they rely on their pinned default. Use the header to test a different version before adopting it.

Webhook versions

Webhooks are versioned too, but because Roam initiates the delivery there is no request to carry a header. Instead, the version is fixed on the subscription:

  • When you create a subscription with webhook.subscribe, it captures your integration's default version (or an explicit apiVersion you pass in the request body), and that subscription delivers that shape from then on.
  • Each delivery includes the Roam-Version header — and, from version 2026-07-07 onward, the envelope's apiVersion field — so your handler can confirm the shape it's receiving.

To move a subscription to a newer payload shape, create a new subscription on the new version (optionally alongside the old one) and retire the old one once you've cut over.

What changes between versions — and what doesn't

We make backward-compatible (additive) changes at any time, on every version, without a new version number. Write your integration to tolerate them. Specifically, you should expect and safely ignore:

  • New fields in responses and webhook payloads.
  • New endpoints and new webhook event types.
  • New optional request parameters.
  • New values in existing enum-style fields.

Build defensively: ignore unknown fields, and don't assume an enum will only ever return the values you've seen. An integration that rejects unexpected fields or values will break on a non-breaking change.

A new dated version is only introduced for backward-incompatible changes, such as:

  • Removing or renaming a field.
  • Changing a field's type or structure (for example, wrapping a payload in an envelope).
  • Changing a default behavior.

Because these only land in a new version, and your integration is pinned, they never reach you until you opt in.

Version history

VersionHighlights
2026-08-20 (current default)Chat membership for v1 push and most REST: organization apps hear a group only if they are a member; personal tokens ride the owner's membership (every message in those chats, not mention-only). {mention:true} restores mention-only. Organization chat.post and chat.startStream to a public group without joining remain allowed. Organization chat.search includes unjoined public groups in the bot's roam. New API keys, OAuth apps, and PATs pin here.
2026-08-07Slack mention grammar in message text on reads: groups render as <!subteam^uuid> (previously <@uuid>) and the broadcast as <!channel> (previously <@all>). Principals stay <@uuid>. The mentions list is unchanged.
2026-07-23Same delivery shapes as 2026-07-07.
2026-07-07Common webhook event envelope: type, eventId, timestamp, apiVersion, data. Route on type; business fields live under data.
2026-06-01 (baseline)First dated v1 pin. Webhook payloads are bare (no envelope). Pre-versioning clients that send no pin resolve here.

Subscriptions pinned to 2026-06-01 keep bare payload shapes byte-for-byte. Subscriptions on 2026-07-07 or newer receive the envelope. Moving a 2026-07-07 client to 2026-07-23 requires no code changes. Moving to 2026-08-07 changes only how mention tokens render in message text on reads (chat.history, chat.search, chat.link.resolve, and the chat.message webhook). Moving to 2026-08-20 applies membership to v1 chat push and most REST (organization chat.post / chat.startStream to public groups stay allowed without joining; organization chat.search includes unjoined public groups). Writes are not versioned: every version accepts both mention grammars (plus Slack-style |label suffixes and the legacy <@all> broadcast alias) on chat.post and chat.update.

Additive changes (all v1 pins, no new date): principal hydration / type fields, optional sender display overrides on message reads, and similar. Strict JSON decoders must ignore unknown properties. See Identity & Principals and Sender Profiles.

The v0 → v1 generation jump (IDs, endpoint renames, event names) is separate from dated pins — use the Migration Guide.

Adopting a new version

  1. Review the version history (and migration notes for the target pin).
  2. Test against it using the Roam-Version header (REST) or a second webhook.subscribe on the new version (webhooks), without touching production.
  3. Update your code to the new shapes.
  4. Update your integration's pinned default to the new version, and migrate any webhook subscriptions.

There's no rush — see the support window below.

Deprecation policy

  • Each version is supported for at least 12 months after a newer version is released.
  • As a version approaches end of life, REST responses include Deprecation and Sunset headers with the shutdown date.
  • After a version is sunset, REST requests pinned to it return 410 Gone. We will contact you well before this happens; no version is retired while integrations are still using it.

Best practices

  • Pin explicitly in code you care about. Relying on your account default is fine, but sending Roam-Version makes the shape your integration expects unambiguous and self-documenting.
  • Tolerate additive changes. Ignore unknown fields and unrecognized enum values rather than failing.
  • Check the delivery header on webhooks. Use Roam-Version to route payloads if you ever run more than one version.
  • Treat cursors and webhook timestamps as opaque. Pagination cursors are server-issued tokens — pass nextCursor back as cursor unchanged. Invalid cursors return error: "invalid_cursor". See Responses and Errors.
  • Version pin is stamped at client creation. New API keys, OAuth apps, and PATs receive the latest published version at registration time (currently 2026-08-20). The pin does not change when you redeploy or when Roam ships a newer version.

Questions?

Contact us via Roam Support Chat or email developer@ro.am.