SOAPNoteAPI

SOAPNoteAPI Documentation

Generate HIPAA-compliant SOAP notes from transcripts or audio. All endpoints are under https://api.soapnoteapi.com.

Getting Started

Authentication, base URL, and your first API call.

Sandbox mode: Sign up for a free account to get a test key (snapi_sk_test_...). Every account gets a $10 signup credit. Test keys work on all endpoints and generate real SOAP notes, limited to 10 requests/day. No credit card required. Try the interactive Playground at app.soapnoteapi.com. Get your key →


Authentication

All requests must include your API key as a Bearer token.

API keys are scoped to your account and can be created or revoked from the dashboard. Use snapi_sk_test_... keys for development and snapi_sk_live_... keys for production.

Request header
Authorization: Bearer snapi_sk_live_••••••••••••••••
HeaderRequiredDescription
AuthorizationRequiredBearer <snapi_sk_...>
Content-TypeRequiredapplication/json (for JSON endpoints)

Generate note

Convert a transcript into a structured SOAP note. Optionally supply clinical context, billing codes, and a patient-facing summary.

POST/v1/note

Accepts a clinical transcript (dictation, conversation summary, or raw notes) and returns a structured SOAP note. Response is synchronous for text inputs — you get the note in one call. Providing a context object improves note accuracy by grounding the AI in existing patient data, prior visit notes, and pre-visit chat messages.

Request body

FieldTypeRequiredDescription
transcriptstringRequiredRaw clinical text to convert. Min 50 chars.
specialtystringRequiredMedical specialty. See specialties list.
templatestringOptional"standard" (default) or a custom template ID.
contextobjectOptionalClinical context object. See context fields below.
include_billing_codesbooleanOptionalWhen true, returns suggested ICD-10, CPT, and HCPCS codes (decision support — clinician review required). Default: false.
include_icd11booleanOptionalWhen true, the billing_codes object also includes advisory ICD-11 codes (reference only — not accepted by US payers). Used with include_billing_codes. Default: false.
include_patient_summarybooleanOptionalWhen true, returns a plain-language patient-facing summary. Default: false.
Legacy aliases: The fields shorthand_notes (alias for transcript), provider_type (alias for specialty), and template_id (alias for template) are still accepted for backward compatibility but are deprecated. Use the primary field names above.

context object fields

All fields within context are optional. Include only what you have — the more context you provide, the more accurate and complete the generated note will be.

FieldTypeDescription
patient_infoobjectStructured patient demographics and clinical data. See patient_info fields below.
patient_historystringFree-text summary of prior visit notes or relevant history.
chat_messagesarrayPre-visit or in-visit messages between patient and provider. Each item: { role, content, timestamp }.

context.patient_info fields

FieldTypeDescription
namestringPatient's full name.
agenumberPatient's age in years.
genderstringPatient gender (e.g., "male", "female", "non-binary").
medicationsstring[]Current medications as free-text strings (e.g., "Lisinopril 10mg").
allergiesstring[]Known drug or environmental allergies.
medical_historystringRelevant past medical history as free text.
cURL — generate a SOAP note with clinical context
curl -X POST https://api.soapnoteapi.com/v1/note \
  -H "Authorization: Bearer snapi_sk_live_••••••••" \
  -H "Content-Type: application/json" \
  -d '{
    "transcript": "Patient presents with headaches since medication change...",
    "specialty":  "nurse_practitioner",
    "include_billing_codes":   true,
    "include_patient_summary": true,
    "context": {
      "patient_info": {
        "name":            "John Smith",
        "age":             45,
        "gender":          "male",
        "medications":     ["Lisinopril 10mg", "Metformin 500mg"],
        "allergies":       ["Penicillin"],
        "medical_history": "Type 2 diabetes, hypertension"
      },
      "patient_history": "Last visit 2 weeks ago: discussed medication
                          adjustment for blood pressure control...",
      "chat_messages": [
        {
          "role":      "patient",
          "content":   "I have been having headaches since the medication change",
          "timestamp": "2026-03-14T10:00:00Z"
        },
        {
          "role":      "provider",
          "content":   "How often and how severe?",
          "timestamp": "2026-03-14T10:01:00Z"
        }
      ]
    }
  }'

