# Versioning and deprecation

How the Signal API changes over time, and the commitments that let you build against it without watching for surprises. The short version: additive changes never break you, breaking changes get a new version, and anything we retire is announced long in advance.

## Additive by default

Most changes are additive and ship on the current version with no version bump and no action from you:

- a new optional request field
- a new field on a response object
- a new stream template
- A new `response_action` value in the cue vocabulary
- a new error code on an existing status

Build tolerant and these are free: ignore response fields you do not recognize, and do not hard-code a closed list of templates, actions, or error codes. The [cue response](https://uphealth.us/docs/concepts-response) is documented as a minimum shape, not a maximum.

## Breaking changes

A change that could break a tolerant integration — removing or renaming a field, changing a type, tightening validation, or altering the meaning of an existing value — ships under a **new version** (a new path prefix), never silently on the current one. The version you integrated against keeps behaving the way it did the day you shipped.

## Deprecation and Sunset

When a version or a documented field is on a path to retirement, two things happen well before it goes away:

- Responses carry a `Sunset` response header (RFC 8594) with the date the behavior is scheduled to change, so a deprecation is detectable in code, not just in a blog post.
- We give **six to twelve months** of notice and email the contact on every affected key before anything is removed.

Nothing in v1 is deprecated today. This is the commitment for when something eventually is.

## Forward-compatible by design

The cue vocabulary is the live proof of the additive policy. The set of `response_action` values grows over time, and the API is deliberately tolerant of that growth: a well-formed but unrecognized value is **accepted** (a `200` ), folded to the `acknowledge` class for scoring, and echoed back to you as `normalized_action` so you can see what happened. Only a malformed value returns `422 invalid_feedback` . So when you read a `response_action` you do not recognize, treat it as `acknowledge` — a low-signal acknowledgement — and your integration keeps working as the vocabulary widens. The full rule is in [Cues & feedback](https://uphealth.us/docs/concepts-cues).

## API change log

Every change to the `/v1/signal/streams` surface since launch, oldest first. Each row is the change as it shipped; none of them bumped the version, because every one is additive under the policy above. Rows dated 2026-05-23 are the launch baseline.

| Date | Endpoint | Version | Change | Notes |
| --- | --- | --- | --- | --- |
| 2026-05-23 | `POST /v1/signal/streams` | v1 (initial) | `INITIAL` | Create a new stream. Body: template_id + mode + patient_ref + audience tags (this call enrolls the member). |
| 2026-05-23 | `GET /v1/signal/streams/:id` | v1 (initial) | `INITIAL` | Read stream state + the current cue. Idempotent, safe to poll. |
| 2026-05-23 | `POST /v1/signal/streams/:id/cue` | v1 (initial) | `INITIAL` | The repeating loop. Returns message + safety + receptivity. |
| 2026-05-23 | `GET /v1/signal/sandbox-topics` | v1 (initial) | `INITIAL` | Browse the curated subset a stream draws from. |
| 2026-06-14 | `POST /v1/signal/streams` | v1 | `ADDITIVE` | Optional Idempotency-Key request header — a retried create replays the original stream instead of opening a duplicate. |
| 2026-06-14 | All /v1 responses | v1 | `ADDITIVE` | RateLimit-Limit / -Remaining / -Reset headers on Discovery-tier responses (where the cue cap applies), plus an X-Request-Id on every response — for client-side backoff and support correlation. |
| 2026-06-15 | `POST /v1/signal/streams/:id/cue` | v1 | `ADDITIVE` | Forward-compatible response_action — a well-formed but unrecognized value is accepted and echoed back as normalized_action; only a malformed value is rejected. |

The MCP server carries its own version line and is logged with the rest of the developer surface on the [changelog](https://uphealth.us/signal/changelog#developer-surface).

## Changelog and status

Template versions, webhook events, and the developer surface (SDKs, MCP, catalogs) are logged on the [changelog](https://uphealth.us/signal/changelog) . Current operational status across every surface is on the [status page](https://uphealth.us/status).

- [What changed](https://uphealth.us/signal/changelog) — Template versions, webhook events, and the developer surface — every shipped change outside the API log above.
- [Live status](https://uphealth.us/status) — Operational status across Signal, Reach, Compass, and the member surface.
- [Cues & feedback](https://uphealth.us/docs/concepts-cues) — The response_action vocabulary and the forward-compatible tolerance in full.

---

_Uphealth Signal developer docs · [View on uphealth.us](https://uphealth.us/docs/versioning) · OpenAPI spec: https://uphealth.us/openapi/signal-v1.yaml · Verified against API v1 on 2026-07-22._
