# Protocol versions (https://docs.open-e2ee.dev/relay/protocol-versions.md)



A Relay protocol version is the wire that the OpenE2EE Signal Protocol SDK and the OpenE2EE Signal Protocol Relay agree on. The Relay reads one version from each request.

* A mailbox socket offers the subprotocol token `open-e2ee-relay.v1`, and the Relay echoes it.
* An HTTP request to a Relay route can send the header `x-open-e2ee-relay-protocol: 1`. The connection document and CORS preflight read no version.
* SDK 10.1.0 and later releases send the header `x-open-e2ee-relay-protocol: 1` on each HTTP request to a Relay route. They send no header on the fetch of the connection document.
* SDK 10.0.0 sends no header. The Relay reads a request without the header as version 1.
* The Relay serves SDK 10.0.0, 10.1.0, and 11.0.0 as version 1.

## Served versions [#served-versions]

| Version | First SDK release | Earliest removal |
| ------- | ----------------- | ---------------- |
| 1       | 10.0.0            | None             |

## Window policy [#window-policy]

When a later version ships, the earlier version gets an earliest removal date. That date is 180 days after the SDK release that carries the later version.

The Relay never rolls back below a version that a published SDK sends.

## Refusals [#refusals]

The Relay refuses a version outside the served set with one of two error codes.

| Code                   | Cause                                                               | HTTP                   | Socket     | What the application does                                                                                                                                                                                                                                                                |
| ---------------------- | ------------------------------------------------------------------- | ---------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `UPGRADE_REQUIRED`     | The version is below the oldest served version.                     | 426, `retryable` false | Close 4426 | Update to an SDK release that speaks a served version. A retry fails the same way. See [upgrades](https://docs.open-e2ee.dev/operate/upgrades.md).                                                                                                                                       |
| `PROTOCOL_UNSUPPORTED` | The version is above the newest served version, or it is malformed. | 400, `retryable` true  | Close 4400 | Retry later. A version above the newest served version is transient, because the Relay never rolls back below a version that a published SDK sends. A malformed version fails until the client sends a valid one. The mailbox subscription of the SDK reconnects with its usual backoff. |

Version 1 is the oldest served version. An SDK that speaks version 1 does not get `UPGRADE_REQUIRED`.

## What the SDK does with a refusal [#what-the-sdk-does-with-a-refusal]

SDK 10.1.0 and later releases stop on `UPGRADE_REQUIRED`. On `PROTOCOL_UNSUPPORTED`, the mailbox socket reconnects, and an HTTP call throws an error whose `retryable` is true.

* An HTTP call that gets `UPGRADE_REQUIRED` throws `HostedRelayUpgradeRequiredError`. Its `code` is `UPGRADE_REQUIRED`, and its `retryable` is false. The SDK does not retry it. See [errors](https://docs.open-e2ee.dev/reference/errors.md#relay-protocol-version).
* A socket close 4426 with the reason `UPGRADE_REQUIRED` moves the mailbox subscription to `stopped` with the reason `upgrade-required`. The subscription does not reconnect and does not pull. Only a newer SDK can connect again.
* A socket close 4400 with the reason `PROTOCOL_UNSUPPORTED` stays retryable, and so does the HTTP code `PROTOCOL_UNSUPPORTED`.