Response

200 OK
Response body (all fields)
{
  "noteId":     "note_01jfg8h4kx9a3bc7d2ef",
  "subjective": "45-year-old male with history of Type 2 diabetes and
                 hypertension presents with new-onset headaches following
                 a recent medication adjustment...",
  "objective":  "Blood pressure 148/92. Heart rate 76. Alert and oriented.
                 No focal neurological deficits noted...",
  "assessment": "Medication-related headache in the setting of recent
                 antihypertensive adjustment. Possible inadequate BP control.",
  "plan":       "1. Hold Lisinopril dose increase — revert to prior dose.
                 2. Recheck BP in 72 hours.
                 3. Patient instructed to log daily headache severity.
                 4. Follow-up in 2 weeks.",
  "transcript": "Patient presents with headaches since medication change...",
  "billing_codes": {
    "icd10": [
      { "code": "G44.309", "description": "Post-traumatic headache, unspecified" },
      { "code": "I10",     "description": "Essential (primary) hypertension" }
    ],
    "cpt": [
      { "code": "99214", "description": "Office visit, established patient, moderate complexity" }
    ]
  },
  "billing_codes_disclaimer": "Recommended codes for review. Not a substitute
    for professional coding. Verify all codes before submission.",
  "patient_summary": "During your visit today, we discussed the headaches
    you have been experiencing since your blood pressure medication was
    adjusted. Based on the examination, we believe the headaches may be
    related to the medication change. We are reverting your Lisinopril
    to the previous dose and would like you to track your headaches daily.
    Please follow up with us in 2 weeks.",
  "expires_at": "2026-06-15T00:00:00Z"
}

Response fields

FieldTypeDescription
noteIdstringUnique note identifier.
subjectivestringSOAP Subjective section.
objectivestringSOAP Objective section.
assessmentstringSOAP Assessment section.
planstringSOAP Plan section.
transcriptstringThe transcript used to generate this note.
billing_codesobjectSuggested ICD-10, CPT, and HCPCS codes (plus advisory ICD-11 when include_icd11 is set). Every code is marked requires_clinician_review. Present when include_billing_codes is true.
billing_codes_disclaimerstringMandatory disclaimer for billing code suggestions.
patient_summarystringPlain-language summary for the patient. Present when include_patient_summary is true.
expires_atISO 8601When the note will be deleted from our servers.

Stream note (SSE)

Generate a SOAP note with real-time streaming using Server-Sent Events.

POST/v1/stream/note

Same request body as POST /v1/note, but the response is an SSE stream. Each event delivers a chunk of the SOAP note as it is generated, allowing you to display sections to providers in real time. The stream ends with a [DONE] event.

Request

Identical to POST /v1/note. All fields — including context, include_billing_codes, include_icd11, and include_patient_summary — are supported. (include_transcript is audio-only and does not apply here.)

cURL — streaming SOAP note generation
curl -X POST https://api.soapnoteapi.com/v1/stream/note \
  -H "Authorization: Bearer snapi_sk_live_••••••••" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "transcript": "Patient presents with headaches since medication change...",
    "specialty": "nurse_practitioner"
  }'

Response format

The response is a stream of SSE events. Each data: line contains a JSON chunk with partial note content. The final event contains [DONE].

SSE response stream
data: {"section":"subjective","content":"42-year-old male with 3-week history of..."}

data: {"section":"objective","content":"Lumbar ROM restricted at 40° flexion..."}

data: {"section":"assessment","content":"Mechanical lower back pain, likely muscular..."}

data: {"section":"plan","content":"1. NSAIDs PRN. 2. Physical therapy referral..."}

data: [DONE]
Tip: Use streaming to display SOAP note sections to providers as they generate, rather than waiting for the full response. This significantly improves perceived speed.

Billing codes

