Unfortunately, the Heidi API and Widget are no longer available for future integrations in Australia and New Zealand. If you are a current Heidi customer looking to integrate, reach out to your Customer Success representative. Otherwise, contact our team to find out what this means for you.
Connectors
Specification

Specification

Heidi Connector Spec v0.1.

This specification is in preview. The transport (REST or MCP) may change before general availability. We will give connector authors notice before any breaking change.

Transport and auth

RequirementValue
ProtocolREST (binding) or Model Context Protocol (opens in a new tab) over Streamable HTTP
EndpointREST: one base URL, e.g. https://emr.example.com/heidi. MCP: one URL, e.g. https://emr.example.com/mcp.
TLSHTTPS only, TLS 1.2+
Data residencyPatient data for a clinic stays in that clinic's region: AU in AU, UK in UK, and so on. data_handling.hosting_regions covers every region in regions.
AuthAuthorization: Bearer <connector key> on every request
Unauthenticated requestHTTP 401 before any tool runs
TenancyA key maps to exactly one practice. Never return another practice's data.
SessionsStateless is fine. Heidi does not rely on MCP sessions or cookies.
TimeoutsRespond within 10 s. Heidi times out at 30 s.
Rate limitsSupport at least 60 requests per minute per practice. Return rate_limited if you throttle.

OAuth 2.1 (MCP authorization) is planned for v0.2. In v0.1 every connector uses per-practice keys.

Tools

Names are fixed. Every tool returns MCP structuredContent that matches the shapes below. Over REST, each tool is one endpoint returning the same JSON (see REST binding).

Required

ToolArgumentsReturns
heidi_get_connector_infononeConnectorInfo
heidi_list_practitionersnonePractitioner[]
heidi_list_appointmentspractitioner_id, start_date, end_date (ISO dates, inclusive, at most 31 days)Appointment[]
heidi_search_patientsname?, date_of_birth?, limit? (default 20, max 50). At least one criterion.Patient[]
heidi_get_patientpatient_idPatient
heidi_push_notenote: NotePushNotePushResult

Optional

ToolArgumentsReturnsAdvertise capability
heidi_get_patient_contextpatient_idPatientContextpatient_context
heidi_upload_documentdocument: DocumentUploadDocumentUploadResultdocument_upload

Shapes

// ConnectorInfo
{ "connector_id": "riverbend-clinic-emr", "name": "Riverbend Clinic EMR", "vendor": "Riverbend",
  "spec_version": "0.1", "timezone": "Australia/Sydney", "practice_name": "Riverbend Family Clinic",
  "capabilities": ["practitioners","appointments","patient_search","patient_read","note_push"] }
 
// Practitioner
{ "id": "dr-chen", "display_name": "Dr Maya Chen", "role": "GP", "provider_number": null, "active": true }
 
// Appointment: start/end MUST carry a UTC offset
{ "id": "a-0001", "practitioner_id": "dr-chen", "start": "2026-10-05T09:00:00+11:00",
  "end": "2026-10-05T09:15:00+11:00", "status": "booked", "type": "Standard consult",
  "reason": "Diabetes review",
  "patient": { "id": "p-1001", "display_name": "Margaret Hughes", "date_of_birth": "1948-03-12" } }
 
// Patient
{ "id": "p-1001", "first_name": "Margaret", "last_name": "Hughes", "display_name": "Margaret Hughes",
  "date_of_birth": "1948-03-12", "sex": "F", "email": null, "phone": null, "address": null,
  "identifiers": { "medicare": "2100156789" } }
 
// NotePush (argument to heidi_push_note)
{ "patient_id": "p-1001", "practitioner_id": "dr-chen", "appointment_id": "a-0001",
  "title": "Consult note - Diabetes review", "content": "S: ...\nO: ...\nA: ...\nP: ...",
  "content_format": "text", "idempotency_key": "heidi-7f1c2a9e..." }
 
// NotePushResult
{ "note_id": "n-00042", "url": "https://emr.example.com/patients/p-1001#n-00042" }

status is one of booked, arrived, fulfilled, cancelled, noshow. Map your own states onto these.

Behaviour you must guarantee

  1. Practitioner scoping. heidi_list_appointments returns only the requested practitioner's appointments.
  2. Timezones. Appointment times include an offset. ConnectorInfo.timezone is the practice's IANA zone.
  3. Idempotent writes. If heidi_push_note (or heidi_upload_document) is called twice with the same idempotency_key, the second call returns the first result and creates nothing new. Heidi retries on network errors.
  4. Not found. An unknown patient_id returns the not_found error, not an empty patient.
  5. No PHI in logs or errors. Error messages must not contain patient data.
  6. Read-only reads. Read tools never modify your system.

Errors

Over MCP, return a tool error (isError: true) whose text content is the body below. Over REST, return it as the JSON body with the HTTP status in the table.

{ "error": { "code": "not_found", "message": "patient p-9 not found" } }
CodeREST statusWhen
unauthorized401Key revoked or practice disabled
not_found404Unknown patient, appointment or practitioner
invalid_argument400Bad input, e.g. an inverted date range or a note that's too long
rate_limited429You are throttling. Heidi backs off and retries.
unsupported501Optional capability not implemented
upstream_error502Your system failed. Heidi shows a generic error.

REST binding

All paths are relative to your base URL. Every request carries Authorization: Bearer <connector key>. Responses are application/json with exactly the shapes above. Lists are bare JSON arrays.

Method and pathToolRequestResponse
GET /infoheidi_get_connector_infoConnectorInfo
GET /practitionersheidi_list_practitionersPractitioner[]
GET /appointmentsheidi_list_appointmentsquery practitioner_id, start_date, end_dateAppointment[]
GET /patientsheidi_search_patientsquery name?, date_of_birth?, limit?Patient[]
GET /patients/{patient_id}heidi_get_patientPatient
POST /notesheidi_push_notebody NotePushNotePushResult
GET /patients/{patient_id}/contextheidi_get_patient_context (optional)PatientContext
POST /documentsheidi_upload_document (optional)body DocumentUploadDocumentUploadResult
curl -H "Authorization: Bearer $KEY" \
  "https://emr.example.com/heidi/appointments?practitioner_id=dr-chen&start_date=2026-10-05&end_date=2026-10-05"

Optional endpoints you don't implement return 501 with code unsupported, or 404.

Versioning

spec_version is 0.1. Additive changes (new optional tools or fields) stay within 0.x. Breaking changes get a new version and at least 6 months of overlap.