AnyBio

Lookup & Query API

Discover biosignals available to your project and query observation history.

The biosignal lookup API lets your application discover what's available at runtime - which biosignals a project is subscribed to, which are currently flowing, and what their metadata looks like - rather than hard-coding identifiers in your client.

All endpoints are authenticated and scoped to the caller's organization.

List biosignals available to a project

GET /api/v1/projects/{projectId}/biosignals

Returns every biosignal configured for the project, including which are currently flowing from connected devices.

import { fetchProjectBiosignals } from "@anybio/sdk";

const biosignals = await fetchProjectBiosignals(projectId);

for (const bs of biosignals) {
  console.log(`${bs.abbreviation} (${bs.name}) - ${bs.unit}`);
  if (bs.is_flowing) {
    console.log(`  ...streaming live from ${bs.source_type}`);
  }
}

Response shape:

[
  {
    "id": 1,
    "name": "Heart Rate",
    "abbreviation": "HR",
    "unit": "bpm",
    "loinc_code": "8867-4",
    "signal_type": "Derived",
    "role": "primary",
    "source_type": "device",
    "is_flowing": true
  }
]

Query observations

Once you know which biosignals are available, query historical observations by ID:

GET /api/v1/observations
  ?biosignal_id={id}
  &subject_id={id}
  &since={ISO 8601 timestamp}
  &until={ISO 8601 timestamp}
const observations = await fetchObservations({
  biosignalId: 1,           // HR
  subjectId,
  since: "2026-05-01T00:00:00Z",
});

Returns FHIR-aligned observation records:

[
  {
    "id": "...",
    "biosignal_id": 1,
    "loinc_code": "8867-4",
    "value": 72,
    "unit": "bpm",
    "effective_time": "2026-05-08T14:32:11Z",
    "device_id": "...",
    "method_code": "algorithm:ecg_v1"
  }
]

Query feature streams

For derived features (HR from ECG, HRV-RMSSD, PRV from PPG, etc.), query the feature series produced by the DSP pipeline:

GET /api/v1/streams/{streamId}/features
const features = await fetchStreamFeatures(streamId);
// features[i].name        e.g. "hr_ecg", "hrv_rmssd", "prv_sdnn_5min"
// features[i].ts_ns       array of nanosecond timestamps
// features[i].values      array of feature values
// features[i].cadence_hz  output sample rate
// features[i].qmask       array of quality flags (0=good, 1=suspect, 2=bad)

See DSP for what features each biosignal produces.

Real-time subscription

For live data, subscribe to the WebSocket feed instead of polling:

const ws = new WebSocket(
  `wss://api.anybio.io/ws?subject=${subjectId}`
);

ws.onmessage = (event) => {
  const frame = parseFrame(event.data);  // 100ms protocol-buffer frame
  // frame.ecg, frame.ppg, frame.eda, frame.temp arrays
};

The wire format is a 100ms binary frame containing every active waveform channel. See the BioSDK streaming guide for the iOS-side equivalent.

Discovery patterns

A few patterns we recommend over hard-coding biosignal IDs in your application:

  1. Look up by abbreviation at startup. Cache the id for the abbreviations your app cares about (HR, ECG, SpO2, ...) once per session, then query by ID afterward.
  2. Drive UI from the catalog. A signal picker that renders the list returned by GET /projects/{id}/biosignals automatically gains support for new biosignals as they're added.
  3. Filter on is_flowing to show only what's currently streaming from a connected device, instead of every biosignal the project is subscribed to.

On this page