Automatically suggest ICD-10, CPT, and HCPCS codes — plus advisory ICD-11 — from the generated note.

Pass include_billing_codes: true on POST /v1/note (or the audio endpoint) to receive suggested billing codes alongside the SOAP note: ICD-10 diagnosis codes, CPT and HCPCS procedure codes, ranked by relevance to the documented encounter. Every code is returned with requires_clinician_review: true — these are decision support, not a coding determination. Add include_icd11: true to also receive advisory icd11 codes (reference only — not accepted by US payers).

Important: Billing codes are AI-generated suggestions intended to accelerate coder review — they are not a substitute for professional medical coding. Always verify codes before submitting claims. The billing_codes_disclaimer field in the response must be presented to end users.

billing_codes object

FieldTypeDescription
icd10arraySuggested ICD-10 diagnosis codes. Each item includes code, description, and requires_clinician_review.
cptarraySuggested CPT procedure codes (with code, description, and an estimated MDM level/rationale where applicable).
hcpcsarraySuggested HCPCS codes (supplies/services). Present when relevant codes are found.
icd11arrayADVISORY ICD-11 codes — reference only, NOT accepted by US payers. Present only when include_icd11 is true.
billing_codes response shape
"billing_codes": {
  "icd10": [
    { "code": "M54.50", "description": "Low back pain, unspecified",
      "requires_clinician_review": true }
  ],
  "cpt": [
    { "code": "99214", "description": "Office visit, established patient, moderate complexity",
      "mdm_level": "moderate", "requires_clinician_review": true }
  ],
  "hcpcs": [
    { "code": "G0283", "description": "Electrical stimulation, unattended",
      "requires_clinician_review": true }
  ],
  "icd11": [
    { "code": "ME84.2", "description": "Low back pain (ICD-11 — advisory, not for US claims)",
      "requires_clinician_review": true }
  ]
},
"billing_codes_disclaimer": "These codes and the medical decision-making (MDM)
  assessment are AI-generated decision support... A qualified clinician and/or
  professional coder must review and approve all codes before submission.
  ICD-11 codes, when included, are advisory only and are not accepted by US payers."

Patient-facing summary

Generate a plain-language visit summary the patient can read and understand.

Pass include_patient_summary: true on POST /v1/note to receive a plain-language summary written for the patient, alongside the clinical SOAP note. The summary avoids medical jargon and describes what was discussed, what was found, and what the plan is in terms a non-clinician can understand.

This field is opt-in and billed as an additional output. It is not included unlessinclude_patient_summary is explicitly set to true.

patient_summary response field
"patient_summary": "During your visit today, we discussed your ongoing
  lower back pain. The examination showed some tenderness in your lower
  back area. Based on the findings, this appears to be a muscle strain.
  The plan is to continue your current pain medication, try gentle
  stretching exercises, and schedule a follow-up in 4 weeks."

Audio to SOAP

Transcribe an audio recording and generate a SOAP note in one request.

PUT/v1/note/audio

Upload an audio file (MP3, M4A, WAV, OGG, WebM, or FLAC) using multipart/form-data with two parts: an audio file part and a metadata JSON part carrying specialty, template, context, and the same include_* option flags as POST /v1/note. Processing is asynchronous: you receive a noteId, then poll GET /v1/audio/status/:noteId (or GET /v1/note/:noteId) until status is completed. Large files are split and transcribed automatically.

Audio-only option: Set include_transcript: true in the metadata to also receive a speaker-diarized, timestamped transcript_structured (see Structured transcript).include_billing_codes, include_icd11, and include_patient_summary work here exactly as on POST /v1/note.
Supported formats: MP3, M4A, WAV, OGG, WebM, FLAC
cURL — audio upload
curl -X PUT https://api.soapnoteapi.com/v1/note/audio \
  -H "Authorization: Bearer snapi_sk_live_••••••••" \
  -F "audio=@/path/to/recording.mp3" \
  -F 'metadata={"specialty":"nurse_practitioner","template":"standard","include_transcript":true,"include_billing_codes":true,"include_icd11":true,"include_patient_summary":true}'

