API Reference v1

API
Documentation

Everything you need to integrate camera-based vital sign monitoring. Authentication, endpoints, schemas, and code examples.

Quickstart
Get measuring in 3 steps
Authentication
API key setup
Endpoints
POST /api/rppg/measure
Code Examples
JS, Python, cURL
Error Codes
Status codes & handling
Rate Limits
Quotas & headers

Quickstart

From zero to heart rate data in three steps. For the full integration guide with SDK usage, see the Quickstart Guide.
1
Get your API key
Sign up at /keys — free sandbox tier, no credit card required. Your key looks like beam_sk_...
2
Send a video frame
POST to /api/rppg/measure with your API key in the X-API-Key header and a video frame as multipart/form-data.
3
Read the vitals
Get back JSON with heart rate, HRV, SpO², stress index, respiration rate, and confidence score.
Tip: Want to try the API before writing any code? Use the interactive playground — no signup required.

Authentication

All API requests require an API key passed in the X-API-Key header.
HTTP Header
X-API-Key: beam_sk_your_api_key_here
Header Value Description
X-API-Key beam_sk_... Your API key from the developer dashboard. Required on every request.
Keep it secret. Your API key grants access to your account's rate limit and usage quota. Never expose it in client-side JavaScript — make API calls from your server.

Endpoints

The Beam AI API currently exposes one endpoint for rPPG vital sign measurement.
POST /api/rppg/measure

Analyze a video frame (or sequence of frames) using remote photoplethysmography to extract vital signs. Returns heart rate, heart rate variability (HRV), blood oxygen saturation (SpO²), stress index, respiration rate, and a signal quality confidence score.

Request Headers
Header Type Description
X-API-Key required string Your API key
Content-Type required string multipart/form-data
Request Body (multipart/form-data)
Field Type Description
frame required file (image/jpeg, image/png) A video frame captured from a front-facing camera. Must contain a clearly visible face. Recommended: 640×480 or higher.
duration_ms optional integer Measurement window in milliseconds. Default: 30000 (30s). Minimum: 10000.
include_raw optional boolean If true, includes raw PPG signal waveform in response. Default: false.
Response (200 OK)
JSON Response
{
  "success": true,
  "data": {
    "heart_rate": 72,         // BPM (±2 accuracy)
    "hrv": 48.3,              // RMSSD in milliseconds
    "spo2": 98,               // Blood oxygen %
    "stress_index": 127.5,      // Baevsky Stress Index
    "respiration_rate": 16,      // Breaths per minute
    "confidence": 0.94,        // Signal quality (0-1)
    "duration_ms": 30120,       // Actual measurement time
    "timestamp": "2026-05-15T14:30:00Z"
  },
  "meta": {
    "api_version": "1.0",
    "processing_ms": 245
  }
}
Response Fields
Field Type Description
heart_rate integer Heart rate in beats per minute (BPM). Accuracy: ±2 BPM vs. clinical ECG.
hrv float Heart rate variability using RMSSD method, in milliseconds. Higher = better recovery.
spo2 integer Estimated blood oxygen saturation (%). Normal range: 95–100%.
stress_index float Baevsky Stress Index derived from HRV. Lower = more relaxed. Typical: 50–150.
respiration_rate integer Estimated breaths per minute. Normal resting: 12–20.
confidence float Signal quality score from 0 to 1. Below 0.7 indicates poor lighting or movement.
duration_ms integer Actual measurement duration in milliseconds.
timestamp string (ISO 8601) Server-side timestamp of measurement completion.

Code Examples

Copy-paste examples in JavaScript, Python, and cURL. Replace beam_sk_your_key with your actual API key.
measure.js
// Capture a frame from webcam and send to Beam AI
async function measureVitals(videoElement) {
  // Draw current video frame to canvas
  const canvas = document.createElement('canvas');
  canvas.width = videoElement.videoWidth;
  canvas.height = videoElement.videoHeight;
  canvas.getContext('2d').drawImage(videoElement, 0, 0);

  // Convert to blob
  const blob = await new Promise(r => canvas.toBlob(r, 'image/jpeg', 0.9));

  // Send to API
  const form = new FormData();
  form.append('frame', blob, 'frame.jpg');

  const res = await fetch('https://api.beamai.co/api/rppg/measure', {
    method: 'POST',
    headers: { 'X-API-Key': 'beam_sk_your_key' },
    body: form
  });

  const { data } = await res.json();
  console.log(`Heart Rate: ${data.heart_rate} BPM`);
  console.log(`HRV: ${data.hrv} ms`);
  console.log(`SpO2: ${data.spo2}%`);
  console.log(`Confidence: ${data.confidence}`);
}
measure.py
import requests

def measure_vitals(frame_path):
    """Send a video frame to Beam AI for rPPG analysis."""
    url = "https://api.beamai.co/api/rppg/measure"
    headers = {"X-API-Key": "beam_sk_your_key"}

    with open(frame_path, "rb") as f:
        files = {"frame": ("frame.jpg", f, "image/jpeg")}
        resp = requests.post(url, headers=headers, files=files)

    resp.raise_for_status()
    data = resp.json()["data"]

    print(f"Heart Rate: {data['heart_rate']} BPM")
    print(f"HRV: {data['hrv']} ms")
    print(f"SpO2: {data['spo2']}%")
    print(f"Confidence: {data['confidence']}")

    return data

# Usage
measure_vitals("./captured_frame.jpg")
Terminal
curl -X POST https://api.beamai.co/api/rppg/measure \
  -H "X-API-Key: beam_sk_your_key" \
  -F "frame=@./frame.jpg" \
  -F "duration_ms=30000"
Live demo: See a complete working implementation in the GitHub example repo, or read the step-by-step tutorial.

Error Codes

All errors return JSON with success: false and a human-readable error message.
Code
Status
Description
400
Bad Request
Missing or invalid frame field, unsupported image format, or no face detected in frame.
401
Unauthorized
Missing or invalid API key. Check the X-API-Key header.
429
Rate Limited
Too many requests. Back off and retry after the time in the Retry-After header.
500
Server Error
Internal processing error. Retry with exponential backoff. If persistent, contact support.
Error Response Example
{
  "success": false,
  "error": {
    "code": "INVALID_API_KEY",
    "message": "The API key provided is invalid or has been revoked.",
    "status": 401
  }
}

Rate Limits

Rate limits are applied per API key. Headers are included in every response so you can track usage.
100
Requests / minute
(Sandbox)
1,000
Requests / minute
(Starter)
10,000
Requests / minute
(Enterprise)
Rate Limit Headers
Header Description
X-RateLimit-Limit Maximum requests allowed per minute for your plan.
X-RateLimit-Remaining Requests remaining in the current window.
X-RateLimit-Reset Unix timestamp when the rate limit window resets.
Retry-After Seconds to wait before retrying (only present on 429 responses).
Need higher limits? Enterprise plans include custom rate limits, dedicated support, and SLA guarantees. Get in touch to discuss your needs.
Pricing Tiers
Plan Rate Limit Price
Sandbox 100 req/min Free
Starter 1,000 req/min $99/mo
Enterprise 10,000+ req/min Custom

Ready to integrate?
Get your API key.

Free sandbox tier. No credit card. Start measuring vital signs in your app today.

Get API Key

$99/mo starter · Free sandbox · Cancel anytime