Integrate HandoffRx into your EHR
The HandoffRx API lets you send and receive behavioral health referrals, browse the provider directory, and get AI-powered clinical matches — all from your existing workflows.
Authentication
All API requests must include your API key in the Authorization header as a Bearer token. API keys start with hrx_.
Generate your API key
Visit your API Keys dashboard to generate a key. Keys are shown once on creation — store them securely.
curl https://handoffrx.com/api/v1/referrals \
-H "Authorization: Bearer hrx_your_api_key_here"const res = await fetch("https://handoffrx.com/api/v1/referrals", {
headers: {
"Authorization": "Bearer hrx_your_api_key_here",
"Content-Type": "application/json",
},
});
const { data } = await res.json();Base URL
Rate Limits
| Plan | Rate Limit | Monthly Cap |
|---|---|---|
| Free | 10 req/min | 100 requests |
| Pro | 100 req/min | Unlimited |
| Enterprise | 500 req/min | Unlimited |
Errors
All errors return a JSON object with an error field describing the issue.
401403404422500Referrals
Create and manage clinical referrals. Requires referrals:read or referrals:write scope.
/api/v1/referralsList all referrals sent by or to your practice. Supports pagination and status filtering.
Query Parameters
statusstringFilter by status: pending, accepted, declined, scheduled, completedlimitintegerResults per page (default: 20, max: 100)offsetintegerPagination offset (default: 0)curl "https://handoffrx.com/api/v1/referrals?status=pending&limit=10" \
-H "Authorization: Bearer hrx_your_key"{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"client_first": "Maria",
"client_last": "Hernandez",
"client_insurance": "AHCCCS",
"sent_to_practice": "Sonora Behavioral Health",
"service_needed": "IOP - Substance Use",
"status": "pending",
"is_urgent": false,
"created_at": "2026-04-10T14:22:00Z"
}
],
"count": 1,
"limit": 10,
"offset": 0
}/api/v1/referralsCreate a new referral. Requires referrals:write.
⚖️ Anti-Brokering Compliance
clinical_justification is required (min 10 characters) per Arizona ARS §36-2212 and AHCCCS anti-brokering regulations. This field is audit-logged.
curl -X POST https://handoffrx.com/api/v1/referrals \
-H "Authorization: Bearer hrx_your_key" \
-H "Content-Type: application/json" \
-d '{
"client_first": "Maria",
"client_last": "Hernandez",
"client_dob": "1985-03-15",
"client_ahcccs_id": "AZ123456789",
"client_insurance": "AHCCCS",
"sent_to_practice": "Sonora Behavioral Health",
"service_needed": "IOP - Substance Use",
"level_of_care": "IOP",
"diagnosis": "F10.20",
"risk_level": "medium",
"is_urgent": false,
"clinical_justification": "Client meets ASAM criteria for IOP level of care. Motivated for treatment, stable housing, support system in place."
}'const res = await fetch("https://handoffrx.com/api/v1/referrals", {
method: "POST",
headers: {
"Authorization": "Bearer hrx_your_key",
"Content-Type": "application/json",
},
body: JSON.stringify({
client_first: "Maria",
client_last: "Hernandez",
client_insurance: "AHCCCS",
sent_to_practice: "Sonora Behavioral Health",
service_needed: "IOP - Substance Use",
level_of_care: "IOP",
clinical_justification: "Client meets ASAM criteria for IOP. Motivated for treatment.",
}),
});
const referral = await res.json(); // status 201/api/v1/referrals/:idFetch a single referral by ID. Returns 404 if the referral doesn't exist or you don't have access.
curl "https://handoffrx.com/api/v1/referrals/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer hrx_your_key"/api/v1/referrals/:idUpdate a referral status or notes. Fires a webhook when status changes. Requires referrals:write.
curl -X PATCH "https://handoffrx.com/api/v1/referrals/550e8400-..." \
-H "Authorization: Bearer hrx_your_key" \
-H "Content-Type: application/json" \
-d '{"status": "accepted", "outcome_notes": "Client scheduled for intake assessment."}'Providers
Browse the HandoffRx provider directory. Requires providers:read scope.
/api/v1/providersList providers currently accepting clients. Filter by county, facility type, and availability.
curl "https://handoffrx.com/api/v1/providers?county=Maricopa&facility_type=IOP&has_availability=true" \
-H "Authorization: Bearer hrx_your_key"{
"data": [
{
"id": "...",
"practice": "Desert Sky IOP",
"county": "Maricopa",
"facility_type": "IOP",
"available_iop_slots": 3,
"insurance_accepted": ["AHCCCS", "Banner"],
"accepting_clients": true
}
],
"count": 8,
"limit": 20,
"offset": 0
}Clinical Matching
Get AI-powered provider recommendations based on clinical criteria. Scoring is based exclusively on clinical factors — no financial relationships influence results.
/api/v1/matchReturns the top 5 clinically-matched providers. Scoring: facility type match (30pts), insurance match (25pts), availability (20pts), specialties (15pts), provider rating (10pts).
curl -X POST https://handoffrx.com/api/v1/match \
-H "Authorization: Bearer hrx_your_key" \
-H "Content-Type: application/json" \
-d '{
"level_of_care": "IOP",
"insurance": "AHCCCS",
"diagnosis": "F10.20",
"risk_level": "medium"
}'{
"matches": [
{
"provider_id": "...",
"practice": "Desert Sky IOP",
"score": 90,
"reasons": ["Facility type (IOP) matches IOP", "Accepts AHCCCS", "3 IOP slots available"],
"available_iop_slots": 3,
"county": "Maricopa",
"facility_type": "IOP"
}
]
}Webhooks
Configure webhook endpoints to receive real-time notifications when referral events occur. Set up webhooks in your API Keys dashboard.
Event Types
referral.createdA new referral was sent to your practicereferral.acceptedA referral was accepted by the receiving providerreferral.declinedA referral was declinedreferral.scheduledAn appointment was scheduledreferral.completedThe referral was marked as completedWebhook Payload
{
"event": "referral.accepted",
"data": {
"referral_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "accepted",
"updated_at": "2026-04-10T15:30:00Z"
},
"timestamp": "2026-04-10T15:30:00.123Z"
}Verifying Signatures
Every webhook includes an X-HandoffRx-Signature header. Verify it using your webhook secret to ensure the request came from HandoffRx.
import { createHash } from "crypto";
function verifyWebhook(rawBody: string, secret: string, signatureHeader: string): boolean {
const expected = "sha256=" + createHash("sha256").update(secret + rawBody).digest("hex");
return expected === signatureHeader;
}
// In your Next.js route handler:
export async function POST(req: Request) {
const rawBody = await req.text();
const sig = req.headers.get("x-handoffrx-signature") || "";
const webhookSecret = process.env.HANDOFFRX_WEBHOOK_SECRET!;
if (!verifyWebhook(rawBody, webhookSecret, sig)) {
return new Response("Unauthorized", { status: 401 });
}
const { event, data } = JSON.parse(rawBody);
// Handle event...
return new Response("OK");
}