> ## Documentation Index
> Fetch the complete documentation index at: https://api.vitarelay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# EHR Integration Guide

> Connect your EHR or EMR to VitaRelay to automate escript submission and order tracking.

# EHR / EMR Integration

This guide walks through connecting an EHR or EMR system to VitaRelay to automate the escript-to-fulfillment workflow.

## What you'll build

* Push patients and intakes from your EHR into VitaRelay
* Receive fulfillment status updates (order shipped, delivered) back in your system
* Keep patient records in sync

## Prerequisites

* A VitaRelay API key issued by a VitaRelay admin (`vr_live_…` or `vr_test_…`) with the write scopes your integration needs
* An HTTPS URL to receive webhook events, configured for your org by a VitaRelay admin

## Step 1 — Create the patient

You don't need to look up existing patients — `POST /patients` is idempotent on
`external_patient_id`, so re-sending returns the original patient.

```bash theme={null}
curl -X POST https://vitarelay.com/api/public/v1/patients \
  -H "Authorization: Bearer vr_live_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "external_patient_id": "ehr-patient-4821",
    "first_name": "Jane",
    "last_name": "Smith",
    "dob": "1985-04-12",
    "email": "jane.smith@example.com",
    "phone": "+18135550100"
  }'
```

Use your own EHR record id as `external_patient_id`. A replay with the same id
and the same body returns the original record (`200` instead of `201`); the same
id with a different body returns `409 duplicate_request`.

Store the returned patient id (a UUID) against your local patient record.

## Step 2 — Submit the intake

```bash theme={null}
curl -X POST https://vitarelay.com/api/public/v1/intakes \
  -H "Authorization: Bearer vr_live_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "external_intake_id": "ehr-intake-4821",
    "patient_id": "3a2b1c0d-9e8f-4a7b-8c6d-5e4f3a2b1c0d",
    "category": "weight_management",
    "responses": {
      "height_in": 65,
      "weight_lb": 198,
      "goal": "weight loss",
      "current_medications": ["lisinopril"]
    }
  }'
```

When a prescriber signs the resulting escript, VitaRelay fires `intake.reviewed`.

## Step 3 — Get your webhook endpoint configured

Webhook endpoints are **not** self-registered through the API. Give your VitaRelay
admin the HTTPS URL that should receive events and the events you want
(`order.paid`, `order.shipped`, `order.delivered`, `order.exception`,
`intake.reviewed`). The admin configures it in the dashboard and shows you the
signing secret once — store it in your secret manager.

## Step 4 — Handle incoming events

In your EHR's webhook handler:

```typescript theme={null}
export async function POST(request: Request) {
  const rawBody = await request.text();

  if (!verifyVitaRelaySignature(rawBody, request.headers.get("X-VitaRelay-Signature"), secret)) {
    return new Response("Unauthorized", { status: 401 });
  }

  const event = JSON.parse(rawBody);

  switch (event.event) {
    case "intake.reviewed":
      await markPrescriptionSigned(event.escript_id, event.patient_id);
      break;

    case "order.shipped":
      await updatePatientChartOrderStatus(event.order_id, "shipped", {
        trackingNumber: event.tracking_number,
        carrier: event.tracking_carrier,
      });
      break;

    case "order.delivered":
      await updatePatientChartOrderStatus(event.order_id, "delivered", {});
      break;
  }

  return new Response("OK", { status: 200 });
}
```

See [Webhook Security](/webhooks/security) for the verification helper.

## Flow diagram

```
EHR captures patient + intake
        ↓
POST /api/public/v1/patients (find or create)
        ↓
POST /api/public/v1/intakes
        ↓
Prescriber signs → webhook: intake.reviewed
        ↓
POST /api/public/v1/orders → webhook: order.paid
        ↓
Pharmacy fulfills → webhook: order.shipped / order.delivered
        ↓
EHR updates patient chart
```