Response (short recordings, <30 min)

200 OK

Same schema as POST /v1/note — full SOAP note in the response body.

Response (long recordings, ≥30 min)

202 Accepted
Async response body
{
  "noteId":  "note_01jfg8h4kx9a3bc7d2ef",
  "status":  "processing",
  "message": "Audio accepted. Poll GET /v1/audio/status/:noteId for status."
}

Structured transcript

Get a speaker-diarized, timestamped transcript alongside the SOAP note. Audio requests only.

Set include_transcript: true in the metadata of an audio request to receive transcript_structured — a speaker-labeled, timestamped transcript — in addition to the SOAP note. This option is audio-only (there is nothing to diarize on text-only POST /v1/note). Files of any size are supported: long recordings are split, diarized in parallel, and merged onto a single timeline automatically.

Speaker labels are AI-inferred. Every segment is flagged speaker_inferred, and the PROVIDER/PATIENT roles may be incorrect. The response includes a transcript_disclaimer you must present to end users — review against the source audio before relying on it.

transcript_structured segment fields

FieldTypeDescription
speakerstring"PROVIDER", "PATIENT", or a raw label — AI-inferred.
textstringThe spoken text for this segment.
startnumberStart time in seconds from the beginning of the recording.
endnumberEnd time in seconds.
speaker_inferredbooleanAlways true — the speaker label is AI-inferred, not authoritative.
transcript_structured response field
"transcript_structured": [
  { "speaker": "PROVIDER", "text": "What brings you in today?",
    "start": 0.0, "end": 2.1, "speaker_inferred": true },
  { "speaker": "PATIENT", "text": "I've had a headache for three days.",
    "start": 2.4, "end": 5.0, "speaker_inferred": true }
],
"transcript_disclaimer": "This transcript is machine-generated and may contain
  transcription errors. Speaker labels (PROVIDER/PATIENT) are AI-inferred and
  may be incorrect. Review against the source audio before relying on it."

Get note

Retrieve a previously generated note by ID.

GET/v1/note/:noteId

Retrieve a note by its ID. Use this endpoint to poll for completion after an async audio upload, or to retrieve a note within its retention window.

cURL — get note
curl https://api.soapnoteapi.com/v1/note/note_01jfg8h4kx9a3bc7d2ef \
  -H "Authorization: Bearer snapi_sk_live_••••••••"

Response fields

FieldTypeDescription
noteIdstringUnique note identifier.
statusstring"processing" | "completed" | "failed"
subjectivestringSOAP Subjective section. Present when status is "completed".
objectivestringSOAP Objective section.
assessmentstringSOAP Assessment section.
planstringSOAP Plan section.
billing_codesobjectSuggested ICD-10, CPT, and HCPCS codes (plus advisory ICD-11 with include_icd11). Present if include_billing_codes was true.
patient_summarystringPlain-language patient summary. Present if include_patient_summary was true.
transcript_structuredarraySpeaker-diarized, timestamped transcript segments. Present on audio notes when include_transcript was true.
transcript_disclaimerstringMandatory disclaimer for the structured transcript.
expires_atISO 8601When the note will be deleted from our servers.

Visit history summary

Synthesize multiple past visit notes into a concise clinical summary.

POST/v1/visit-summary

Accepts a list of past visit records — each containing a date, provider, and either a structured SOAP note or a free-text summary — and returns a concise longitudinal summary focused on a clinical area of interest. Useful for preparing for follow-up visits, generating referral summaries, or giving a provider rapid context before an encounter.

Request body

FieldTypeRequiredDescription
patient_infoobjectOptionalPatient demographics. Accepts name and age at minimum.
visitsarrayRequiredArray of past visit objects. Min 1. See visit object fields below.
focusstringOptionalClinical focus area for the summary (e.g., "diabetes management", "pain control"). When omitted, all conditions are summarized.

Visit object fields

