AVYCENNA
For Doctors

Integrations & Webhooks

Connect AVYCENNA to your clinical systems, EHR platforms, and automation workflows.

Integrations & Webhooks

AVYCENNA is built to fit into your existing clinical workflow, not replace it. This page covers what's available now, what's coming, and how to build your own integrations.

Current Integrations

These integrations are available today:

IntegrationStatusHow
REST APIAvailableJWT or API key auth — full programmatic access
Apple Health exportAvailableVia mobile app on iOS
Garmin data ingestionAvailableVia POST /api/v1/wearables/ingest
Bulk wearable uploadAvailableVia POST /api/v1/wearables/bulk-ingest

Wearables API

The wearables API accepts biometric data from any source — Garmin, custom hardware, your own pipeline, or any device that can make an HTTP request.

Ingest a Single Data Point

POST /api/v1/wearables/ingest
curl -X POST https://api.avycenna.com/api/v1/wearables/ingest \
  -H "X-API-Key: avk_a7f3c91e8b2d4..." \
  -H "Content-Type: application/json" \
  -d '{
    "metric": "heart_rate",
    "value": 62.0,
    "unit": "bpm",
    "recorded_at": "2026-06-30T07:45:00Z",
    "source": "garmin",
    "source_device_id": "garmin-device-001"
  }'

Bulk Ingest

More efficient for high-volume or batch uploads:

POST /api/v1/wearables/bulk-ingest
curl -X POST https://api.avycenna.com/api/v1/wearables/bulk-ingest \
  -H "X-API-Key: avk_a7f3c91e8b2d4..." \
  -H "Content-Type: application/json" \
  -d '{
    "data_points": [
      {
        "metric": "hrv",
        "value": 48.3,
        "unit": "ms",
        "recorded_at": "2026-06-30T06:30:00Z",
        "source": "garmin"
      },
      {
        "metric": "spo2",
        "value": 97.0,
        "unit": "%",
        "recorded_at": "2026-06-30T06:30:00Z",
        "source": "garmin"
      },
      {
        "metric": "sleep_duration",
        "value": 7.5,
        "unit": "hours",
        "recorded_at": "2026-06-30T06:30:00Z",
        "source": "garmin"
      }
    ]
  }'

The bulk endpoint accepts up to 500 data points per request.

Retrieve a Metric Time-Series

GET /api/v1/wearables/metric/{metric}?days=30
curl "https://api.avycenna.com/api/v1/wearables/metric/heart_rate?days=7" \
  -H "Authorization: Bearer eyJhbGci..."

Response:

{
  "metric": "heart_rate",
  "unit": "bpm",
  "data_points": [
    {"value": 62.0, "recorded_at": "2026-06-30T07:45:00Z", "source": "garmin"},
    {"value": 58.0, "recorded_at": "2026-06-29T07:30:00Z", "source": "garmin"}
  ]
}

Get Latest Value Per Metric

GET /api/v1/wearables/latest

Returns the most recent value for every metric with available data:

curl https://api.avycenna.com/api/v1/wearables/latest \
  -H "Authorization: Bearer eyJhbGci..."
{
  "latest": {
    "heart_rate": {"value": 62.0, "unit": "bpm", "recorded_at": "2026-06-30T07:45:00Z"},
    "hrv": {"value": 48.3, "unit": "ms", "recorded_at": "2026-06-30T06:30:00Z"},
    "spo2": {"value": 97.0, "unit": "%", "recorded_at": "2026-06-30T06:30:00Z"},
    "steps": {"value": 9241, "unit": "steps", "recorded_at": "2026-06-30T20:00:00Z"}
  }
}

Supported Metrics

Metric KeyUnitDescription
heart_ratebpmResting or spot heart rate
hrvms (RMSSD)Heart rate variability
spo2%Blood oxygen saturation
stepsstepsDaily step count
sleep_durationhoursTotal sleep time
sleep_deephoursDeep sleep stage
sleep_remhoursREM sleep stage
body_temperature°CSkin or wrist temperature
respiratory_ratebreaths/minOvernight respiratory rate
calorieskcalActive or total calorie burn

Webhooks (Coming Q3 2026)

Webhooks are planned for Q3 2026. The endpoint structure and payload format described here are finalized and will ship as documented.

Webhooks let AVYCENNA push events to your system in real time — no polling required.

Event Types

