AnyBio
Guides

Getting Started

Consume DSP-derived feature series from the AnyBio API.

This guide walks through the practical case: a stream is flowing, the DSP layer is running, and your application wants the heart rate, HRV, or other derived features that come out of it.

If you haven't yet captured a stream, start with the BioSDK quickstart. DSP runs automatically against any incoming waveform stream; you don't need to enable it.

Querying a feature series

Every signal stream that produces derived features exposes them through a single endpoint:

GET /api/v1/streams/{streamId}/features
import { fetchStreamFeatures } from "@anybio/sdk";

const features = await fetchStreamFeatures(streamId);

const hr = features.find((f) => f.name === "hr_ecg");
if (hr) {
  console.log(`${hr.values.length} HR samples at ${hr.cadence_hz} Hz`);
  console.log(`Latest: ${hr.values[hr.values.length - 1]} bpm`);
}

Each feature series carries five fields:

type FeatureSeries = {
  name: string;        // "hr_ecg", "hrv_rmssd", "prv_sdnn_5min", ...
  ts_ns: number[];     // nanosecond timestamps, one per value
  values: number[];    // feature values
  cadence_hz: number;  // output sample rate
  qmask: number[];     // quality mask, one per value (0=good, 1=suspect, 2=bad)
};

The timestamps are nanosecond-precision and aligned with the source stream's clock, so feature series can be plotted alongside the raw waveform without resampling.

What features come from what biosignal

Map a biosignal abbreviation to its feature outputs:

If your stream contains...You get these features
ECGhr_ecg, hrv_rmssd, hrv_sdnn_5min
PPGhr_ppg, prv_rmssd, prv_sdnn_5min
EDA, TEMP, HR (device-reported), other discrete signalsDirect observations - see Biosignals: Lookup

Discrete signals (anything emitted by the device at 1 Hz or slower) skip DSP and become observations directly.

Reading the quality mask

Every feature value has a qmask byte:

ValueMeaning
0Good. Use the value.
1Suspect. The underlying window had partial signal quality issues. Use with caution; consider downweighting.
2Bad. The window contained data the platform flagged as unreliable (motion artifact, dropped samples, lead-off). Skip in aggregations.

A simple consumer pattern:

const cleanValues = hr.values.filter((_, i) => hr.qmask[i] === 0);
const meanHR = cleanValues.reduce((a, b) => a + b, 0) / cleanValues.length;

Live vs. historical

The same /streams/{streamId}/features endpoint works for both live and completed streams. For live streams, poll periodically or subscribe to updates via WebSocket. For completed streams, the full feature series is available as soon as the stream closes.

For raw waveform data in real time, subscribe to the WebSocket feed - see BioSDK streaming.

Provenance

Every feature value is tagged with the algorithm that produced it. When the same feature is later persisted as an observation, the method_code field records this:

{
  "biosignal_id": 1,
  "value": 72,
  "method_code": "algorithm:ecg_v1"
}

The version suffix advances when an algorithm is updated. Historical values keep their original method_code so reanalysis is reproducible.

On this page