FieldTypeRequiredDescription
visit_datestringRequiredISO 8601 date of the visit (e.g., "2026-02-15").
providerstringOptionalProvider name or identifier.
soap_noteobjectOptionalStructured SOAP note. Accepts any combination of subjective, objective, assessment, plan keys.
summarystringOptionalFree-text visit summary. Used when a structured SOAP note is not available.

Each visit object must include at least one of soap_note or summary.

cURL — visit history summary
curl -X POST https://api.soapnoteapi.com/v1/visit-summary \
  -H "Authorization: Bearer snapi_sk_live_••••••••" \
  -H "Content-Type: application/json" \
  -d '{
    "patient_info": {
      "name": "Jane Doe",
      "age":  62
    },
    "focus": "diabetes management",
    "visits": [
      {
        "visit_date": "2026-02-15",
        "provider":   "Dr. Smith",
        "soap_note": {
          "assessment": "E11.65 Type 2 DM with hyperglycemia",
          "plan":       "Increased Metformin to 1000mg BID. Recheck A1C in 3 months."
        }
      },
      {
        "visit_date": "2026-01-10",
        "provider":   "Dr. Smith",
        "summary":    "Routine follow-up. A1C 7.8%, up from 7.2%. Blood pressure well controlled."
      }
    ]
  }'

Response

200 OK
Response body
{
  "summary": "62-year-old patient with Type 2 diabetes showing upward A1C
    trend (7.2% -> 7.8%) over the past 2 months. Metformin was increased
    to 1000mg BID at the last visit. Blood pressure well controlled on
    current regimen. Key follow-up: recheck A1C and fasting glucose.",
  "key_findings": [
    "A1C trending upward: 7.2% -> 7.8%",
    "Metformin recently increased to 1000mg BID",
    "Blood pressure stable on current medications"
  ],
  "active_diagnoses": [
    { "code": "E11.65", "description": "Type 2 DM with hyperglycemia" }
  ]
}

Response fields

FieldTypeDescription
summarystringConcise narrative summary of the patient visit history, focused on the requested clinical area.
key_findingsstring[]Bulleted list of the most clinically significant observations across all visits.
active_diagnosesarrayActive diagnoses identified across the visit history. Each item: { code, description }.

Specialties

Pass one of these values as the specialty field in your request.

GET/v1/specialties
nurse_practitionerNurse Practitioner
physicianPhysician
psychiatristPsychiatrist
psychotherapistPsychotherapist
physical_therapyPhysical Therapy
occupational_therapyOccupational Therapy
chiropractorChiropractor
dentistDentist
acupunctureAcupuncture
social_workerSocial Worker
registered_nurseRegistered Nurse
slpSpeech Language Pathology
veterinaryVeterinary
massage_therapyMassage Therapy
pharmacyPharmacy
podiatristPodiatrist
dietitian_nutritionistDietitian / Nutritionist
athletic_trainerAthletic Trainer
aroma_therapyAromatherapy
exercise_therapyExercise Therapy
emsEmergency Medical Services
paramedicParamedic
genetic_counsellingGenetic Counseling
genericGeneric

Error reference

All errors return a consistent JSON body. Check the code field to handle errors programmatically.

Error response shape
{
  "error": {
    "code":    "invalid_api_key",
    "message": "The API key is missing or invalid.",
    "details": {}
  }
}
CodeHTTPHow to fix
VALIDATION_ERROR400Check the required fields: transcript and specialty.
AUTHENTICATION_ERROR401Check your Authorization header. Key format: Bearer snapi_sk_...
AUTHORIZATION_ERROR403Create a new key in the dashboard if yours was revoked.
NOT_FOUND404Notes expire after the retention period. Check the expires_at field.
METHOD_NOT_ALLOWED405Use POST for /v1/note, GET for /v1/note/:id.
CONFLICT409Revoke an existing key before creating a new one (max 5).
INSUFFICIENT_BALANCE429Add funds at your dashboard before retrying.
INTERNAL_ERROR500Retry with exponential backoff. Contact support if the issue persists.
SERVICE_UNAVAILABLE503Wait and retry. Contact support if the issue persists.