Reference
Changelog
2026-10-07: Self-serve webhook events are picked from the Entity dropdown
- Opting in to
clinicalDataAddedandaiResearchCompletedmoved. On the Notifications tab both events are now picked from the Events group of the subscription builder’s Entity dropdown, when creating an endpoint and when adding to one, instead of being ticked in a separate Other events list. An endpoint can carry either event alone or alongside its subscriptions, and each one is listed with them on the endpoint and removed the same way. Delivery is unchanged.
2026-10-06: Companies report whether in-network requests are enabled
- New
company.inNetworkRequestEnabledfield. Every browse endpoint that can select or filter on the company now accepts and returnsinNetworkRequestEnabled, a boolean saying whether the company is approved to use in-network requests. It isfalseuntil Hermes staff turn it on, alongsiderecordRequestEnabled.
2026-10-06: Webhooks subscribe to named events
New webhook endpoints subscribe to named events instead of picking table
columns. Events are grouped by product capability and named group.event,
such as recordRequest.completed, siteSonar.completed or
authorization.approved; ticking a group subscribes to every event in it.
Each group sends one fixed, documented data payload, and every delivery
carries "version": "events". One endpoint-level scope (which projects, whose
records) replaces the per-subscription scope.
siteSonar.completed, patientHistories.completed and ehrSearch.completed
are sent when a run finishes, whatever the result, so repeating a search that
ends the same way still sends an event.
clinicalData.added and aiResearch.completed are now signed with a
timestamp, carry X-Webhook-Id, and are retried like every other event.
Existing endpoints become Classic endpoints and keep receiving exactly the
deliveries they did, with no version field; the Classic webhooks entries
are marked deprecated. No new Classic endpoint can be created. Each Classic
endpoint offers Upgrade to Events in the web app, with a preview of how its
subscriptions map.
2026-10-06: Joined columns keep their access rules; site tax ID is Hermes-only
- A Hermes-only column stays Hermes-only when a browse reaches it through
a join. A column the API withholds from your account on its own browse
(for example
visit.dataSourcesonPOST /v0/visits/browse) is now withheld the same way when another browse joins to it, such asvisitonPOST /v0/procedures/browseorlabAccession.orderingPhysicianSiteonPOST /v0/lab-results/browse. Selecting it returns no value, and a filter, sort or aggregate on it is ignored rather than applied. - A site’s
taxIdis no longer returned. The site tax identification number is now Hermes-only wherever the API returns a site. That coversGET /v0/sites/{site_id}(including itsreferencehalf),GET /v0/sites/random,POST /v0/sites,PUTandPATCH /v0/sites/{site_id},POST /v0/sites/{site_id}/research, the site-finder job and record-request site finder responses, and the site embedded in record-request responses. On those routestaxIdreads as an empty string. On every browse that joins a site the column is still accepted in aselect, filter or sort, and is ignored.
2026-10-06: Embed tokens without parentOrigin deprecated; parentOrigin checked strictly
- Minting a write-capable embed token without
parentOriginis deprecated. This covers the auth-intake, site finder and clinical-data embed-token routes. A mint without it still succeeds and keeps today’s behavior (any page may frame the iframe, and the clinical-data iframe posts its browse state to any parent), but a later release will requireparentOriginand answer a mint without it with400. Send it now. parentOriginis checked more strictly. It must be one exacthttps://host[:port]origin: a wildcard host (https://*.example.com), credentials, a path, query or fragment, or whitespace, control characters or backslashes inside the value is answered with400, as is any origin not on your approved list. An approved origin written plainly, ashttps://host[:port], is accepted exactly as before, and leading or trailing whitespace around it is still ignored.- Guides: the site finder guide now shows sending
parentOrigin, and both embed guides mark leaving it out as deprecated.
2026-10-05: Webhook event schemas for clinical data added and AI research completed
clinicalDataAddedandaiResearchCompletedare in the spec. The top-levelwebhookssection now documents both events alongside the subscription events, with the two-fieldeventType/databody each is delivered with and the schema of its payload:ClinicalDataAddedPayload(with its per-typecountsandsource) andAiResearchCompletedPayload. Neither delivery changed; only its documentation is new.- Each subscription event’s body names its own
eventType. The envelope every subscription delivery carries is unchanged, and itseventTypeis now published as the one value that entry delivers rather than as any string. sourcecan beparsePass. AclinicalDataAddeddelivery already reportedparsePassfor content surfaced by re-reading clinical data Hermes holds; the reference now lists it besidesiteSonar,patientHistoriesandsandboxSearch.- Guides:
ccdais optional when creating a record request and defaults tofalse; the guide used to call all four deliverable flags required. The browse aggregation example no longer asks forminandmaxof visit service dates, which the API rejects: those aggregates take numeric columns only.
2026-10-05: Purpose alignment judged against the project’s purpose; dates of service pass on coverage
purposeAlignmentis judged against the project’s purpose. Theverdicts.purposeAlignmentitem onGETandPUT /v0/auth-check/{filename}, on the patient and record-request authorization reads, and on the project letter responses compares the form’s classifiedauthorizationPurposewith the purpose of the project the document belongs to, no longer with the set of purposes the company is authorized for. AGeneralgrant passes, a different purpose fails naming both, and a project with no purpose fails every classified form. The item staysnullfor an analysis without a classification and for a standalone submission, which belongs to no project.- Minting a signing link needs the project’s purpose. The
/auth-intake/embed-tokenroutes answer400withProject purpose is requiredfor a project that names none; the generated authorization states that purpose. - Dates of Service passes when the form’s range covers the request’s. The
check used to require the form’s start and end to equal the request’s, so a
form granting 2015 to present failed a request for 2020 to 2023. A covering
range now passes. A failure names the side the form does not cover, for
example
startDateOfService: request starts 2018-01-01, before the form's start 2020-01-01.
2026-10-04: Deleting a patient’s authorization answers 404 for an unknown patient
- Deleting a patient’s authorization now answers 404 for an unknown
patient.
DELETE /v0/companies/{companyId}/projects/{projectId}/patients/{patientId}/authorizationused to answer200whatever the patient, even when no such patient existed. It now answers404when the patient does not exist or is not visible to the caller, and deletes the document only for a patient the caller can see. For a patient that exists, the call is unchanged, including the200when no document is on file.
2026-10-04: Browse columns and value formats described
The API itself is unchanged; these are changes to what the reference and the spec describe.
- Browse columns are described wherever they appear. A column’s
description used to be published only on the row it is returned in. The
same sentence is now on that column in every browse request schema: the
filter (
where), the field selection (select), the sort, and the numeric aggregates. The keys that name an entity or a joined entity insidewhere,selectandorderByare described too, including theisNull/isNotNullshorthand a joined entity’s filter accepts. - Validated values document their format. Each value type the API checks, such as a ZIP code, a US state, a person’s name, a phone number, a date of birth or an identifier, now states in the spec what it accepts, how it is normalized, and that any other value is rejected. The reference repeats those rules under every field of that type, in the HTML pages and in their Markdown versions.
2026-10-04: Machine-readable docs, deprecation flags and documented 401s
The API itself is unchanged except where noted; these are changes to what the reference publishes and how it can be read.
- Markdown and
llms.txt. Every page of the reference and the guides is also served as Markdown at the same path with.mdappended./llms.txtlists them all, and/llms-full.txtis every guide and reference section in one file. - Per-group spec slices.
/api-docs/openapi/<tag>.jsonserves one endpoint group’s operations with only the schemas they use, for example/api-docs/openapi/patients.json. servers. The spec now declareshttps://api.hermeshealth.aias its server, and no longer publishes a blanklicense.- Deprecation flags. These fields are marked
deprecated: true. They still work; read the replacement in new code:siteSonarStatuson the patient response: readsearchStatus.hipaaAuthorizationon the patient output: readauthorization.zipCodeon the patient response and the patient form: usezipCodes.lastNameon the patient form: uselastNames.isSandboxon the project form: usestatus.siteAddresson the record request form: usesiteAddressLine1andsiteAddressLine2.
lastNames,zipCodesandcityStatesare in the patient form schema. The routes always accepted them; the published request body had left them out.401on every authenticated route. Twenty-six operations now document their401response. On those routes a401raised while handling the request used to be answered as a500; it is now answered as a401.recordRequest.followUpDuewebhook. The event was already delivered and is now listed under the spec’swebhooks.- Descriptions and examples. Every operation, path parameter, enum and customer-facing field has a description; enum values list what each one means and which statuses are terminal. Patients, record requests, projects, sites, files and notes carry example values.