raehDocs

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 websockets

4. 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.py

5. 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.py

What 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't ppg_green at 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.

On this page