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}/biosignalsReturns 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}/featuresconst 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:
- Look up by abbreviation at startup. Cache the
idfor the abbreviations your app cares about (HR,ECG,SpO2, ...) once per session, then query by ID afterward. - Drive UI from the catalog. A signal picker that renders the list returned by
GET /projects/{id}/biosignalsautomatically gains support for new biosignals as they're added. - Filter on
is_flowingto show only what's currently streaming from a connected device, instead of every biosignal the project is subscribed to.