> ## Documentation Index
> Fetch the complete documentation index at: https://build.practicehub.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a clinical note

> Creates a finalized (or draft) clinical note on the patient record, filed against one of the account's own practitioner/scribe form templates (`form_id` — list `/form_templates` to find one and see its fields). Allowed to integration keys with the write scope, and to connected assistants whose PracticeHub role allows patient visit notes (own-patients limits apply; a role restricted to saving drafts always creates drafts). Answer keys not defined by the form's schema are refused (`unknown_field`) so imported content can never be silently dropped. For historical imports, `created` back-dates the note so it keeps its place in the record's chronology.



## OpenAPI

````yaml /openapi.json post /clinical_notes
openapi: 3.0.3
info:
  title: PracticeHub API
  version: 1.0.0
  description: >
    The canonical PracticeHub REST API. Every clinic account is a tenant
    addressed by the host the practice signs in on:
    `https://{clinic}.{region}.practicehub.io` (region host `neptune` London,
    `mercury` Frankfurt, `vulcan` Ohio, `jupiter` Singapore, `apollo` Sydney).


    ## Filtering

    List endpoints accept `?attribute=operator:value` with operators `eq`, `ne`,
    `gt`, `gte`, `lt`, `lte`, `null`, `not-null`, `like`, `contains`, `in`,
    `not-in`, `between` (`null`/`not-null` take no value; `in`, `not-in`,
    `between` take comma-separated values; `contains` is a case-insensitive
    substring match with no wildcards to escape). A value with no operator is an
    equality match. Only attributes marked filterable may be filtered (422
    otherwise).


    ## Metadata

    Every record carries an integrator-owned `metadata` object of string, number
    or boolean values (max 50 keys). Send `metadata` on create/update to merge
    keys (`null` removes a key) and filter with `?metadata[key]=operator:value`.


    ## Sorting & pagination

    `?sort=attr[,attr]:asc|desc` on sortable attributes; `?page=` and
    `?page_size=` (max 100). List responses wrap rows in `data` with `links` and
    `meta`.
servers:
  - url: https://{clinic}.{region}.practicehub.io/v3/api
    description: PracticeHub API — the host the practice signs in on
    variables:
      clinic:
        default: your-clinic
        description: The clinic subdomain
      region:
        default: neptune
        enum:
          - neptune
          - mercury
          - vulcan
          - jupiter
          - apollo
        description: >-
          The region host from the practice login URL: neptune (London), mercury
          (Frankfurt), vulcan (Ohio), jupiter (Singapore), apollo (Sydney)
security:
  - bearerAuth: []
tags:
  - name: Utility
    description: Liveness, identity and discovery
  - name: Availability
    description: Free, bookable slots — check before creating an appointment
  - name: Appointments
    description: The appointments resource
  - name: Appointment Types
    description: The appointment_types resource
  - name: Practitioner Availabilities
    description: The practitioner_availabilities resource
  - name: Resources
    description: The resources resource
  - name: Patients
    description: The patients resource
  - name: Tags
    description: The tags resource
  - name: Patient Tags
    description: The patient_tags resource
  - name: Numbers
    description: The numbers resource
  - name: Addresses
    description: The addresses resource
  - name: Patient Logs
    description: The patient_logs resource
  - name: Patient Log Tags
    description: The patient_log_tags resource
  - name: Files
    description: The files resource
  - name: Care Plans
    description: The care_plans resource
  - name: Clinical Notes
    description: Clinical notes on the patient record
  - name: Form Templates
    description: The form_templates resource
  - name: Invoices
    description: The invoices resource
  - name: Line Items
    description: The line_items resource
  - name: Payments
    description: The payments resource
  - name: Refunds
    description: The refunds resource
  - name: Payment Allocations
    description: The payment_allocations resource
  - name: Payment Methods
    description: The payment_methods resource
  - name: Billable Items
    description: The billable_items resource
  - name: Locations
    description: The locations resource
  - name: Practitioners
    description: The practitioners resource
  - name: Modalities
    description: The modalities resource
  - name: Referral Sources
    description: The referral_sources resource
  - name: Deleted Entities
    description: The deleted_entities resource
