orion-sleep-api
Async Python client for the Orion Sleep smart mattress topper.
Orion publishes no API documentation. This contract was rebuilt from captured traffic and a decompile of the Android app, then verified against a real bed one endpoint at a time.
Every endpoint says how much it is trusted
That verification is the point of this library, so it is written into the code rather than a wiki nobody reads.
| Label | Meaning |
|---|---|
| Measured | A real request went to a real bed and the result was recorded. |
| App-derived | Read out of the decompiled Android client. Plausible, never executed. |
| Speculative | Guessed. Nothing speculative ships here. |
Every method's docstring carries one, along with what the label rests on: a dated request and its response, or the part of the app the contract was read out of.
The labels exist because a reverse-engineered contract has no other way to tell a route that was proven from one that was only inferred. Both look equally confident in code, and only one of them will work.
Install
pip install orion-sleep-api
Quick start
import aiohttp
from orion_sleep_api import OrionApiClient
async with aiohttp.ClientSession() as session:
client = OrionApiClient(session)
# Passwordless, same as the app. A code arrives by SMS or email.
await client.request_auth_code(phone="15555550100")
tokens = await client.verify_auth_code(code="123456", phone="15555550100")
client = OrionApiClient(session, **tokens)
devices = await client.list_devices()
Tokens refresh themselves. Register a callback to persist the new ones:
client.set_token_refresh_callback(
lambda access, refresh, expires_at: save_somewhere(access, refresh, expires_at)
)
Two identifiers, and they are not interchangeable
This is the single easiest way to get a confusing 403 or 404 out of this API.
| Routes | Identifier |
|---|---|
/live, /live/zones/{id}, /action, /activate, /deactivate, /update, the WebSocket |
serial_number |
PUT /v1/devices/{id}, the only metadata write (name, orientation, timezone) |
device UUID |
Sending the wrong one fails with no useful message. Three of these routes were originally wired up with the UUID and returned an error on every call, which is how the rule was found.
Nearly everything takes the serial. Reach for the UUID only on that one metadata write, and when a route is undocumented, guess serial.
What it covers
Devices and live state, per-zone temperature and power, LED brightness and quiet mode, rapid cooling, per-user sleep schedules including single-day overrides, sleep insights with stages and apnea, session management, user access and invitations, and the live WebSocket.
Full endpoint list with confidence labels: read the docstrings. The
evidence behind every "measured" label is under "What is known about the
API" in AGENTS.md, organised by route family, recording
what was sent and what came back.
There is also an
openapi.yaml
in the Home Assistant integration repository.
Live data
from orion_sleep_api import OrionWebSocketManager
def on_message(serial, event_type, payload):
print(serial, event_type, payload.get("zones"))
manager = OrionWebSocketManager(session, client, on_message=on_message)
manager.sync_to_serials(["ABCDEF123456"])
The socket pushes roughly every two seconds. It needs ALPN forced to
http/1.1 and an okhttp user agent, both of which this library handles.
Thirty seconds of silence means the stream is dead even though the socket
is still open, so the client reconnects with backoff.
Home Assistant
The Orion Sleep integration is built on this library and is the reason it exists. If you want a bed in Home Assistant, install that. If you want to write your own tooling, this is the piece you want.
Contributing
One rule: do not add a method for a route you have not verified. If you cannot demonstrate a request against a live bed, label it app-derived and say so in the docstring. A confident wrapper around a guessed endpoint is worse than no wrapper.
AGENTS.md has the rest: how to verify a write against a bed
somebody may be asleep on, what is known about each route family, the
traps that have cost people hours, the layout, and the release process.
License
MIT.
Not affiliated with or endorsed by Orion Longevity Inc.
Metadata
Release files for orion-sleep-api 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| orion_sleep_api-0.1.0.tar.gz | 77.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| orion_sleep_api-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 121.7 kB
Release files / orion_sleep_api-0.1.0.tar.gz
| Download URL | orion_sleep_api-0.1.0.tar.gz |
|---|---|
| Size | 77.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3b8f423505a7d70715bf33da70e3660f8408d13cec66a21cb76b22b64c8bf920
|
|
BLAKE2b-256 checksum How to use checksums |
a3d414cf2c33e7a9d0feeb8f26c8a9910e275275a879189b96a6b7675fa092dc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.
Transparency logRelease files / orion_sleep_api-0.1.0-py3-none-any.whl
| Download URL | orion_sleep_api-0.1.0-py3-none-any.whl |
|---|---|
| Size | 44.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ab8c5a9f429742b5c4f0a94997bf737433b4f830f0b64775cef92c34680f6a69
|
|
BLAKE2b-256 checksum How to use checksums |
da4ec81317866965b1191546cdc74d7f97c9d06f7183d3f3d87cebd97263f726
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.
Transparency log