A psychiatric clinic loses revenue every time a patient no-shows, and the standard fix is having staff call each patient the day before. The Rubin Center wanted those reminders to fire automatically from their Valant EHR, route through their existing Spruce Health SMS number, and stay HIPAA-compliant end to end. No off-the-shelf product fit: the EHR has no public webhooks, the SMS vendor needed HMAC-verified inbound parsing, and patient phone numbers had to be encrypted at rest.

A psychiatric clinic loses revenue every time a patient no-shows, and the standard fix is having staff call each patient the day before. The Rubin Center wanted those reminders to fire automatically from their Valant EHR, route through their existing Spruce Health SMS number, and stay HIPAA-compliant end to end. No off-the-shelf product fit: the EHR has no public webhooks, the SMS vendor needed HMAC-verified inbound parsing, and patient phone numbers had to be encrypted at rest.
We built a FastAPI scheduler that authenticates against Valant's three-step token flow and pulls providers, patients, and appointments hourly between 5 AM and 7 PM MST. Each appointment inside a 14-day window queues two reminders: a one-week-out message and a two-business-days-out follow-up, both fired at 8 AM MST. A task queue polls every 15 seconds and sends the SMS through Spruce. Patient replies come back through a Spruce webhook with HMAC-SHA256 signature verification, where a parser routes C, R, and X codes into confirm, reschedule, and cancel paths. Four layers of duplicate prevention (Python set, database query, unique constraint, IntegrityError catch) make sure the same reminder never fires twice. Patient phone numbers are AES-256 encrypted in MySQL. Staff get a Next.js dashboard, with httpOnly cookie auth, that surfaces the reminder queue, lets them override sends, and edits SMS templates per provider and per modality.
## What we built Replaced manual phone-call confirmations at The Rubin Center Psychiatry with an automated SMS pipeline tied directly into the clinic's Valant EHR. Staff do not enter anything by hand. Appointments scheduled in Valant trigger reminders on their own, patient replies move appointments through confirm, reschedule, or cancel states, and a dashboard shows the queue in real time. ## Tech FastAPI backend on Python 3.11, scheduled with APScheduler. MySQL on AWS RDS with SSL enforced and a CA bundle auto-downloaded at boot. Phone numbers encrypted at rest with AES-256. Next.js 14 dashboard in TypeScript, built in standalone mode. Spruce Health for SMS send and inbound webhook with HMAC-SHA256 verification. CI/CD through GitHub Actions to EC2, with separate systemd services for the API and the scheduler. ## Results - Hourly Valant sync, 5 AM to 7 PM MST - Two scheduled reminders per appointment (7 days out, 2 business days out), plus a courtesy message the day before for confirmed visits - Three patient reply codes (C, R, X) routed automatically into confirm, reschedule, and cancel flows - Four-layer duplicate prevention so the same reminder cannot fire twice - 15-second task queue poll for outbound SMS - Master kill switch, whitelist mode, and a business-hours guard before any message leaves the system - All times stored UTC, business logic locked to fixed MST so daylight saving never shifts a send ## What is next Adding per-provider escalation rules, expanding template variables for telehealth Zoom links, and surfacing reminder history per patient inside the dashboard.
Hourly Valant sync running 5 AM to 7 PM MST
two scheduled reminders per appointment plus a courtesy day-of message for confirmed visits
three patient reply codes (C
R
X) parsed automatically
AES-256 encrypted patient phones
four-layer duplicate prevention on the reminder queue
15-second task queue poll
deployed through GitHub Actions to EC2 with separate systemd services for API and scheduler

Jesse Sulo
CEO