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:
| Integration | Status | How |
|---|---|---|
| REST API | Available | JWT or API key auth — full programmatic access |
| Apple Health export | Available | Via mobile app on iOS |
| Garmin data ingestion | Available | Via POST /api/v1/wearables/ingest |
| Bulk wearable upload | Available | Via 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/ingestcurl -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-ingestcurl -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=30curl "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/latestReturns 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 Key | Unit | Description |
|---|---|---|
heart_rate | bpm | Resting or spot heart rate |
hrv | ms (RMSSD) | Heart rate variability |
spo2 | % | Blood oxygen saturation |
steps | steps | Daily step count |
sleep_duration | hours | Total sleep time |
sleep_deep | hours | Deep sleep stage |
sleep_rem | hours | REM sleep stage |
body_temperature | °C | Skin or wrist temperature |
respiratory_rate | breaths/min | Overnight respiratory rate |
calories | kcal | Active 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
| Event | Trigger |
|---|---|
check_in.created | A patient you have a grant for submits a check-in |
symptom.created | A patient logs a new symptom (requires symptoms grant) |
grant.accepted | A patient accepts your grant invitation |
grant.revoked | A 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 401Retry Policy
If your endpoint returns a non-2xx response or times out (10 second timeout), AVYCENNA retries with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 30 seconds |
| 2nd retry | 5 minutes |
| 3rd retry | 1 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 Field | FHIR Resource | FHIR Code |
|---|---|---|
| Mood | Observation | LOINC 44250-9 |
| Sleep hours | Observation | LOINC 93832-4 |
| Steps | Observation | LOINC 41950-7 |
| Heart rate | Observation | LOINC 8867-4 |
| SpO2 | Observation | LOINC 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);