openapi: 3.1.0 info: title: Heidi Health API version: v2 summary: Public Heidi REST API for ambient AI medical scribe, transcription, consult notes, documents, clinical coding, and Ask Heidi. description: | The Heidi API lets partner platforms (EHRs, telehealth apps, custom clinician tools) drive Heidi's ambient documentation engine end-to-end: authentication via tenant API key + per-user JWT, patient profile management, session lifecycle (create, update, list, retrieve), contextual attachments and linked sessions, audio upload (single file or chunked live), transcript retrieval (final or live-chunked), template discovery, streamed consult-note and document generation against Heidi or custom templates, multi-standard clinical coding (ICD-10/SNOMED/CPT and others), and streamed Ask Heidi assistant responses. Documentation: https://www.heidihealth.com/developers/heidi-api/overview contact: name: Heidi Health Support url: https://support.heidihealth.com license: name: Heidi Health Terms of Service url: https://www.heidihealth.com/legal/terms-of-service servers: - url: https://registrar.api.heidihealth.com/api/v2/ml-scribe/open-api description: Production tags: - name: Authentication description: Token exchange. - name: Templates description: Consult-note templates. - name: Patient Profiles description: Longitudinal patient records. - name: Sessions description: Clinical session lifecycle. - name: Session Context description: Notes, linked sessions, and context document attachments. - name: Transcription description: Audio upload and transcript retrieval. - name: Consult Notes description: Streamed consult-note generation. - name: Documents description: Auxiliary template-driven documents. - name: Clinical Coding description: ICD/SNOMED/CPT and related code generation. - name: Ask Heidi description: Streamed AI-assistant responses scoped to a session. security: - bearerAuth: [] paths: /jwt: get: tags: [Authentication] summary: Exchange API Key For JWT description: Exchange a tenant Heidi API key for a short-lived bearer JWT bound to an EHR user. operationId: getJwt security: - heidiApiKey: [] parameters: - in: query name: email required: true schema: { type: string, format: email } - in: query name: third_party_internal_id required: true schema: { type: string } responses: '200': description: Token issued. content: application/json: schema: { $ref: '#/components/schemas/Jwt' } /templates/document-templates: get: tags: [Templates] summary: List Consult Note Templates operationId: listTemplates responses: '200': description: Templates returned. content: application/json: schema: type: object properties: data: type: array items: { $ref: '#/components/schemas/Template' } /patient-profiles: post: tags: [Patient Profiles] summary: Create Patient Profile operationId: createPatientProfile requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/PatientProfileCreate' } responses: '200': description: Patient profile created. content: application/json: schema: { $ref: '#/components/schemas/PatientProfile' } get: tags: [Patient Profiles] summary: List Patient Profiles operationId: listPatientProfiles parameters: - in: query name: ehr_patient_id schema: { type: string } - in: query name: provider schema: { type: string } responses: '200': description: Patient profiles returned. content: application/json: schema: type: object properties: data: type: array items: { $ref: '#/components/schemas/PatientProfile' } /patient-profiles/{patient_profile_id}: get: tags: [Patient Profiles] summary: Get Patient Profile operationId: getPatientProfile parameters: - $ref: '#/components/parameters/PatientProfileId' responses: '200': description: Patient profile. content: application/json: schema: { $ref: '#/components/schemas/PatientProfile' } patch: tags: [Patient Profiles] summary: Update Patient Profile operationId: updatePatientProfile parameters: - $ref: '#/components/parameters/PatientProfileId' requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/PatientProfileUpdate' } responses: '200': description: Patient profile updated. content: application/json: schema: { $ref: '#/components/schemas/PatientProfile' } /patient-profiles:batch-delete: post: tags: [Patient Profiles] summary: Batch Delete Patient Profiles operationId: batchDeletePatientProfiles requestBody: required: true content: application/json: schema: type: object properties: patient_profile_ids: type: array items: { type: string } responses: '200': description: Profiles deleted. /patient-profiles/{patient_profile_id}/sessions: post: tags: [Patient Profiles] summary: Link Session To Patient Profile operationId: linkSessionToPatientProfile parameters: - $ref: '#/components/parameters/PatientProfileId' requestBody: required: true content: application/json: schema: type: object properties: session_id: { type: string } responses: '200': description: Session linked. /sessions: post: tags: [Sessions] summary: Create Session operationId: createSession requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/SessionCreate' } responses: '200': description: Session created. content: application/json: schema: type: object properties: session_id: { type: string } /sessions/{session_id}: get: tags: [Sessions] summary: Get Session operationId: getSession parameters: - $ref: '#/components/parameters/SessionId' responses: '200': description: Session details. content: application/json: schema: { $ref: '#/components/schemas/Session' } patch: tags: [Sessions] summary: Update Session operationId: updateSession parameters: - $ref: '#/components/parameters/SessionId' requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/SessionUpdate' } responses: '200': description: Session updated. content: application/json: schema: { $ref: '#/components/schemas/Session' } /sessions/linked-user: get: tags: [Sessions] summary: List Linked User Sessions operationId: listLinkedUserSessions parameters: - in: query name: page_size schema: { type: integer, minimum: 1, maximum: 200 } responses: '200': description: Paginated list of sessions. content: application/json: schema: type: object properties: count: { type: integer } total_count: { type: integer } has_next: { type: boolean } has_previous: { type: boolean } data: type: array items: { $ref: '#/components/schemas/Session' } /sessions/{session_id}/context-documents: post: tags: [Session Context] summary: Upload Context Document operationId: uploadContextDocument parameters: - $ref: '#/components/parameters/SessionId' requestBody: required: true content: multipart/form-data: schema: type: object properties: file: type: string format: binary unstructured: { type: boolean } responses: '200': description: Document uploaded. content: application/json: schema: { $ref: '#/components/schemas/ContextDocument' } get: tags: [Session Context] summary: List Context Documents operationId: listContextDocuments parameters: - $ref: '#/components/parameters/SessionId' responses: '200': description: Context documents. content: application/json: schema: type: object properties: data: type: array items: { $ref: '#/components/schemas/ContextDocument' } delete: tags: [Session Context] summary: Delete Context Documents operationId: deleteContextDocuments parameters: - $ref: '#/components/parameters/SessionId' - in: query name: ids required: true schema: type: array items: { type: string } responses: '204': { description: Deleted. } /sessions/{session_id}/upload-audio: post: tags: [Transcription] summary: Upload Session Audio description: Upload a full audio file (MP3 or OGG recommended) for lazy transcription. operationId: uploadSessionAudio parameters: - $ref: '#/components/parameters/SessionId' requestBody: required: true content: multipart/form-data: schema: type: object properties: file: type: string format: binary responses: '200': { description: Audio stored. } /sessions/{session_id}/transcript: get: tags: [Transcription] summary: Get Session Transcript operationId: getSessionTranscript parameters: - $ref: '#/components/parameters/SessionId' responses: '200': description: Final transcript. content: application/json: schema: { $ref: '#/components/schemas/Transcript' } /sessions/{session_id}/transcript/live: get: tags: [Transcription] summary: Get Live Session Transcript description: Chunked live transcript with per-chunk status and source. operationId: getLiveSessionTranscript parameters: - $ref: '#/components/parameters/SessionId' responses: '200': description: Chunked live transcript. content: application/json: schema: { $ref: '#/components/schemas/LiveTranscript' } /sessions/{session_id}/consult-note: post: tags: [Consult Notes] summary: Generate Consult Note description: Stream a consult note generated from the session's transcript and context. operationId: generateConsultNote parameters: - $ref: '#/components/parameters/SessionId' requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/ConsultNoteGenerate' } responses: '200': description: Streamed consult-note chunks. content: application/x-ndjson: schema: { $ref: '#/components/schemas/StreamChunk' } /sessions/{session_id}/client-customised-template/response: post: tags: [Consult Notes] summary: Generate Custom Template Consult Note description: Generate a consult note against a client-supplied JSON template. operationId: generateCustomTemplateConsultNote parameters: - $ref: '#/components/parameters/SessionId' requestBody: required: true content: application/json: schema: type: object properties: template: { type: object } content_type: type: string enum: [MARKDOWN, HTML] responses: '200': description: Generated structured response. content: application/json: schema: { type: object } /sessions/{session_id}/documents: post: tags: [Documents] summary: Generate Document operationId: generateDocument parameters: - $ref: '#/components/parameters/SessionId' requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/DocumentGenerate' } responses: '200': description: Document generated. content: application/json: schema: { $ref: '#/components/schemas/Document' } get: tags: [Documents] summary: List Session Documents operationId: listSessionDocuments parameters: - $ref: '#/components/parameters/SessionId' responses: '200': description: Documents linked to session. content: application/json: schema: type: object properties: data: type: array items: { $ref: '#/components/schemas/Document' } /sessions/{session_id}/clinical-codes: get: tags: [Clinical Coding] summary: Get Clinical Codes description: Generate clinical codes for the session across the requested coding system. operationId: getSessionClinicalCodes parameters: - $ref: '#/components/parameters/SessionId' - in: query name: coding_system required: true schema: type: string enum: - ICD-10 - ICD-10-CM - ICD-9 - ICD-9-CM - SNOMED - SNOMED-CT - OPCS-410 - ACHI-13 - CPT-2025 responses: '200': description: Clinical codes for session. content: application/json: schema: { $ref: '#/components/schemas/ClinicalCodesResponse' } /sessions/{session_id}/ask-ai: post: tags: [Ask Heidi] summary: Ask Heidi description: Stream an AI-assistant response scoped to the session. operationId: askHeidi parameters: - $ref: '#/components/parameters/SessionId' requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/AskHeidiRequest' } responses: '200': description: Streamed AI response chunks. content: application/x-ndjson: schema: { $ref: '#/components/schemas/StreamChunk' } components: securitySchemes: heidiApiKey: type: apiKey in: header name: Heidi-Api-Key bearerAuth: type: http scheme: bearer bearerFormat: JWT parameters: SessionId: in: path name: session_id required: true schema: { type: string } PatientProfileId: in: path name: patient_profile_id required: true schema: { type: string } schemas: Jwt: type: object required: [token, expiration_time] properties: token: { type: string } expiration_time: { type: string, format: date-time } Template: type: object properties: id: { type: string } name: { type: string } structure_template: { type: object } template_category: type: string enum: [CONSULT_NOTE_TEMPLATE, DOCUMENT_TEMPLATE] template_html: { type: string } author_name: { type: string } PatientProfileCreate: type: object properties: first_name: { type: string } last_name: { type: string } date_of_birth: { type: string, format: date } gender: { type: string } ehr_patient_id: { type: string } provider: { type: string } PatientProfileUpdate: allOf: - $ref: '#/components/schemas/PatientProfileCreate' PatientProfile: allOf: - $ref: '#/components/schemas/PatientProfileCreate' - type: object properties: id: { type: string } created_at: { type: string, format: date-time } updated_at: { type: string, format: date-time } SessionCreate: type: object properties: patient_profile_id: { type: string } ehr_appointment_id: { type: string } SessionUpdate: type: object properties: duration: { type: integer, description: Session duration in seconds. } language_code: { type: string } output_language_code: { type: string } patient: { type: object } clinician_notes: type: array items: { type: string } ehr_appointment_id: { type: string } ehr_patient_id: { type: string } consent_obtained: { type: boolean } linked_sessions_for_context: type: array items: { type: string } Session: type: object properties: session_id: { type: string } patient: { type: object } duration: { type: integer } language_code: { type: string } output_language_code: { type: string } clinician_notes: type: array items: { type: string } consent_obtained: { type: boolean } linked_sessions_for_context: type: array items: { type: string } consult_note: { type: object } documents: type: array items: { $ref: '#/components/schemas/Document' } audio: { type: object } created_at: { type: string, format: date-time } updated_at: { type: string, format: date-time } ContextDocument: type: object properties: id: { type: string } filename: { type: string } uploaded_at: { type: string, format: date-time } status: type: string enum: [PARSING, READY] unstructured: { type: boolean } Transcript: type: object properties: session_id: { type: string } transcript: { type: string } language_code: { type: string } LiveTranscript: type: object properties: session_id: { type: string } transcript: { type: string } active_source: type: string enum: [USER_UPLOADED, LIVE, BACKUP] chunks: type: array items: type: object properties: id: { type: string } status: type: string enum: [PENDING, READY, FAILED] duration: { type: number } text: { type: string } source: type: string enum: [USER_UPLOADED, LIVE, BACKUP] ConsultNoteGenerate: type: object required: [generation_method, addition, voice_style, brain] properties: generation_method: type: string enum: [TEMPLATE] template_id: { type: string } addition: { type: string } voice_style: type: string enum: [GOLDILOCKS, DETAILED, BRIEF, SUPER_DETAILED, MY_VOICE] brain: type: string enum: [LEFT, RIGHT] default: LEFT content_type: type: string enum: [MARKDOWN, HTML] DocumentGenerate: type: object required: [generation_method, template_id, voice_style, brain] properties: generation_method: type: string enum: [TEMPLATE] template_id: { type: string } voice_style: type: string enum: [GOLDILOCKS, DETAILED, BRIEF, SUPER_DETAILED, MY_VOICE] brain: type: string enum: [LEFT, RIGHT] content_type: type: string enum: [MARKDOWN, HTML] Document: type: object properties: id: { type: string } index: { type: integer } name: { type: string } template_id: { type: string } generation_type: { type: string } content: { type: string } content_type: type: string enum: [MARKDOWN, HTML] ClinicalCodesResponse: type: object properties: coding_system: { type: string } status: type: string enum: [PROCESSING, READY, FAILED] entities: type: array items: { $ref: '#/components/schemas/ClinicalCodeEntity' } ClinicalCodeEntity: type: object properties: entity: { type: string } primary_code: { $ref: '#/components/schemas/ClinicalCode' } similar_codes: type: array items: { $ref: '#/components/schemas/ClinicalCode' } references: type: array items: type: object properties: source: type: string enum: [TRANSCRIPT, CONSULT_NOTE] text: { type: string } start: { type: integer } end: { type: integer } ClinicalCode: type: object properties: code: { type: string } description: { type: string } coding_system: { type: string } effective_date: { type: string, format: date } valid: { type: boolean } hierarchy: type: array items: { type: string } AskHeidiRequest: type: object required: [ai_command_text, content, content_type] properties: ai_command_text: { type: string } content: { type: string } content_type: type: string enum: [MARKDOWN, HTML] StreamChunk: type: object properties: data: { type: string }