EHR sync
Inbound integration with major EHRs. Cursor-based polling plus per-vendor webhooks where available.
Supported vendors
Today ContactFollowUp ships clients for DrChrono, Elation, and Athena. Each vendor has its own polling cursor and webhook-verification scheme — the API endpoints below are uniform.
Endpoints
Trigger a sync
Advance the cursor for a specific vendor by one tick. The container service handles vendor-specific pagination.
Required scopes:
users.manageRequest body
| Name | Type | Description |
|---|---|---|
ehrrequired | string | Vendor key — drchrono | elation | athena. |
Request body
{ "ehr": "drchrono" }Responses
200 OKSync ran.example { "vendor": "drchrono", "processed": 17, "cursor": "2026-05-18T14:00:00Z" }404 Not FoundUnknown vendor.
Code samples
curl -X POST https://app.contactfollowup.com/api/ehr/sync \
-H "Authorization: Bearer $HEARTHNOTE_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "ehr": "drchrono" }'Inspect cursors
Return the current high-water cursor for every wired EHR.
Required scopes:
users.manageResponses
200 OKCursors.example { "cursors": [{ "vendor": "drchrono", "cursor": "2026-05-18T14:00:00Z", "lastError": null }] }
Code samples
curl -X GET https://app.contactfollowup.com/api/ehr/cursors \
-H "Authorization: Bearer $HEARTHNOTE_TOKEN" \
-H "Content-Type: application/json"Receive a vendor webhook
Vendor-pushed event. Authenticated by HMAC over the raw body.
Path parameters
| Name | Type | Description |
|---|---|---|
ehrrequired | string | Vendor key. |
Responses
202 AcceptedSignature valid, dispatching.401 UnauthorizedBad signature. Receipt still recorded.404 Not FoundUnknown vendor.501Vendor doesn't support inbound webhooks.
Code samples
curl -X POST https://app.contactfollowup.com/api/ehr/webhooks/{ehr} \
-H "Authorization: Bearer $HEARTHNOTE_TOKEN" \
-H "Content-Type: application/json"