EHR
EHR is the NewInstance electronic health records product. This section covers the parts that are stable in this phase: reference code lookups, the outbound webhook subscriptions that tell your systems when something happens, and the event log those webhooks are built on.
How events and webhooks fit togetherlink
Every meaningful change inside EHR (a program created, a location updated, a break-the-glass session started, and so on) is appended to a per-organization event log with an increasing sequence number. A webhook subscription tells the platform which of those event types you want pushed to a URL you control; the Send a test event request lets you verify a receiver end to end without waiting for a real change.
If you would rather pull than have events pushed to you, poll List events with sinceSeq set to the nextSeq you got back last time.
Webhook URL and secret ruleslink
- HTTPS only. Loopback, private, link-local, carrier-grade NAT and unspecified addresses are rejected, both as literal IPs and after resolving the hostname.
- The signing secret (
whsec_...) is generated on creation and returned in the response body exactly once. After that, only a masked preview (whsec_••••plus the last four characters) is ever shown. - Set
includePhi: trueonly when delivered payloads may contain protected health information, and pair it with aphiAcknowledgmentTextof at least 20 characters confirming you understand that.
Schedulinglink
List appointments and Create an appointment need the scheduling scope, and Look up a client by MRN needs clients-read. Instants are always ISO 8601 in UTC, and every appointment carries the IANA zone it was booked in, so a caller in another zone can render the local wall time without guessing. A key holding scheduling alone sees the slots but no client identifiers; add clients-read to see which client each appointment belongs to.
Appointments protected by an additional consent requirement are not returned to an API key at all: they are absent from the page, from the total and from every filter, and a lookup of such a client answers exactly as an unknown record does. They still hold their slot, so a booking over one comes back as a clash without naming what is in the way.
The inbound SMS webhook is the one EHR endpoint that takes no API key: it is authenticated by your provider's request signature instead.
Permission scopes for EHR API keyslink
| Scope code | Description |
|---|---|
full-access | All EHR permissions |
webhooks | Create, update, delete and test webhook subscriptions, and read the event log |
scheduling | List and create appointments |
clients-read | Look up a client by medical record number, and see client identifiers on appointments |
Reference code lookups only need the key to carry any ehr product scope, full access or a specific group such as webhooks, not a dedicated scope of their own.
List reference codes
Searches ICD-10-CM, HCPCS, place of service, modifier, LOINC, RxNorm and taxonomy reference codes. Matches code prefix or display text substring, case insensitive, sorted by code. Any ehr product scope on the key is enough, no specific group is required.
Authorization
x-api-keyAPI key · headerrequiredParameters
systemquery · stringdefault: Optional. Code system: ICD10CM, HCPCS, POS, MODIFIER, LOINC, RXNORM or TAXONOMY. Omit it to search every system.
qquery · stringdefault: Optional. Search text, 1 to 80 characters. Matches a code prefix or a display text substring, case insensitive.
limitquery · stringdefault: Optional. Number of codes to return, 1 to 100. Defaults to 25.
Responses
200Reference codes401Invalid or missing API key403Missing permission scopecurl -X GET 'https://api.newinstance.cloud/api/v1/ehr/reference-codes?system=ICD10CM&q=chol&limit=25' \
-H 'x-api-key: YOUR_API_KEY'{
"items": [
{
"system": "ICD10CM",
"code": "A00",
"display": "Cholera"
}
]
}List webhook subscriptions
Returns this organization's webhook subscriptions, newest first. Each item carries a masked secret preview, never the real secret.
Authorization
x-api-keyAPI key · headerrequiredResponses
200Webhook subscriptions401Invalid or missing API key403Missing permission scopecurl -X GET 'https://api.newinstance.cloud/api/v1/ehr/webhooks' \
-H 'x-api-key: YOUR_API_KEY'{
"items": [
{
"id": "66f1a2b3c4d5e6f7a8b9c0d1",
"name": "Order sync",
"url": "https://example.com/hooks/ehr",
"events": [
"ehr.program.created",
"ehr.program.updated"
],
"status": "active",
"includePhi": false,
"failureCount": 0,
"secretMasked": "whsec_••••ab12",
"createdAt": "2026-09-01T12:00:00.000Z",
"updatedAt": "2026-09-01T12:00:00.000Z"
}
]
}Create a webhook subscription
Creates a webhook subscription. The response includes the signing secret in clear text. Copy it now, it is never shown again. A key issued by a member whose role does not reach every client is refused, because a webhook is sent events about every client. The member who issued the key becomes the member the webhook is delivered under, and nothing more is sent to it once that member no longer reaches every client or leaves the organization, until a member who does saves it again.
Authorization
x-api-keyAPI key · headerrequiredRequest body
application/json{
"name": "Order sync",
"url": "https://example.com/hooks/ehr",
"events": [
"ehr.program.created",
"ehr.program.updated"
],
"includePhi": false
}Responses
201Webhook subscription created400Validation error401Invalid or missing API key403Missing permission scopecurl -X POST 'https://api.newinstance.cloud/api/v1/ehr/webhooks' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
--data-raw '{
"name": "Order sync",
"url": "https://example.com/hooks/ehr",
"events": [
"ehr.program.created",
"ehr.program.updated"
],
"includePhi": false
}'{
"id": "66f1a2b3c4d5e6f7a8b9c0d1",
"name": "Order sync",
"url": "https://example.com/hooks/ehr",
"events": [
"ehr.program.created",
"ehr.program.updated"
],
"status": "active",
"includePhi": false,
"failureCount": 0,
"secretMasked": "whsec_••••ab12",
"secret": "whsec_5f2b9c1a7d3e4f6089ab12",
"createdAt": "2026-09-01T12:00:00.000Z",
"updatedAt": "2026-09-01T12:00:00.000Z"
}Send a test event
Queues an ehr.webhook.test event and a pending delivery for this subscription, so you can confirm your receiver handles a delivery correctly. ehrWebhookId in the path is the id returned by Create a webhook subscription, which Postman stores after that request runs.
Authorization
x-api-keyAPI key · headerrequiredParameters
ehrWebhookIdpath · stringrequireddefault: Responses
202Test event queued401Invalid or missing API key403Missing permission scope404Webhook subscription not foundcurl -X POST 'https://api.newinstance.cloud/api/v1/ehr/webhooks/{ehrWebhookId}/test' \
-H 'x-api-key: YOUR_API_KEY'{
"eventId": "66f1a2b3c4d5e6f7a8b9c0d2",
"deliveryId": "66f1a2b3c4d5e6f7a8b9c0d3"
}List events
Returns this organization's event log in sequence order. Pass the previous nextSeq back as sinceSeq to continue from where you left off. An event that names a client protected by 42 CFR Part 2 or a client with no record, or that is about an appointment marked protected or one that cannot be found, is left out, and nextSeq still moves past it. A key issued by a member whose role does not reach every client, such as a clinician who reads a caseload, is refused before a record is read; issue the key from the front desk or an administrator.
Authorization
x-api-keyAPI key · headerrequiredParameters
sinceSeqquery · stringdefault: Optional. Return only events with a sequence number greater than this value. Pass the previous nextSeq to continue.
limitquery · stringdefault: Optional. Number of events to return, 1 to 500. Defaults to 100.
Responses
200Event log page401Invalid or missing API key403Missing permission scopecurl -X GET 'https://api.newinstance.cloud/api/v1/ehr/events?sinceSeq=0&limit=100' \
-H 'x-api-key: YOUR_API_KEY'{
"items": [
{
"id": "66f1a2b3c4d5e6f7a8b9c0d2",
"seq": 1,
"type": "ehr.webhook.test",
"occurredAt": "2026-09-01T12:00:00.000Z",
"aggregate": {
"type": "webhook_subscription",
"id": "66f1a2b3c4d5e6f7a8b9c0d1"
},
"status": "pending"
}
],
"nextSeq": 1
}List appointments
Returns appointments that overlap the requested range, oldest first. Every instant is ISO 8601 in UTC and each appointment carries the IANA zone it was booked in, so a client in another zone can render the local wall time correctly. Needs the scheduling scope. A key issued by a member whose role does not reach every client, such as a clinician who reads a caseload, is refused before a record is read; issue the key from the front desk or an administrator.
Authorization
x-api-keyAPI key · headerrequiredParameters
fromquery · stringdefault: Required. Range start, an ISO 8601 instant.
toquery · stringdefault: Required. Range end, an ISO 8601 instant.
pagequery · stringdefault: Optional. Page number, from 1. Defaults to 1.
limitquery · stringdefault: Optional. Appointments per page, 1 to 100. Defaults to 25.
Responses
200Appointment page400Validation error401Invalid or missing API key403Missing permission scopecurl -X GET 'https://api.newinstance.cloud/api/v1/ehr/appointments?from=2026-10-25T00%3A00%3A00.000Z&to=2026-10-26T00%3A00%3A00.000Z&page=1&limit=25' \
-H 'x-api-key: YOUR_API_KEY'{
"items": [
{
"id": "66f1a2b3c4d5e6f7a8b9c0e1",
"seriesId": null,
"typeId": "66f1a2b3c4d5e6f7a8b9c0a1",
"status": "scheduled",
"clientIds": [
"66f1a2b3c4d5e6f7a8b9c0b1"
],
"primaryStaffId": "66f1a2b3c4d5e6f7a8b9c0c1",
"staffIds": [
"66f1a2b3c4d5e6f7a8b9c0c1"
],
"roomLocationId": "66f1a2b3c4d5e6f7a8b9c0d4",
"locationId": null,
"programId": null,
"serviceCodeId": null,
"start": "2026-10-25T11:00:00.000Z",
"end": "2026-10-25T12:00:00.000Z",
"timezone": "America/New_York",
"checkInAt": null,
"checkOutAt": null,
"encounterId": null
}
],
"total": 1,
"page": 1,
"limit": 25
}Create an appointment
Books an appointment. Send start and end in UTC and the zone the time was chosen in. A clash returns 409 naming the resource already booked, unless the organization double-booking policy allows it or you send allowConflicts. A client, staff member, room, program or appointment type that cannot take the booking is refused with 4xx and a message saying what to change; a 503 means the service could not confirm its own indexes and the request is worth retrying. A key issued by a member whose role does not reach every client, such as a clinician who reads a caseload, is refused before a record is read; issue the key from the front desk or an administrator.
Authorization
x-api-keyAPI key · headerrequiredRequest body
application/json{
"typeId": "66f1a2b3c4d5e6f7a8b9c0a1",
"clientIds": [
"66f1a2b3c4d5e6f7a8b9c0b1"
],
"primaryStaffId": "66f1a2b3c4d5e6f7a8b9c0c1",
"start": "2026-10-26T13:00:00.000Z",
"end": "2026-10-26T14:00:00.000Z",
"timezone": "America/New_York"
}Responses
201Appointment booked400Validation error401Invalid or missing API key403Missing permission scope409Booking clashcurl -X POST 'https://api.newinstance.cloud/api/v1/ehr/appointments' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
--data-raw '{
"typeId": "66f1a2b3c4d5e6f7a8b9c0a1",
"clientIds": [
"66f1a2b3c4d5e6f7a8b9c0b1"
],
"primaryStaffId": "66f1a2b3c4d5e6f7a8b9c0c1",
"start": "2026-10-26T13:00:00.000Z",
"end": "2026-10-26T14:00:00.000Z",
"timezone": "America/New_York"
}'{
"id": "66f1a2b3c4d5e6f7a8b9c0e2",
"seriesId": null,
"typeId": "66f1a2b3c4d5e6f7a8b9c0a1",
"status": "scheduled",
"clientIds": [
"66f1a2b3c4d5e6f7a8b9c0b1"
],
"primaryStaffId": "66f1a2b3c4d5e6f7a8b9c0c1",
"staffIds": [
"66f1a2b3c4d5e6f7a8b9c0c1"
],
"roomLocationId": null,
"locationId": null,
"programId": null,
"serviceCodeId": null,
"start": "2026-10-26T13:00:00.000Z",
"end": "2026-10-26T14:00:00.000Z",
"timezone": "America/New_York",
"checkInAt": null,
"checkOutAt": null,
"encounterId": null
}List claims
Lists claims newest first with what each one is worth and whether the clearinghouse answered. Needs the billing-read group on the key and a creator who holds the permission to view billing amounts. Claims for a client protected by 42 CFR Part 2 are in neither the rows nor the total. Payer reason codes are on the single claim read, never here. A key issued by a member whose role does not reach every client, such as a clinician who reads a caseload, is refused before a record is read; issue the key from the front desk or an administrator.
Authorization
x-api-keyAPI key · headerrequiredParameters
pagequery · stringdefault: Optional. Page number, from 1. Defaults to 1.
limitquery · stringdefault: Optional. Claims per page, 1 to 100. Defaults to 25.
Responses
200Claims401Invalid or missing API key403Missing permission scopecurl -X GET 'https://api.newinstance.cloud/api/v1/ehr/billing/claims?page=1&limit=25' \
-H 'x-api-key: YOUR_API_KEY'{
"items": [
{
"id": "66f1a2b3c4d5e6f7a8b9c0e1",
"payerId": "66f1a2b3c4d5e6f7a8b9c0e2",
"controlNumber": "10001",
"status": "queued",
"chargeCount": 1,
"totalAmountMinor": 12500,
"currency": "USD",
"transmission": {
"status": "acknowledged",
"sentAt": "2026-09-02T11:00:00.000Z",
"acknowledgedAt": "2026-09-03T11:00:00.000Z"
},
"submittedAt": "2026-09-02T10:00:00.000Z"
}
],
"total": 1,
"page": 1,
"limit": 25
}Read one claim
Returns one claim with its service lines, the state of its transmission, and the payer reason and remark codes where the payer denied it, with deniedAt, the date the payer gave for the denial, as that calendar date in the form YYYY-MM-DD, such as 2026-09-11, with no time of day. The claim file itself, which carries the member number, the name, the date of birth and the diagnoses, is never returned. A claim for a Part 2 client answers 404. A key issued by a member whose role does not reach every client, such as a clinician who reads a caseload, is refused before a record is read; issue the key from the front desk or an administrator. ehrClaimId in the path is a claim id from List claims, which Postman stores after that request runs.
Authorization
x-api-keyAPI key · headerrequiredParameters
ehrClaimIdpath · stringrequireddefault: Responses
200Claim401Invalid or missing API key403Missing permission scope404Claim not foundcurl -X GET 'https://api.newinstance.cloud/api/v1/ehr/billing/claims/{ehrClaimId}' \
-H 'x-api-key: YOUR_API_KEY'{
"id": "66f1a2b3c4d5e6f7a8b9c0e1",
"payerId": "66f1a2b3c4d5e6f7a8b9c0e2",
"controlNumber": "10001",
"payerClaimControlNumber": null,
"status": "queued",
"format": "837P",
"frequencyCode": "1",
"totalAmountMinor": 12500,
"currency": "USD",
"transmission": {
"status": "acknowledged",
"sentAt": "2026-09-02T11:00:00.000Z",
"acknowledgedAt": "2026-09-03T11:00:00.000Z"
},
"lines": [
{
"lineNo": 1,
"chargeId": "66f1a2b3c4d5e6f7a8b9c0e3",
"serviceCode": "90834",
"modifiers": [],
"units": 1,
"amountMinor": 12500,
"dateOfService": "2026-09-01"
}
],
"denial": {
"status": "open",
"reasons": [
"CO-97"
],
"remarkCodes": [
"N19"
],
"deniedMinor": 2500,
"allowedMinor": 10000,
"deniedAt": "2026-09-11"
},
"submittedAt": "2026-09-02T10:00:00.000Z",
"updatedAt": "2026-09-02T10:00:00.000Z"
}Read one charge and its ledger
Returns one charge and every ledger entry posted against it, with what each party still owes on it: payerOwedMinor for the insurer, clientOwedMinor for the client, and transferredToClientMinor for what has moved from one to the other. There is no single party blind balance, because once responsibility has moved between the two a single figure names neither of them. The entry count is there because nothing owed is also what a charge nothing ever posted to looks like. Diagnoses are not returned. The figures are worked out from the entries returned beside them when the charge is read, so the two always agree. A charge for a Part 2 client answers 404. A key issued by a member whose role does not reach every client, such as a clinician who reads a caseload, is refused before a record is read; issue the key from the front desk or an administrator. ehrChargeId in the path is a chargeId from the lines of Read one claim.
Authorization
x-api-keyAPI key · headerrequiredParameters
ehrChargeIdpath · stringrequireddefault: Responses
200Charge and ledger401Invalid or missing API key403Missing permission scope404Charge not foundcurl -X GET 'https://api.newinstance.cloud/api/v1/ehr/billing/charges/{ehrChargeId}' \
-H 'x-api-key: YOUR_API_KEY'{
"id": "66f1a2b3c4d5e6f7a8b9c0e3",
"serviceCode": "90834",
"modifiers": [],
"units": 1,
"dateOfService": "2026-09-01",
"amountMinor": 12500,
"currency": "USD",
"status": "ready",
"payerOwedMinor": 0,
"clientOwedMinor": 2500,
"transferredToClientMinor": 2500,
"entryCount": 4,
"entries": [
{
"kind": "charge",
"sourceType": "charge",
"amountMinor": 12500,
"currency": "USD",
"payerId": "66f1a2b3c4d5e6f7a8b9c0e2",
"postedAt": "2026-09-01T12:00:00.000Z"
},
{
"kind": "payer_payment",
"sourceType": "remittance_line",
"amountMinor": 8000,
"currency": "USD",
"payerId": "66f1a2b3c4d5e6f7a8b9c0e2",
"postedAt": "2026-09-10T12:00:00.000Z"
},
{
"kind": "contractual_adjustment",
"sourceType": "remittance_line",
"amountMinor": 2000,
"currency": "USD",
"payerId": "66f1a2b3c4d5e6f7a8b9c0e2",
"postedAt": "2026-09-10T12:00:00.000Z"
},
{
"kind": "transfer_to_client",
"sourceType": "remittance_line",
"amountMinor": 2500,
"currency": "USD",
"payerId": null,
"postedAt": "2026-09-10T12:00:00.000Z"
}
],
"capturedAt": "2026-09-01T12:00:00.000Z"
}Look up a client by MRN
Returns the demographic summary for one client by medical record number. The number is sent in the request body, never in the path or the query string, because those reach an access log. Needs the clients-read scope, and a key issued by a member whose role reaches every client, such as the front desk or an administrator; any other key is refused before a record is read. Every call is written to the access log with the API key as the actor.
Authorization
x-api-keyAPI key · headerrequiredRequest body
application/json{
"mrn": ""
}Responses
200Client summary401Invalid or missing API key403Missing permission scope404No such clientcurl -X POST 'https://api.newinstance.cloud/api/v1/ehr/clients/lookup' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
--data-raw '{
"mrn": ""
}'{
"id": "66f1a2b3c4d5e6f7a8b9c0b1",
"mrn": "MRN-1042",
"firstName": "Ada",
"lastName": "Okafor",
"dob": "1984-03-09",
"status": "active",
"part2": false,
"primaryProgramId": "66f1a2b3c4d5e6f7a8b9c0f4",
"primaryClinicianStaffId": "66f1a2b3c4d5e6f7a8b9c0c1"
}Inbound SMS webhook
Receives the message replies your SMS provider posts. The request carries the provider signature, so no API key is used. A signature that does not verify answers 401 with an empty body. A reply of C, CONFIRM, YES or Y confirms the next appointment within seven days, except from a number more than one client shares, where it confirms nothing and the reply is recorded as ignored. STOP, STOPALL, UNSUBSCRIBE, CANCEL, END or QUIT removes text message consent for that number immediately, so a reply of CANCEL opts the number out of text messages and cancels no appointment.
Headers
x-twilio-signatureRequest body
application/x-www-form-urlencoded{
"To": "+15550100000",
"From": "+15550101234",
"Body": "C",
"MessageSid": "SM00000000000000000000000000000001"
}Responses
204Reply handled400Validation error401Signature did not verify, empty body404No organization owns that numbercurl -X POST 'https://api.newinstance.cloud/api/v1/ehr/sms/inbound' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-raw '{
"To": "+15550100000",
"From": "+15550101234",
"Body": "C",
"MessageSid": "SM00000000000000000000000000000001"
}'nullDelete a webhook subscription
Soft deletes a webhook subscription. It stops receiving deliveries immediately and drops out of the list. ehrWebhookId in the path is the id returned by Create a webhook subscription. A key issued by a member whose role does not reach every client is refused, because a webhook is sent events about every client.
Authorization
x-api-keyAPI key · headerrequiredParameters
ehrWebhookIdpath · stringrequireddefault: Responses
204Subscription deleted401Invalid or missing API key403Missing permission scope404Webhook subscription not foundcurl -X DELETE 'https://api.newinstance.cloud/api/v1/ehr/webhooks/{ehrWebhookId}' \
-H 'x-api-key: YOUR_API_KEY'nullUpdate a webhook subscription
Updates one or more fields on a webhook subscription: name, url, events, or status. At least one field is required. ehrWebhookId in the path is the id returned by Create a webhook subscription. A key issued by a member whose role does not reach every client is refused, because a webhook is sent events about every client. The member who issued the key becomes the member the webhook is delivered under, and nothing more is sent to it once that member no longer reaches every client or leaves the organization, until a member who does saves it again.
Authorization
x-api-keyAPI key · headerrequiredParameters
ehrWebhookIdpath · stringrequireddefault: Request body
application/json{
"status": "paused"
}Responses
200Webhook subscription updated400Validation error401Invalid or missing API key403Missing permission scope404Webhook subscription not foundcurl -X PATCH 'https://api.newinstance.cloud/api/v1/ehr/webhooks/{ehrWebhookId}' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
--data-raw '{
"status": "paused"
}'{
"id": "66f1a2b3c4d5e6f7a8b9c0d1",
"name": "Order sync",
"url": "https://example.com/hooks/ehr",
"events": [
"ehr.program.created",
"ehr.program.updated"
],
"status": "paused",
"includePhi": false,
"failureCount": 0,
"secretMasked": "whsec_••••ab12",
"createdAt": "2026-09-01T12:00:00.000Z",
"updatedAt": "2026-09-01T12:05:00.000Z"
}