paths:
  /clinical_notes:
    post:
      tags:
        - Clinical Notes
      summary: Create a clinical note
      description: >-
        Creates a finalized (or draft) clinical note on the patient record,
        filed against one of the account's own practitioner/scribe form
        templates (`form_id` — list `/form_templates` to find one and see its
        fields). Allowed to integration keys with the write scope, and to
        connected assistants whose PracticeHub role allows patient visit notes
        (own-patients limits apply; a role restricted to saving drafts always
        creates drafts). Answer keys not defined by the form's schema are
        refused (`unknown_field`) so imported content can never be silently
        dropped. For historical imports, `created` back-dates the note so it
        keeps its place in the record's chronology.
      operationId: create_clinical_notes
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ClinicalNoteCreate'
      responses:
        '201':
          description: The clinical note
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/ClinicalNote'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '403':
          description: >-
            The credential may not do this: `key_read_only` for a read-only key,
            `permission_denied` for a connected assistant whose PracticeHub role
            does not allow patient visit notes (or a patient outside an
            own-patients role's scope)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: >-
            Invalid input (`validation_failed`), an unresolvable reference
            (`patient_not_found`, `appointment_not_found`,
            `appointment_patient_mismatch`, `form_not_found`), a non-note form
            (`form_type_invalid`), or an answer key the form's schema does not
            define (`unknown_field`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      description: >-
        Any unique string (≤255 chars). A retry with the same key within 24
        hours replays the original response (Idempotent-Replayed: true) instead
        of creating a second record.
      schema:
        type: string
        maxLength: 255
  schemas:
    ClinicalNoteCreate:
      type: object
      required:
        - patient_id
        - form_id
        - data
      properties:
        patient_id:
          type: integer
          description: The patient the note belongs to
        form_id:
          type: integer
          description: >-
            An active practitioner/scribe form template of the account to file
            the note against — list /form_templates to find one
        appointment_id:
          type: integer
          nullable: true
          description: The documented appointment; must belong to the patient
        data:
          type: object
          description: >-
            Answers keyed by the form schema's field names (the template's
            schema lists them). Keys the schema does not define are refused
            (unknown_field)
        state:
          type: string
          enum:
            - draft
            - final
          default: final
          description: final stamps finalized_at / finalized_by
        note_type:
          type: string
          enum:
            - practitioner
            - scribe
          description: Defaults to the form's own type
        appt_date:
          type: string
          format: date
          nullable: true
          description: Date of the documented visit
        created_at:
          type: string
          format: date-time
          nullable: true
          description: >-
            Historical-import override, UTC: back-dates the note's
            created_at/updated_at (and, for a final note, finalized_at) so
            imports keep their chronology
        metadata:
          $ref: '#/components/schemas/Metadata'
    ClinicalNote:
      type: object
      description: >-
        A clinical note in the unified note shape the app itself reads: the raw
        answers (`data`, keyed by the form schema's field names), the
        human-readable rendering (`formatted_fields`, resolved against the
        schema snapshot taken when the note was written), and the note's
        clinical context.
      properties:
        id:
          type: integer
        source:
          type: string
          enum:
            - form_response
        patient_id:
          type: integer
        form_id:
          type: integer
          nullable: true
        form_type:
          type: string
          enum:
            - practitioner
            - scribe
        form_name:
          type: string
        data:
          type: object
          description: Raw answers keyed by the form schema's field names
        state:
          type: string
          enum:
            - draft
            - final
        pinned:
          type: boolean
        created_at:
          type: string
          format: date-time
          nullable: true
          description: UTC, YYYY-MM-DDTHH:MM:SSZ
          example: '2026-09-01T14:31:00Z'
        updated_at:
          type: string
          format: date-time
          nullable: true
          description: UTC, YYYY-MM-DDTHH:MM:SSZ
          example: '2026-09-01T14:31:00Z'
        appt_date:
          type: string
          format: date
          nullable: true
          description: Date of the documented visit
        practitioner:
          type: object
          nullable: true
          description: >-
            The display practitioner: the appointment's practitioner when
            linked, otherwise the note's author
        note_author:
          type: object
          nullable: true
          description: Who wrote the note (uid, name, type)
        appointment:
          type: object
          nullable: true
          description: >-
            The linked appointment (appointmentID, start, end, type), if any.
            `start`/`end` are clinic wall time with no zone marker
            (`YYYY-MM-DDTHH:MM:SS`), unlike `created_at`/`updated_at`, which are
            UTC
        canvases:
          type: object
          description: Per-field signature/drawing snapshots, keyed by field name
        formatted_fields:
          type: array
          items:
            type: object
          description: >-
            Human-readable field renderings ({key, label, type, value,
            section?}) resolved against the schema snapshot
        formatted_soap:
          type: object
          nullable: true
          description: >-
            Subjective/Objective/Assessment/Plan values when the note is
            SOAP-structured
        spinal_codes:
          type: array
          items:
            type: object
          description: Spinal listings, when the form carries them
        scribe_attachment:
          type: object
          nullable: true
          description: AI Scribe transcription and summary, on scribe notes
        files:
          type: array
          items:
            type: object
          description: >-
            Attached files ({id, name, mime_type, size, url}); url is a
            short-lived signed link
        patient_details:
          type: array
          items:
            type: object
          description: Patient-details snapshot fields, on notes that captured one
        form_schema:
          type: object
          nullable: true
          description: The form schema snapshot the note was written against
        revision_number:
          type: integer
        is_current:
          type: boolean
          description: Always true here — only current revisions are served
        previous_revision_id:
          type: integer
          nullable: true
        revised_by_uid:
          type: integer
          nullable: true
        finalized_at:
          type: string
          format: date-time
          nullable: true
        finalized_by_uid:
          type: integer
          nullable: true
        metadata:
          $ref: '#/components/schemas/Metadata'
    Error:
      type: object
      required:
        - message
        - code
      properties:
        message:
          type: string
          description: Human-readable; may change — do not parse
        code:
          type: string
          description: >-
            Stable machine-readable code (snake_case), e.g. validation_failed,
            not_found, key_read_only, not_online_bookable, group_full,
            appointment_rule, billing_rule, idempotency_key_reused, rate_limited
        errors:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
          description: Present on validation failures, keyed by attribute
    Metadata:
      type: object
      description: >-
        Integrator-owned key/value metadata (max 50 keys). Values are strings
        (≤500 chars), numbers or booleans and read back with the type they were
        written with. On write, a null value removes the key. Filter with
        metadata[key]=op:value; number operands compare numerically.
      additionalProperties:
        nullable: true
        oneOf:
          - type: string
            maxLength: 500
          - type: number
          - type: boolean
  responses:
    Unauthenticated:
      description: Missing or invalid credentials
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'API key from Developers → API Keys, sent as Authorization: Bearer <key>.'

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.