Quickstart
Sign up, register a device, stream a frame, and see a live heart-rate insight in about 5 minutes.
By the end of this page you'll have a session running against api.raeh.io with heart-rate insights streaming to your terminal.
You'll need Python 3.10+ or Node 18+. The snippets below are Python; the Examples page has JS equivalents.
1. Register a device model
In the dashboard, open Devices → Register Device Type. Give it a name (e.g. xyz_1) and add at least one modality channel. PPG Green at 100 Hz is a good default.
Open the device detail page and copy the Device Model ID (a UUID). You'll use it in every connection and bake it into your firmware or SDK as a constant; every physical unit of this hardware type shares the same ID.
2. Mint an API key
Go to API Keys → Create key. Every key is prefixed raeh_. Copy it now; the dashboard shows it once and never again.
3. Install dependencies
pip install httpx websockets4. Stream a frame
Save this as ingest.py:
import os, asyncio, json, time, uuid, struct, math
from urllib.parse import quote
import websockets
KEY = os.environ["RAEH_CLIENT_KEY"]
DEVICE_MODEL_ID = os.environ["RAEH_DEVICE_MODEL_ID"]
async def main():
device_id = f"demo-{uuid.uuid4().hex[:8]}"
url = (
f"wss://api.raeh.io/stream/ingest"
f"?api_key={quote(KEY)}"
f"&device_id={quote(device_id)}"
f"&device_model_id={quote(DEVICE_MODEL_ID)}"
)
async with websockets.connect(url) as ws:
handshake = json.loads(await ws.recv())
slot_id = handshake["slots"][0]["slot_id"]
print(f"session {handshake['session_id']}")
# 30 one-second frames of synthetic PPG (100 Hz, int16 little-endian)
for second in range(30):
t0 = int(time.time() * 1000)
samples = [int(2048 + 500 * math.sin(2 * math.pi * 1.2 * i / 100))
for i in range(100)]
header = struct.pack(">BqHB", slot_id, t0, len(samples), 0)
payload = b"".join(s.to_bytes(2, "little", signed=True) for s in samples)
await ws.send(header + payload)
print(f" sent frame {second + 1}/30", end="\r", flush=True)
await asyncio.sleep(1.0)
asyncio.run(main())Run it:
RAEH_CLIENT_KEY=raeh_... \
RAEH_DEVICE_MODEL_ID=<uuid> \
python ingest.py5. Subscribe to insights
In a second terminal, save this as subscribe.py:
import os, asyncio, json
from urllib.parse import quote
import websockets
KEY = os.environ["RAEH_CLIENT_KEY"]
async def main():
async with websockets.connect(
f"wss://api.raeh.io/stream/subscribe?api_key={quote(KEY)}"
) as ws:
await ws.recv() # drain the subscribe ack
while True:
msg = json.loads(await ws.recv())
if msg.get("type"):
print(f"{msg['type']:<5} {msg['value']} {msg.get('unit', '')}")
asyncio.run(main())Run it before you start streaming, then kick off ingest.py in the first terminal.
RAEH_CLIENT_KEY=raeh_... python subscribe.pyWhat you should see
Roughly 15 seconds in, once there's enough PPG data for the pipeline to lock on:
hr 72 bpm
spo2 98 %
hr 72 bpm
rr 15 brpm
hr 72 bpm
...The synthetic signal in step 4 is a clean 1.2 Hz sinusoid → 72 bpm. When you feed in real PPG samples from your sensor, the values track the wearer's actual heart rate.
Troubleshooting
- No insights after 30 seconds. You probably passed the wrong
device_model_id, or the modality channel isn'tppg_greenat 100 Hz. Double-check the Device Model page in the dashboard. 401 unauthorized. The API key is wrong, revoked, or belongs to a different account.403 forbidden. The account has no entitled algorithms. Contact us if you think this is a mistake.
Next
- Concepts: account, device model, device, session, insight.
- Authentication: where the key fits and how to rotate it.
- Frame format: the binary layout, if you're writing firmware in C or Rust.