The Note Format
The same note travels every integration path, so it is the part worth understanding first. It is a set of ordered, titled sections with typed rich text, not a transcript, which is what makes it mappable into the fields your chart already has.
What a Note Is Made Of
A note is an ordered list of titled sections. Each section holds its own rich text as typed blocks rather than as markup. That model is what lets the same note pass through editing, offline storage and sync without losing its shape, and it is what lets your side route sections into fields instead of into one box.
| Element | What it carries |
|---|---|
| Format | SOAP, H&P, or a custom template the practice defines |
| Sections | An ordered list, each with a stable title and its own body |
| Blocks | Within a section: paragraphs, headings, bulleted and numbered lists |
| Emphasis | Bold and italic, carried as marks on spans of text rather than as HTML |
| Template name | Which template produced the note, so your side can branch on it |
The Section Vocabularies
Two built-in shapes cover most documentation. Practices can also define their own templates, in which case the titles are theirs. Treat section titles as data rather than as a fixed list you hard-code, because a custom template will not match either column below.
SOAP
Subjective, Objective, Assessment, Plan.
H&P
Chief Complaint, History of Present Illness, Past Medical History, Medications, Allergies, Social History, Family History, Review of Systems, Physical Examination, Assessment, Plan.
Custom
Section titles defined by the practice, in their own order. The note carries the template name alongside the sections so your integration can branch on it.
What Travels With It
The content is only half of what you need. The rest is provenance: how the note was captured, whether a human has reviewed it, and what the coder should look at.
| Field | What it tells you |
|---|---|
| Capture mode | Ambient, drafted from the visit conversation, or live dictation |
| Duration | Length of the recording the note came from |
| Word count | Computed across all sections |
| State | Draft, finalized, or archived |
| Version | Increments on edit, with prior versions retained |
| Suggested codes | Billing codes extracted from the encounter, each pending until confirmed |
For how ambient capture differs from dictation, see ambient clinical documentation.
Four Decisions Worth Knowing About
Sections map, transcripts do not
A wall of text can only ever land in one free-text box. Titled sections can be routed into the discrete fields your chart already has, which is the difference between a note that arrives and a note that is usable.
Blocks survive the round trip
Rich text is carried as typed blocks and marked spans rather than as HTML, so a note keeps its structure through editing, offline storage and sync without accumulating markup. What you receive is what the clinician saw.
Draft and finalized are different things
A note carries its state explicitly. That matters at your end, because writing an unreviewed draft into a chart as though it were signed is a compliance problem rather than an integration convenience.
Codes travel with the note
Suggested billing codes are extracted from the same encounter and arrive alongside the note, each one pending until a human confirms it. Nothing is asserted as final on the clinician’s behalf.
On the Wire, v1
This is what arrives at the endpoint you expose. Published in full because you should be able to write the handler before talking to us, and because a serialisation you cannot see is not something you can estimate.
POST https://your-endpoint.example.com/voiceboxmd/notes
Content-Type: application/json
{
"version": "1",
"event": "note.finalized",
"deliveryId": "dlv_8f2c1a...",
"occurredAt": "2026-08-03T14:12:09Z",
"clinician": { "externalId": "the id you gave us at link time" },
"note": {
"id": "note_4b91...",
"status": "finalized",
"format": "soap",
"templateName": "SOAP",
"recordingMode": "ambient",
"durationSeconds": 412,
"wordCount": 380,
"revision": 3,
"sections": [
{
"title": "Subjective",
"blocks": [
{
"type": "paragraph",
"spans": [
{ "text": "Patient reports ", "marks": [] },
{ "text": "worsening", "marks": ["bold"] },
{ "text": " cough for three days.", "marks": [] }
]
}
]
}
]
},
"codes": [
{
"code": "99213",
"type": "CPT",
"description": "Established patient office visit",
"confidence": 82,
"sourceText": "office visit",
"status": "pending"
}
]
}Codes carry a confidence from 0 to 100 and the sourceText they were drawn from, so a coder can jump to the sentence that produced a suggestion instead of re-reading the note. At most 25 are returned, low-confidence ones are flagged, and each stays pending until a human confirms or rejects it.
Verifying a Delivery
Each request carries a timestamp and an HMAC-SHA256 signature over the timestamp and the raw body, computed with the secret you issued us.
X-VoiceboxMD-Delivery: dlv_8f2c1a...
X-VoiceboxMD-Event: note.finalized
X-VoiceboxMD-Signature: t=1785766329,v1=5257a869e7...
signed_payload = "${t}." + raw_request_body
expected = hex( hmac_sha256(your_shared_secret, signed_payload) )Compare in constant time, and reject a timestamp outside your tolerance so a captured request cannot be replayed. Verify against the raw body rather than a re-serialised copy, because re-encoding JSON changes the bytes and the comparison then fails for reasons that are painful to debug. Retries reuse the delivery id, so treat it as an idempotency key.
v1 is the contract we build to with partners, and it freezes once the first one ships against it. New optional fields can appear; breaking changes mean a v2 alongside it.
See the integration pathsThe Note Format, Frequently Asked Questions
Do we receive a transcript or a note?
A note. VoiceboxMD produces an ordered set of titled sections in SOAP or H&P shape, or against a custom template the practice defines, with the conversational filler removed. A raw transcript is an intermediate artifact, not the deliverable, because a transcript cannot be mapped into the discrete fields of a chart.
Which sections should we expect?
SOAP notes carry Subjective, Objective, Assessment and Plan. H&P notes carry Chief Complaint, History of Present Illness, Past Medical History, Medications, Allergies, Social History, Family History, Review of Systems, Physical Examination, Assessment and Plan. Practices can also define custom templates, in which case the section titles are theirs, so treat titles as data rather than as an enum you hard-code.
How is formatting represented?
Each section holds ordered blocks, which are paragraphs, headings, bulleted or numbered list items. Text within a block is carried as spans that may be marked bold or italic. Formatting is structural rather than HTML, which is what lets a note round-trip through editing, offline storage and sync without degrading.
Can we tell whether the clinician reviewed it?
Yes. Every note carries an explicit state of draft, finalized or archived, and a version that increments as it is edited. An ambient note begins as a draft because it was generated from a conversation and has not yet been reviewed. Integrations should treat that distinction as meaningful rather than writing every note into the chart the same way.
Are the billing codes reliable enough to submit?
They are suggestions extracted from the encounter, and each one stays pending until a human confirms or rejects it. They are intended to save the coder time rather than to replace the review step, and an integration should carry the pending state through rather than treating a suggestion as an assertion.
Is the payload versioned, and can it change?
Every delivery carries a version, and what is published here is v1. Additive changes, meaning new optional fields, can appear within v1, so parse defensively and ignore what you do not recognise. Anything that would break an existing integration means a v2 delivered alongside v1 rather than instead of it, with a deprecation window. v1 freezes once the first partner ships against it.
How do we verify a delivery actually came from VoiceboxMD?
Each request carries a timestamp and an HMAC-SHA256 signature over the timestamp and the raw request body, computed with the secret you issued us. Compute the same value and compare, and reject anything with a timestamp outside your tolerance so a captured request cannot be replayed later. Verify against the raw body rather than a re-serialised copy, since re-encoding JSON changes the bytes and breaks the comparison.
What happens if our endpoint is down?
Deliveries are retried with exponential backoff. Every delivery carries a stable id, and a retry reuses it, so treat that id as an idempotency key rather than assuming each request is a new note. Respond 2xx once you have durably accepted the payload; anything else is treated as a failure and retried.
A note your chart can actually use.
Sections, not transcripts. The same payload on every path.
Talk to us about integrating