EventTrigger
check_in.createdA patient you have a grant for submits a check-in
symptom.createdA patient logs a new symptom (requires symptoms grant)
grant.acceptedA patient accepts your grant invitation
grant.revokedA patient revokes your access

Webhook Payload Format

Each event is delivered as an HTTP POST to your configured endpoint URL:

{
  "event": "check_in.created",
  "event_id": "evt_5nXyZaBc",
  "timestamp": "2026-06-30T08:15:00Z",
  "data": {
    "patient_id": "usr_7jRtHvBk",
    "check_in_id": "ci_4nWxYzAb",
    "mood": 4,
    "energy": 3,
    "focus": 4,
    "sleep_hours": 7.5,
    "steps": 9241,
    "checked_in_at": "2026-06-30T08:15:00Z"
  }
}

Signature Verification

Always verify the HMAC-SHA256 signature on incoming webhooks. Never process a webhook event without checking the signature first.

Every webhook request includes an X-AVYCENNA-Signature header. Verify it:

import hmac
import hashlib

def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        body,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature)

# In your webhook handler:
signature = request.headers.get("X-AVYCENNA-Signature")
if not verify_webhook(request.body, signature, WEBHOOK_SECRET):
    return 401

Retry Policy

If your endpoint returns a non-2xx response or times out (10 second timeout), AVYCENNA retries with exponential backoff:

AttemptDelay
1st retry30 seconds
2nd retry5 minutes
3rd retry1 hour

After 3 failed retries, the event is dropped and logged.


EHR / HL7 FHIR (Roadmap)

FHIR integration is on the roadmap. The mapping below reflects our planned design, not a shipped feature.

We plan FHIR R4 support that maps AVYCENNA check-ins to FHIR Observation resources, enabling ingestion into Epic, Cerner, and other FHIR-compliant EHR systems.

Planned mapping:

AVYCENNA FieldFHIR ResourceFHIR Code
MoodObservationLOINC 44250-9
Sleep hoursObservationLOINC 93832-4
StepsObservationLOINC 41950-7
Heart rateObservationLOINC 8867-4
SpO2ObservationLOINC 59408-5

If FHIR integration is important to your deployment, contact us — early design partners shape the implementation.


Custom Integration Examples

Python: Fetch Patient Data with an API Key

import requests
from datetime import datetime

API_KEY = "avk_a7f3c91e8b2d4..."
BASE_URL = "https://api.avycenna.com/api/v1"

headers = {"X-API-Key": API_KEY}

# List all patients with active grants
patients = requests.get(f"{BASE_URL}/grants/outgoing", headers=headers).json()

for grant in patients["grants"]:
    patient_id = grant["patient_id"]
    patient_name = grant["patient_name"]

    # Fetch last 30 days of check-ins
    check_ins = requests.get(
        f"{BASE_URL}/grants/patient/{patient_id}/check-ins",
        params={"days": 30},
        headers=headers
    ).json()

    summary = check_ins["summary"]
    print(f"{patient_name}: avg mood {summary['avg_mood']:.1f}, "
          f"avg sleep {summary['avg_sleep_hours']:.1f}h, "
          f"{summary['total_check_ins']} check-ins")

Node.js: Fetch Patient Check-ins

const API_KEY = 'avk_a7f3c91e8b2d4...';
const BASE_URL = 'https://api.avycenna.com/api/v1';

const headers = {
  'X-API-Key': API_KEY,
  'Content-Type': 'application/json',
};

async function getPatientCheckIns(patientId, days = 30) {
  const res = await fetch(
    `${BASE_URL}/grants/patient/${patientId}/check-ins?days=${days}`,
    { headers }
  );

  if (!res.ok) {
    const err = await res.json();
    throw new Error(`API error ${res.status}: ${err.detail}`);
  }

  return res.json();
}

async function main() {
  // Get all patients
  const { grants } = await fetch(`${BASE_URL}/grants/outgoing`, { headers })
    .then(r => r.json());

  for (const grant of grants) {
    const data = await getPatientCheckIns(grant.patient_id, 30);
    const { avg_mood, avg_energy, total_check_ins } = data.summary;
    console.log(
      `${grant.patient_name}: mood=${avg_mood.toFixed(1)}, ` +
      `energy=${avg_energy.toFixed(1)}, ${total_check_ins} check-ins`
    );
  }
}

main().catch(console.error);

On this page