Skip to main content

Escape Dental API (1.0.0)

Download OpenAPI specification:Download

Practice management platform API for Escape Dental.

Scheduling

Appointments, day sheet, templates, overrides, recalls

practice_scheduling_appointment_list

List and create appointments. Staff-only.

List supports filtering by date range (from / to), status, patient, and provider. Results are ordered by date_time ascending with a pk tiebreaker (see :class:AppointmentPagination).

Status vocabulary -- the Django state machine uses its own status slugs, distinct from any PMS-side arrival_status value carried by sync tools. The three statuses that matter for the No-show report are:

  • broken -- patient did not arrive (no-show). The Status.BROKEN choice is labelled Broken/No-Show in the model. This is the value the No-show report filters on.
  • cancelled -- patient cancelled ahead of time (slot could be refilled; does not count as a no-show).
  • complete -- patient arrived and the visit finished normally.

For convenience, ?status=no_show is accepted as an alias for ?status=broken so the web app can keep semantic URLs.

No-show shortcut -- ?no_show_between=YYYY-MM-DD,YYYY-MM-DD expands to status=no_show plus from/to using the supplied dates. Explicit from / to / status query params still win if passed alongside, so the shortcut is purely additive.

No-show annotations -- when the resolved status is broken / no_show, each row is additionally annotated with:

  • patient_no_show_count -- lifetime count of broken appointments for the patient scoped to this practice (ignores other practices).
  • patient_phone -- patient's best reach-out number (phone_mobile preferred, then phone_home, then phone_work).
  • patient_outstanding_balance -- the patient's current aged receivables snapshot (Patient.balance_current).
  • cancel_reason -- the appointment's cancellation_reason if set.

These fields are null on rows that are not no-shows, keeping the payload lean for normal schedule queries.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
from
string <date>
Examples:
  • from=2025-06-01 - Month start

Inclusive lower bound on date_time (ISO 8601 date, YYYY-MM-DD). Interpreted in the practice's local timezone -- a from=2025-06-01 filter returns appointments whose local-time start is on or after midnight on June 1 in the practice's zone.

no_show_between
string
Examples:
  • no_show_between=2025-06-01,2025-06-30 - June 2025

Shortcut for the No-show report: two ISO dates separated by a comma (YYYY-MM-DD,YYYY-MM-DD) expands to status=no_show + from=<first> + to=<second>. Explicit from / to / status query params still win if supplied alongside. Example: no_show_between=2025-06-01,2025-06-30.

page
integer

1-indexed page number. Pagination is keyed by date_time with a pk tiebreaker for stability.

page_size
integer

Results per page. Default 50, max 100 for regular clients. First-party sync tools (escape-eaglesoft, escape-opendental) bypass the cap via StandardPageNumberPagination so they can fetch large historical windows.

patient
integer

Filter by patient integer PK. Combine with from/to for a patient visit history slice.

provider
integer

Filter by primary provider integer PK.

status
string
Enum: "arrived" "broken" "cancelled" "complete" "no_show" "note" "other" "planned" "ready_for_doctor" "ready_for_walkout" "scheduled" "seated" "unscheduled"

Filter by appointment status slug. Status vocabulary used by the Django state machine (distinct from any PMS-specific arrival_status values on the sync side):

  • broken -- patient did not arrive for the appointment (a.k.a. no-show). The model's Status.BROKEN choice is labelled Broken/No-Show; this is the value the No-show report filters on.
  • cancelled -- patient cancelled the appointment ahead of time.
  • scheduled / arrived / seated / ready_for_doctor / ready_for_walkout / complete -- normal patient-flow states.

status=no_show is accepted as an alias for status=broken so the web-facing report URLs can stay semantic.

to
string <date>
Examples:
  • to=2025-06-30 - Month end

Inclusive upper bound on date_time (ISO 8601 date, YYYY-MM-DD). Interpreted in the practice's local timezone -- the full to day is included (the filter resolves to midnight at the start of the following day).

Responses

Response samples

Content type
application/json

A typical staff-app response when fetching a week of appointments. Results are ordered by date_time; the response envelope is the project-wide paginator shape (count, next, previous, results).

{
  • "count": 123,
  • "results": [
    ]
}

practice_scheduling_appointment_create

List and create appointments. Staff-only.

List supports filtering by date range (from / to), status, patient, and provider. Results are ordered by date_time ascending with a pk tiebreaker (see :class:AppointmentPagination).

Status vocabulary -- the Django state machine uses its own status slugs, distinct from any PMS-side arrival_status value carried by sync tools. The three statuses that matter for the No-show report are:

  • broken -- patient did not arrive (no-show). The Status.BROKEN choice is labelled Broken/No-Show in the model. This is the value the No-show report filters on.
  • cancelled -- patient cancelled ahead of time (slot could be refilled; does not count as a no-show).
  • complete -- patient arrived and the visit finished normally.

For convenience, ?status=no_show is accepted as an alias for ?status=broken so the web app can keep semantic URLs.

No-show shortcut -- ?no_show_between=YYYY-MM-DD,YYYY-MM-DD expands to status=no_show plus from/to using the supplied dates. Explicit from / to / status query params still win if passed alongside, so the shortcut is purely additive.

No-show annotations -- when the resolved status is broken / no_show, each row is additionally annotated with:

  • patient_no_show_count -- lifetime count of broken appointments for the patient scoped to this practice (ignores other practices).
  • patient_phone -- patient's best reach-out number (phone_mobile preferred, then phone_home, then phone_work).
  • patient_outstanding_balance -- the patient's current aged receivables snapshot (Patient.balance_current).
  • cancel_reason -- the appointment's cancellation_reason if set.

These fields are null on rows that are not no-shows, keeping the payload lean for normal schedule queries.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
patient
string or null <uuid>
provider
string or null <uuid>
provider_hygienist
string or null <uuid>
operatory
string or null <uuid>
treatment_plan
string or null <uuid>

Treatment plan this appointment was scheduled from

date_time
string or null <date-time>
duration_minutes
integer [ 0 .. 2147483647 ]
status
string (AppointmentStatusEnum)
Enum: "scheduled" "arrived" "seated" "ready_for_doctor" "ready_for_walkout" "complete" "broken" "cancelled" "unscheduled" "planned" "other" "note"
  • scheduled - Scheduled
  • arrived - Arrived
  • seated - Seated
  • ready_for_doctor - Ready for Doctor
  • ready_for_walkout - Ready for Walkout
  • complete - Complete
  • broken - Broken/No-Show
  • cancelled - Cancelled
  • unscheduled - Unscheduled
  • planned - Planned
  • other - Other
  • note - Note
ConfirmedStatusEnum (string) or BlankEnum (any)
appointment_type
string <= 100 characters

e.g. New Patient Exam, Crown Prep

is_hygiene
boolean
is_new_patient
boolean
procedure_description
string
note
string
cancellation_reason
string

Patient-supplied reason for cancellation

reschedule_requested
boolean

Patient asked the front desk to reschedule

arrived_at
string or null <date-time>
seated_at
string or null <date-time>
ready_for_doctor_at
string or null <date-time>

When hygienist signaled ready for doctor exam

ready_for_walkout_at
string or null <date-time>

When patient is ready for walkout (checkout/scheduling)

dismissed_at
string or null <date-time>
dollars_scheduled
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Scheduled procedure total from the source PMS; nullable when unknown

Array of objects (AppointmentProcedureRequest)
custom_data
any
allow_overbooking
boolean
Default: false
skip_validation
boolean
Default: false

Responses

Request samples

Content type

Minimal payload to create a scheduled appointment. date_time MUST be an ISO 8601 string with a timezone offset — the API rejects naive datetimes. duration_minutes is required for conflict-checking. Set allow_overbooking=true to skip the double-book guard (used by import/sync tools).

{
  • "patient": "11111111-1111-4111-8111-111111111111",
  • "provider": "22222222-2222-4222-8222-222222222222",
  • "operatory": "44444444-4444-4444-8444-444444444444",
  • "date_time": "2026-05-14T09:00:00-07:00",
  • "duration_minutes": 60,
  • "appointment_type": "Crown Prep",
  • "is_hygiene": false,
  • "procedure_description": "D2740 Crown - porcelain/ceramic substrate",
  • "note": "Patient prefers morning appointments.",
  • "scheduled_procedures": [
    ]
}

Response samples

Content type
application/json

Response returned after successfully creating the appointment above.

{
  • "id": "55555555-5555-4555-8555-555555555555",
  • "patient": "11111111-1111-4111-8111-111111111111",
  • "provider": "22222222-2222-4222-8222-222222222222",
  • "provider_hygienist": "33333333-3333-4333-8333-333333333333",
  • "operatory": "44444444-4444-4444-8444-444444444444",
  • "treatment_plan": null,
  • "date_time": "2026-05-14T09:00:00-07:00",
  • "duration_minutes": 60,
  • "status": "scheduled",
  • "confirmed_status": "not_called",
  • "appointment_type": "Crown Prep",
  • "is_hygiene": false,
  • "is_new_patient": false,
  • "procedure_description": "D2740 Crown - porcelain/ceramic substrate",
  • "note": "Patient prefers morning appointments.",
  • "cancellation_reason": "",
  • "reschedule_requested": false,
  • "arrived_at": null,
  • "seated_at": null,
  • "ready_for_doctor_at": null,
  • "ready_for_walkout_at": null,
  • "dismissed_at": null,
  • "patient_name": "Example, Jane",
  • "provider_name": "Synthetic, Dr. Dana",
  • "provider_hygienist_name": "Synthetic, Hollis",
  • "scheduled_procedures": [
    ],
  • "custom_data": { }
}

practice_scheduling_appointment_bulk_partial_update

Handle PATCH on the list endpoint for bulk updates.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
patient
string or null <uuid>
provider
string or null <uuid>
provider_hygienist
string or null <uuid>
operatory
string or null <uuid>
treatment_plan
string or null <uuid>

Treatment plan this appointment was scheduled from

date_time
string or null <date-time>
duration_minutes
integer [ 0 .. 2147483647 ]
ConfirmedStatusEnum (string) or BlankEnum (any)
appointment_type
string <= 100 characters

e.g. New Patient Exam, Crown Prep

is_hygiene
boolean
is_new_patient
boolean
procedure_description
string
note
string
cancellation_reason
string

Patient-supplied reason for cancellation

reschedule_requested
boolean

Patient asked the front desk to reschedule

arrived_at
string or null <date-time>
seated_at
string or null <date-time>
ready_for_doctor_at
string or null <date-time>

When hygienist signaled ready for doctor exam

ready_for_walkout_at
string or null <date-time>

When patient is ready for walkout (checkout/scheduling)

dismissed_at
string or null <date-time>
dollars_scheduled
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Scheduled procedure total from the source PMS; nullable when unknown

custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_hygienist": "cc1b609c-8966-4136-9bf1-9a022231718a",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "treatment_plan": "c4c01122-8b32-4bce-bbce-bb1bda9a1a32",
  • "date_time": "2019-08-24T14:15:22Z",
  • "duration_minutes": 2147483647,
  • "confirmed_status": "not_called",
  • "appointment_type": "string",
  • "is_hygiene": true,
  • "is_new_patient": true,
  • "procedure_description": "string",
  • "note": "string",
  • "cancellation_reason": "string",
  • "reschedule_requested": true,
  • "arrived_at": "2019-08-24T14:15:22Z",
  • "seated_at": "2019-08-24T14:15:22Z",
  • "ready_for_doctor_at": "2019-08-24T14:15:22Z",
  • "ready_for_walkout_at": "2019-08-24T14:15:22Z",
  • "dismissed_at": "2019-08-24T14:15:22Z",
  • "dollars_scheduled": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_hygienist": "cc1b609c-8966-4136-9bf1-9a022231718a",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "treatment_plan": "c4c01122-8b32-4bce-bbce-bb1bda9a1a32",
  • "date_time": "2019-08-24T14:15:22Z",
  • "duration_minutes": 2147483647,
  • "status": "scheduled",
  • "confirmed_status": "not_called",
  • "appointment_type": "string",
  • "is_hygiene": true,
  • "is_new_patient": true,
  • "procedure_description": "string",
  • "note": "string",
  • "cancellation_reason": "string",
  • "reschedule_requested": true,
  • "arrived_at": "2019-08-24T14:15:22Z",
  • "seated_at": "2019-08-24T14:15:22Z",
  • "ready_for_doctor_at": "2019-08-24T14:15:22Z",
  • "ready_for_walkout_at": "2019-08-24T14:15:22Z",
  • "dismissed_at": "2019-08-24T14:15:22Z",
  • "dollars_scheduled": "string",
  • "patient_name": "string",
  • "provider_name": "string",
  • "provider_hygienist_name": "string",
  • "cancelled_by": "string",
  • "cancelled_by_name": "string",
  • "scheduled_procedures": [
    ],
  • "custom_data": null
}

practice_scheduling_appointment_status_list

Read-only list of appointment status metadata.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

practice_scheduling_appointment_status_retrieve

Read-only list of appointment status metadata.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
slug
required
string

A unique value identifying this appointment status.

Responses

Response samples

Content type
application/json
{
  • "slug": "string",
  • "label": "string",
  • "color": "string",
  • "is_visible": true,
  • "blocks_slot": true,
  • "sort_order": 0
}

practice_scheduling_appointment_confirm_create

Update appointment confirmation status (orthogonal to lifecycle status).

POST {"confirmed_status": "Confirmed"}

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
appointment_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
confirmed_status
required
string (ConfirmedStatusEnum)
Enum: "not_called" "left_message" "confirmed" "econfirmed"
  • not_called - Not Called
  • left_message - Left Message
  • confirmed - Confirmed
  • econfirmed - eConfirmed

Responses

Request samples

Content type

Confirmation is orthogonal to lifecycle status — an appointment can be scheduled and confirmed at the same time. Valid values: not_called, left_message, confirmed, econfirmed.

{
  • "confirmed_status": "confirmed"
}

Response samples

Content type
application/json

Response mirrors the appointment-detail shape.

{
  • "id": "55555555-5555-4555-8555-555555555555",
  • "patient": "11111111-1111-4111-8111-111111111111",
  • "provider": "22222222-2222-4222-8222-222222222222",
  • "provider_hygienist": "33333333-3333-4333-8333-333333333333",
  • "operatory": "44444444-4444-4444-8444-444444444444",
  • "treatment_plan": null,
  • "date_time": "2026-05-14T09:00:00-07:00",
  • "duration_minutes": 60,
  • "status": "scheduled",
  • "confirmed_status": "confirmed",
  • "appointment_type": "Crown Prep",
  • "is_hygiene": false,
  • "is_new_patient": false,
  • "procedure_description": "D2740 Crown - porcelain/ceramic substrate",
  • "note": "Patient prefers morning appointments.",
  • "cancellation_reason": "",
  • "reschedule_requested": false,
  • "arrived_at": null,
  • "seated_at": null,
  • "ready_for_doctor_at": null,
  • "ready_for_walkout_at": null,
  • "dismissed_at": null,
  • "patient_name": "Example, Jane",
  • "provider_name": "Synthetic, Dr. Dana",
  • "provider_hygienist_name": "Synthetic, Hollis",
  • "scheduled_procedures": [
    ],
  • "custom_data": { }
}

practice_scheduling_appointment_history_list

Return the status transition history for an appointment.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
appointment_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json

One entry per transition, oldest first. changed_by is null for automated transitions (e.g. system auto-marking broken appointments overnight).

[
  • [
    ]
]

practice_scheduling_appointment_route_slip_retrieve

Aggregate endpoint for the front-desk route-slip print template (api#239).

GET /v1/practice/<uid>/scheduling/appointment/<appt_uid>/route-slip/

Returns every field the print template renders -- appointment, patient, procedures, primary insurance, provider, and operatory -- in a single JSON response. Designed for under ~50ms per call so check-in at the front desk stays snappy; the N+1 alternative (fetch the appointment, then patient, then insurance, then procedures) was measured as a noticeable stall while the patient stood at the counter.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
appointment_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "appointment": {
    },
  • "patient": {
    },
  • "procedures": [
    ],
  • "insurance": {
    },
  • "provider": {
    },
  • "operatory": {
    }
}

practice_scheduling_appointment_transition_create

Transition an appointment to a new status with validation and audit logging.

POST {"status": "complete", "note": "optional reason"}

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
appointment_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
status
required
string (AppointmentStatusEnum)
Enum: "scheduled" "arrived" "seated" "ready_for_doctor" "ready_for_walkout" "complete" "broken" "cancelled" "unscheduled" "planned" "other" "note"
  • scheduled - Scheduled
  • arrived - Arrived
  • seated - Seated
  • ready_for_doctor - Ready for Doctor
  • ready_for_walkout - Ready for Walkout
  • complete - Complete
  • broken - Broken/No-Show
  • cancelled - Cancelled
  • unscheduled - Unscheduled
  • planned - Planned
  • other - Other
  • note - Note
note
string
Default: ""

Responses

Request samples

Content type
Example

Call when the patient physically arrives. The API stamps arrived_at with the current server time (UTC).

{
  • "status": "arrived",
  • "note": "Checked in at front desk."
}

Response samples

Content type
application/json

Returns the full appointment resource with the new status and patient-flow timestamps.

{
  • "id": "55555555-5555-4555-8555-555555555555",
  • "patient": "11111111-1111-4111-8111-111111111111",
  • "provider": "22222222-2222-4222-8222-222222222222",
  • "provider_hygienist": "33333333-3333-4333-8333-333333333333",
  • "operatory": "44444444-4444-4444-8444-444444444444",
  • "treatment_plan": null,
  • "date_time": "2026-05-14T09:00:00-07:00",
  • "duration_minutes": 60,
  • "status": "arrived",
  • "confirmed_status": "not_called",
  • "appointment_type": "Crown Prep",
  • "is_hygiene": false,
  • "is_new_patient": false,
  • "procedure_description": "D2740 Crown - porcelain/ceramic substrate",
  • "note": "Patient prefers morning appointments.",
  • "cancellation_reason": "",
  • "reschedule_requested": false,
  • "arrived_at": "2026-05-14T16:00:12Z",
  • "seated_at": null,
  • "ready_for_doctor_at": null,
  • "ready_for_walkout_at": null,
  • "dismissed_at": null,
  • "patient_name": "Example, Jane",
  • "provider_name": "Synthetic, Dr. Dana",
  • "provider_hygienist_name": "Synthetic, Hollis",
  • "scheduled_procedures": [
    ],
  • "custom_data": { }
}

practice_scheduling_available_slots_retrieve

Find available appointment slots for a given date.

Query params: date: Date in YYYY-MM-DD format (required). duration_minutes: Appointment length in minutes (required). provider: Optional provider ID. operatory: Optional operatory ID. interval: Slot interval in minutes (default 15).

Returns only slot times — does not leak why other times are unavailable.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
date
required
string <date>

Date (YYYY-MM-DD)

duration_minutes
required
integer

Required duration

interval
integer

Slot interval in minutes (default 15)

operatory
Array of integers

Filter by operatory. Repeat the param for a union: ?operatory=3&operatory=4.

provider
Array of integers

Filter by provider. Repeat the param for a union: ?provider=1&provider=2.

Responses

practice_scheduling_day_sheet_retrieve

Return the complete day-sheet for operatory-based schedule rendering.

Single request returning operatories, schedule blocks, and appointments.

Each entry in operatories[] carries an in_chair_patient field (GH-713) — None when the chair is empty, otherwise the authoritatively-resolved currently-seated patient:

{
    "patient_id": "<uuid>",
    "patient_name": "Last, First",
    "appointment_id": "<uuid> | null",
    "since": "<ISO 8601 UTC>",
}

Resolution rules (see :func:apps.scheduling.services._resolve_in_chair_patients):

  • Status is one of seated / ready_for_doctor / ready_for_walkout (the patient is in the chair across all three; arrived is lobby-only, complete sets dismissed_at).
  • dismissed_at IS NULL as a safety net for imported data.
  • On multiple "in chair" rows per operatory (back-to-back seatings without a dismiss — see GH-713 issue body), the most-recently-seated row wins.
  • Walk-ins: not exposed today (no walk-in-patient surface exists in the API yet — OperatoryPresence tracks staff occupancy, not patients). The appointment_id field is nullable so the shape is forward-compatible.

Query params: date: Date in YYYY-MM-DD format (required). include_hidden: "true" to include cancelled/unscheduled/planned appointments (default false).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
date
required
string <date>

Day sheet date (YYYY-MM-DD)

include_hidden
boolean

Include hidden appointments

Responses

Response samples

Content type
application/json
{
  • "date": "string",
  • "operatories": [
    ],
  • "blocks": [
    ],
  • "appointments": [
    ]
}

practice_scheduling_find_spot_retrieve

Multi-day slot search with patient scheduling constraints.

All constraint logic runs server-side. Clients send one request with constraints and get back matching slots across multiple days.

Query params: duration_minutes: Required appointment length in minutes. start_date: First date to search (default: today). YYYY-MM-DD. end_date: Last date to search (default: start_date + 30 days). YYYY-MM-DD. days_of_week: Legacy shorthand — comma-separated weekday ints (0=Mon..6=Sun). earliest_time: Legacy shorthand — earliest acceptable start time (HH:MM). latest_time: Legacy shorthand — latest acceptable start time (HH:MM). availability_windows: Repeatable <days>:<start>-<end> windows. Union semantics. Mutually exclusive with the legacy days_of_week / earliest_time / latest_time params — supply one form or the other. provider: Optional provider ID(s). Repeatable for union. operatory: Optional operatory ID(s). Repeatable for union. max_results: Max slots to return (default 20, max 50).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
availability_windows
Array of strings

Disjoint availability windows. Each value is <days>:<start>-<end> where <days> is a comma-separated list of weekday ints (0=Mon..6=Sun) and each time bound is HH:MM or blank. Repeat the param for a union. Example: ?availability_windows=4:15:00-&availability_windows=0,2,4:-10:00 means "Thursdays 3 PM onwards OR Mon/Wed/Fri before 10 AM". Mutually exclusive with the legacy days_of_week / earliest_time / latest_time trio.

days_of_week
string

Legacy single-window shorthand: comma-separated weekday ints (0=Mon..6=Sun). Mutually exclusive with availability_windows.

duration_minutes
required
integer

Required duration

earliest_time
string

Legacy single-window shorthand: earliest start time (HH:MM). Mutually exclusive with availability_windows.

end_date
string <date>

Last date to search (max 90 days)

latest_time
string

Legacy single-window shorthand: latest start time (HH:MM). Mutually exclusive with availability_windows.

max_results
integer

Max results (default 20, max 50)

operatory
Array of integers

Filter by operatory. Repeat the param for a union: ?operatory=3&operatory=4.

provider
Array of integers

Filter by provider. Repeat the param for a union: ?provider=1&provider=2.

start_date
string <date>

First date to search (default: today)

Responses

practice_scheduling_month_summary_retrieve

Per-day appointment aggregate for the month-view calendar grid.

GET /v1/practice/<uid>/scheduling/month-summary/?from=YYYY-MM-DD&to=YYYY-MM-DD

Returns a sparse map of local-date strings to {appointment_count, production} in a single round-trip, replacing the auto-paginated /scheduling/appointment/ fetch loop used by the web month-view (useMonthData).

Business rules:

  • Days are bucketed in the practice's timezone, never server UTC nor the browser's timezone. An appointment at 11 PM local on 2026-04-01 stays on that date regardless of the server's wall clock.
  • appointment_count and production both exclude appointments whose status is cancelled or broken, matching the client-side filter the web app used to apply.
  • production sums AppointmentProcedure.fee for every scheduled procedure attached to an included appointment on the day.
  • The response is sparse: only days with at least one included appointment appear. Callers treat absent keys as empty days.
  • from / to are both inclusive. No server-side range cap is imposed (the caller bounds it to ~6 weeks for the month grid); the endpoint is a single GROUP BY query covered by (practice_id, date_time) so a reasonable window stays well under 50 ms even at 2000 appointments.
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
from
required
string <date>

Inclusive start date (YYYY-MM-DD), interpreted in practice timezone.

to
required
string <date>

Inclusive end date (YYYY-MM-DD), interpreted in practice timezone.

Responses

Response samples

Content type
application/json
{
  • "from": "2019-08-24",
  • "to": "2019-08-24",
  • "days": {
    }
}

practice_scheduling_open_close_retrieve

Return the practice's open/close times for a date from appointment data.

GET /v1/practice/<uid>/scheduling/open-close/?date=YYYY-MM-DD

"Open" is the earliest qualifying appointment's start; "close" is the latest qualifying appointment's end (start + duration). The endpoint is intentionally shaped for third-party integrations that simply need "when does the office open today?" without having to iterate the full schedule.

Business rules:

  • date is interpreted in the practice's timezone. An appointment whose local start time falls on that date counts, regardless of server UTC or the caller's wall clock.
  • Appointments with status cancelled or broken (the model's combined Broken / No-Show choice) are excluded -- a cancelled 8 AM slot does not make the office "open at 8:00".
  • open / close are returned as ISO-8601 datetimes with the practice's TZ offset baked in (e.g. 2026-04-22T08:15:00-04:00). The offset reflects the practice's timezone on that calendar date, so DST transitions produce the right offset on each side of the jump. Consumers that want bare wall-clock time can slice the string; consumers that need an unambiguous instant already have one.
  • No qualifying appointments yields {"date": ..., "open": null, "close": null} (HTTP 200) -- no data is a valid answer, not a 404.

Auth: any authenticated user with practice access. OAuth tokens must carry the scheduling:read scope; JWT / session callers pass through :class:SchedulingScope unchanged.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
date
required
string <date>
Examples:
  • date=2026-04-22 - Example date

Target date (YYYY-MM-DD) interpreted in the practice's local timezone. An appointment that starts at 8:15 AM local on that date yields an open timestamp anchored to 08:15 on that date with the practice's TZ offset.

Responses

Response samples

Content type
application/json
Example
{
  • "date": "2026-04-22",
  • "open": "2026-04-22T08:15:00-04:00",
  • "close": "2026-04-22T17:30:00-04:00"
}

practice_scheduling_operatory_walkin_create

Seat a patient as a walk-in in the given operatory (GH-715).

POST /api/v1/practice/<practice_uid>/scheduling/operatory/<operatory_id>/walkin/

Body: {"patient": "<patient_uid>"}

Creates an :class:OperatoryWalkIn row with seated_at=now() and surfaces the patient in the chair-grid's in_chair_patient field on the next day-sheet fetch (with appointment_id: null).

Refuses with HTTP 400 when an active walk-in already covers the same operatory -- a chair holds at most one patient at a time. Callers must dismiss the existing walk-in (or transition a scheduled appointment to seated, which auto-dismisses the walk-in) before seating a second one.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
operatory_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
patient
required
string <uuid>

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "patient_name": "string",
  • "seated_at": "2019-08-24T14:15:22Z",
  • "dismissed_at": "2019-08-24T14:15:22Z",
  • "seated_by": "b45d71b8-3393-4485-9ef5-232c57d50c44"
}

practice_scheduling_operatory_walkin_dismiss_create

Dismiss the active walk-in for the given operatory (GH-715).

POST /api/v1/practice/<practice_uid>/scheduling/operatory/<operatory_id>/walkin/dismiss/

Sets dismissed_at = now() on the active :class:OperatoryWalkIn row for the operatory, returning the closed row. Returns 404 when no active walk-in exists for that chair (also covers cross-tenant: operatories from another practice are filtered out before lookup).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
operatory_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "patient_name": "string",
  • "seated_at": "2019-08-24T14:15:22Z",
  • "dismissed_at": "2019-08-24T14:15:22Z",
  • "seated_by": "b45d71b8-3393-4485-9ef5-232c57d50c44"
}

practice_scheduling_recall_list

List and create recall / recare records for a practice.

Supports filtering by patient, recall_type, is_disabled, due-date range (due_before / due_after), and unscheduled status.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
due_after
string <date>
Examples:
  • due_after=2025-06-01 - Due from today

Inclusive lower bound on date_due (ISO 8601 date, YYYY-MM-DD).

due_before
string <date>
Examples:
  • due_before=2025-09-30 - Due this quarter

Inclusive upper bound on date_due (ISO 8601 date, YYYY-MM-DD).

is_disabled
string
Enum: "false" "true"

Filter by disabled status. Accepts true or false.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

patient
integer

Filter by patient integer PK.

recall_type
string
Examples:
  • recall_type=prophy -
  • recall_type=perio - Perio maintenance
  • recall_type=exam - Periodic exam

Filter by recall type slug. The field is free-form (CharField(max_length=100)) to accommodate PMS-specific categories during migrations; common values include prophy, perio, and exam.

unscheduled
string
Enum: "false" "true"

Filter to recalls whose date_scheduled is null (true) or non-null (false). Drives the operations-team 'unscheduled recalls' worklist.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_scheduling_recall_create

List and create recall / recare records for a practice.

Supports filtering by patient, recall_type, is_disabled, due-date range (due_before / due_after), and unscheduled status.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
patient
string <uuid>
recall_type
required
string [ 1 .. 100 ] characters
date_due
string or null <date>
date_previous
string or null <date>
date_scheduled
string or null <date>
is_disabled
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "recall_type": "string",
  • "date_due": "2019-08-24",
  • "date_previous": "2019-08-24",
  • "date_scheduled": "2019-08-24",
  • "is_disabled": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "recall_type": "string",
  • "date_due": "2019-08-24",
  • "date_previous": "2019-08-24",
  • "date_scheduled": "2019-08-24",
  • "is_disabled": true,
  • "custom_data": null
}

practice_scheduling_recall_bulk_partial_update

Handle PATCH on the list endpoint for bulk updates.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
custom_data
any

Responses

Request samples

Content type
{
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "patient_name": "string",
  • "prefers_sms": true,
  • "prefers_email": true,
  • "recall_type": "string",
  • "date_due": "2019-08-24",
  • "date_previous": "2019-08-24",
  • "date_scheduled": "2019-08-24",
  • "last_visit_date": "2019-08-24",
  • "has_future_appointment": true,
  • "last_reached_at": "2019-08-24T14:15:22Z",
  • "is_disabled": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

List distinct recall types in use at a practice.

Reference-data endpoint that returns every distinct recall_type string currently in use on the practice's :class:Recall rows. The web Recall Due report uses this to populate its filter dropdown without having to harvest types from the visible page of results (which hides rare types the user has not scrolled to). Recall type is currently a free-form CharField on :class:apps.scheduling.models.Recall, so the source of truth is the existing rows -- there is no separate reference table.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "results": [
    ]
}

practice_scheduling_reports_cancellations_retrieve

Cancellation report with rebook annotations (api#155).

Returns every appointment whose status is cancelled and whose latest "to cancelled" status-log entry falls inside the requested window. Each row is annotated with rebook status and lead time so the front desk can tell at a glance whether the patient got back on the books and how much notice they gave.

Query params: cancelled_between YYYY-MM-DD,YYYY-MM-DD in practice TZ (preferred). When present, overrides from / to below. from, to Inclusive dates in practice TZ. Used when cancelled_between is not supplied.

Either the shortcut or explicit from/to must be provided.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
cancelled_between
string

Two ISO dates separated by a comma (YYYY-MM-DD,YYYY-MM-DD) interpreted in the practice's local timezone. Filters on the cancellation timestamp (latest status-log entry transitioning the row to cancelled). Either this parameter, or explicit from/to below, is required.

from
string <date>

Inclusive start date (YYYY-MM-DD, practice TZ). Ignored when cancelled_between is passed.

to
string <date>

Inclusive end date (YYYY-MM-DD, practice TZ). Ignored when cancelled_between is passed.

Responses

Response samples

Content type
application/json
{
  • "results": [
    ]
}

practice_scheduling_reports_provider_utilization_retrieve

Provider Utilization -- scheduled patient time / available working time.

Denominator rule (Aaron, api#156): blocked time (lunch, admin blocks, time-off overrides flagged non-patient) is subtracted from the denominator. A provider with 8h template time and a 1h lunch blockout shows a denominator of 7h, not 8h. Including blocked time would drag utilization down for reasons that are not actionable by the front desk.

Cancelled, broken (no-show), and unscheduled appointments do not count toward scheduled_hours -- they're treated as open time since the slot was released.

Query params: from Required. Inclusive start date (YYYY-MM-DD, practice TZ). to Required. Inclusive end date (YYYY-MM-DD, practice TZ). granularity Optional. day | week | month. provider Optional. Provider UID; repeat for multi-select.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
from
required
string <date>

Inclusive start date in the practice's local timezone (ISO 8601 YYYY-MM-DD).

granularity
string
Enum: "day" "month" "week"

Bucket size: day, week, or month. Defaults to day when the window is 14 days or less, week otherwise.

provider
Array of strings

Restrict the report to specific providers. Repeat the parameter for a multi-select filter, e.g. ?provider=<uuid-a>&provider=<uuid-b>. Omit to include every active, non-hidden provider in the practice.

to
required
string <date>

Inclusive end date in the practice's local timezone (ISO 8601 YYYY-MM-DD). The window must not exceed 12 months.

Responses

Response samples

Content type
application/json
{
  • "results": [
    ]
}

practice_scheduling_resolved_schedule_retrieve

Return the effective schedule for a date or date range.

Query params: date: Single date (YYYY-MM-DD). Returns blocks for that date. date_from / date_to: Date range. Returns blocks keyed by date. provider: Optional provider ID to filter to a single provider.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
date
string <date>

Single date (YYYY-MM-DD)

date_from
string <date>

Range start (YYYY-MM-DD)

date_to
string <date>

Range end (YYYY-MM-DD)

provider
integer

Filter by provider

Responses

Response samples

Content type
application/json
{
  • "date": "string",
  • "date_from": "string",
  • "date_to": "string",
  • "blocks": [
    ],
  • "schedule": {
    }
}

practice_scheduling_schedule_override_list

List and create date-specific schedule overrides.

Supports filtering by provider, date_from/date_to range, and schedule_type.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
date_from
string <date>
Examples:
  • date_from=2025-06-01 - Today forward

Inclusive lower bound on schedule_date (ISO 8601 date, YYYY-MM-DD).

date_to
string <date>
Examples:
  • date_to=2025-09-30 - Quarter end

Inclusive upper bound on schedule_date (ISO 8601 date, YYYY-MM-DD).

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

provider
integer

Filter to overrides owned by this provider (integer PK). Overrides with a null provider are practice-wide entries (holidays, closure days).

schedule_type
string
Enum: "blockout" "office_hours" "provider"

Filter by override kind. office_hours = one-off practice open/closed window, provider = one-off provider availability change, blockout = date-specific unavailable window.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_scheduling_schedule_override_create

List and create date-specific schedule overrides.

Supports filtering by provider, date_from/date_to range, and schedule_type.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
provider
string or null <uuid>
schedule_date
required
string <date>
start_time
required
string <time>
end_time
required
string <time>
schedule_type
required
string (ScheduleTypeEnum)
Enum: "office_hours" "provider" "blockout"
  • office_hours - Office Hours
  • provider - Provider Availability
  • blockout - Blockout
blockout_type
string <= 50 characters

e.g. lunch, meeting, holiday, time_off

operatory
string or null <uuid>
status
string (ScheduleOverrideStatusEnum)
Enum: "open" "closed" "holiday"
  • open - Open
  • closed - Closed
  • holiday - Holiday
note
string
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "schedule_date": "2019-08-24",
  • "start_time": "14:15:22Z",
  • "end_time": "14:15:22Z",
  • "schedule_type": "office_hours",
  • "blockout_type": "string",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "status": "open",
  • "note": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "schedule_date": "2019-08-24",
  • "start_time": "14:15:22Z",
  • "end_time": "14:15:22Z",
  • "schedule_type": "office_hours",
  • "blockout_type": "string",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "status": "open",
  • "note": "string",
  • "custom_data": null
}

practice_scheduling_schedule_template_list

List and create recurring schedule templates.

Supports filtering by provider, day_of_week, and schedule_type.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
day_of_week
integer
Enum: 0 1 2 3 4 5 6

Filter by day of week. Integer 0-6 where 0=Sunday and 6=Saturday (Django Weekday convention).

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

provider
integer

Filter to templates owned by this provider (integer PK). Templates with a null provider are practice-wide entries (e.g. office hours when schedule_type=office_hours) and will not match a numeric provider filter.

schedule_type
string
Enum: "blockout" "office_hours" "provider"

Filter by template kind. office_hours = practice-wide open hours, provider = per-provider availability, blockout = recurring unavailable window (lunch, meetings).

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_scheduling_schedule_template_create

List and create recurring schedule templates.

Supports filtering by provider, day_of_week, and schedule_type.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
provider
string or null <uuid>
day_of_week
required
integer [ -2147483648 .. 2147483647 ]

0=Sunday, 1=Monday, ..., 6=Saturday

start_time
required
string <time>
end_time
required
string <time>
schedule_type
required
string (ScheduleTypeEnum)
Enum: "office_hours" "provider" "blockout"
  • office_hours - Office Hours
  • provider - Provider Availability
  • blockout - Blockout
blockout_type
string <= 50 characters

e.g. lunch, meeting, admin

operatory
string or null <uuid>
is_active
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "day_of_week": -2147483648,
  • "start_time": "14:15:22Z",
  • "end_time": "14:15:22Z",
  • "schedule_type": "office_hours",
  • "blockout_type": "string",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "is_active": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "day_of_week": -2147483648,
  • "start_time": "14:15:22Z",
  • "end_time": "14:15:22Z",
  • "schedule_type": "office_hours",
  • "blockout_type": "string",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "is_active": true,
  • "custom_data": null
}

practice_scheduling_stats_retrieve

Quick scheduling stats.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "total_appointments": 0,
  • "completed": 0,
  • "scheduled": 0,
  • "today": 0,
  • "this_week": 0
}

practice_scheduling_validate_appointment_create

Validate a proposed appointment against scheduling constraints.

POST { "operatory": 1, "date_time": "2026-03-19T09:00:00", "duration_minutes": 60, "provider": 1, // optional "exclude_appointment": 42 // optional, for rescheduling }

Returns {"issues": [...], "valid": true/false}

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
operatory
string or null <uuid>
date_time
required
string <date-time>

ISO 8601 with timezone offset.

duration_minutes
required
integer >= 1
provider
string or null <uuid>
exclude_appointment
string or null <uuid>

Responses

Request samples

Content type

Returns scheduling issues without persisting anything. Useful for drag-to-reschedule UX where the client wants to warn before the drop is committed. exclude_appointment ignores conflicts with the appointment being rescheduled.

{
  • "operatory": "44444444-4444-4444-8444-444444444444",
  • "date_time": "2026-05-14T09:00:00-07:00",
  • "duration_minutes": 60,
  • "provider": "22222222-2222-4222-8222-222222222222",
  • "exclude_appointment": "55555555-5555-4555-8555-555555555555"
}

Response samples

Content type
application/json
Example

Safe to book — no conflicts, no warnings.

{
  • "valid": true,
  • "issues": [ ]
}

Patients

Patient demographics and search

practice_intake_arrive_create

Single round-trip patient lookup + appointment arrival for kiosks.

POST /api/v1/practice/<uid>/intake/arrive/ Body: {"last_name": "Smith", "date_of_birth": "1980-04-22"}

Collapses the legacy three-call kiosk sequence (intake/lookup/scheduling/appointment/scheduling/.../transition/) into a single signed request so that a kiosk on a slow network can mark a patient arrived in one round-trip and so the kiosk OAuth token does not need IsStaffUser — only the write:patients scope.

Privacy contract

The 404 response is deliberately generic: the same status fires for "no patient match", "no eligible appointment today", and "multiple ambiguous patient matches". This prevents a public kiosk from being used as an enumeration oracle (whether a given last name + DOB exists in the practice, or whether that patient has an appointment).

Today is computed in the practice's local timezone, not the server's UTC clock — a remote staff member or a worker process in a different region must still see "today" from the office's perspective.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
last_name
required
string [ 1 .. 100 ] characters

Patient's last name (case-insensitive exact match).

date_of_birth
required
string <date>

Patient's date of birth (YYYY-MM-DD).

Responses

Request samples

Content type
{
  • "last_name": "string",
  • "date_of_birth": "2019-08-24"
}

Response samples

Content type
application/json
{
  • "patient": {
    },
  • "appointment": {
    }
}

practice_patient_list

List and create patients. Staff-only — patient users cannot access.

Supports the reporting filters for the New Patient report (api#153) and the Inactive Patient report (api#154). Both compute their "visit" date from the patient's completed appointments (complete / ready_for_walkout), bucketed in the practice's timezone, so a 23:30 appointment in Los Angeles doesn't spill into tomorrow because the server happens to speak UTC.

The first-visit and last-visit annotations are attached only when a corresponding filter is active or include=first_visit / include=last_visit is supplied -- they each add a correlated Subquery and we don't want every typeahead request paying for them.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
as_of
string <date>

Reference date for the is_still_active annotation (YYYY-MM-DD, practice TZ). Defaults to today in the practice timezone. Only meaningful when include=first_visit is set -- is_still_active is true when the patient has at least one completed appointment in the 90 days preceding as_of (inclusive).

first_visit_date_from
string <date>

Include only patients whose first completed visit (earliest complete or ready_for_walkout appointment, bucketed in practice TZ) is on or after this date (inclusive). Used by the New Patient report.

first_visit_date_to
string <date>

Include only patients whose first completed visit is on or before this date (inclusive). Combine with first_visit_date_from to form a closed range.

first_visit_production_gte
number <double>

Include only patients whose first-visit production is greater than or equal to this value. Requires the first-visit include group to be active (include=first_visit or first_visit_date_from/first_visit_date_to). Used by the New Patient report to exclude walk-in exams that never converted into real production.

has_future_appointment
boolean

When false, exclude patients with any scheduled future appointment (scheduled / arrived / seated / ready_for_doctor / ready_for_walkout with date_time in the future). When true, include only those patients. Default: no filtering on future appointments.

include
string

Comma-separated list of optional serializer field groups to include on every row. Supported values: first_visit (adds first_visit_date, first_visit_production, first_visit_provider_id, first_visit_provider_name, is_still_active), last_visit (adds last_visit_date). The first_visit_* fields are also returned automatically when first_visit_date_from / first_visit_date_to is set; last_visit_date is returned automatically when last_visit_before is set.

last_visit_before
string <date>

Include only patients whose most recent completed visit is on or before this date (inclusive). Used by the Inactive Patient report.

ordering
string

Ordering: first_visit_date / -first_visit_date, last_visit_date / -last_visit_date. Nulls are sorted last in either direction so patients without any completed visits don't crowd the top of the list.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

phone
string

Filter to patients whose phone_mobile, phone_home, or phone_work matches the supplied phone number after E.164 normalisation on both sides. Accepts any phone-shaped input (+15551234567, 555-123-4567, (555) 123-4567); stored values are also re-normalised at match time, so a query for +15551234567 matches a stored (555) 123-4567 or 5551234567. Used by the call-pop screen to fetch a pre-filtered list instead of paging the full patient table. Unparseable input returns an empty list (200, not 400) — matches the spirit of the other forgiving query params on this endpoint.

provider
Array of strings <uuid> [ items <uuid > ]

Filter by provider UUID. May be repeated (?provider=<u1>&provider=<u2>) or comma-separated (?provider=<u1>,<u2>) to match any of several providers (union / OR). When the first-visit include group is active (include=first_visit or first_visit_date_from/first_visit_date_to is set), matches against the patient's first-visit provider -- i.e. who they saw on their earliest completed appointment. Otherwise matches against primary_provider.

search
string

Case-insensitive substring search. Single-token queries fan out across first_name, last_name, email, phone_home/phone_work/phone_mobile, date_of_birth, address, city, state, and zip_code. Multi-token queries (e.g. aaron de bruyn) are treated as name searches: every token must match first_name or last_name (AND across tokens, OR across the two name fields), which prevents accidental substring hits inside email/phone/address from returning unrelated patients. Also powers the patient-search typeahead; the TypeaheadPageNumberPagination cap (25/50) keeps autocomplete responses tight for UI clients.

status
string
Enum: "active" "archived" "deceased" "inactive" "prospective"

Filter by patient status.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_create

List and create patients. Staff-only — patient users cannot access.

Supports the reporting filters for the New Patient report (api#153) and the Inactive Patient report (api#154). Both compute their "visit" date from the patient's completed appointments (complete / ready_for_walkout), bucketed in the practice's timezone, so a 23:30 appointment in Los Angeles doesn't spill into tomorrow because the server happens to speak UTC.

The first-visit and last-visit annotations are attached only when a corresponding filter is active or include=first_visit / include=last_visit is supplied -- they each add a correlated Subquery and we don't want every typeahead request paying for them.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
first_name
required
string [ 1 .. 100 ] characters
last_name
required
string [ 1 .. 100 ] characters
preferred_name
string <= 100 characters
email
string <email> <= 254 characters
date_of_birth
string or null <date>
gender
string (GenderEnum)
Enum: "male" "female" "other" "unknown"
  • male - Male
  • female - Female
  • other - Other
  • unknown - Unknown
status
string (PatientStatusEnum)
Enum: "active" "inactive" "archived" "deceased" "prospective"
  • active - Active
  • inactive - Inactive
  • archived - Archived
  • deceased - Deceased
  • prospective - Prospective
phone_home
string or null
phone_work
string or null
phone_mobile
string or null
address
string <= 255 characters
address2
string <= 255 characters
city
string <= 100 characters
state
string <= 50 characters
zip_code
string <= 10 characters ^\d{5}(-\d{4})?$
primary_provider
string or null <uuid>
secondary_provider
string or null <uuid>
balance_current
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Current account balance, denormalized from the ledger for fast list rendering.

last_recall_date
string or null <date>

Most recent recall appointment date from the source PMS

next_recall_date
string or null <date>

Next scheduled recall appointment date from the source PMS

prefers_email
boolean

Patient opts in to email communications (per source PMS)

prefers_sms
boolean

Patient opts in to SMS/text communications (per source PMS)

hipaa_consent_signed
boolean

HIPAA treatment consent signed (per source PMS)

hipaa_consent_date
string or null <date>

Date HIPAA treatment consent was signed

hipaa_authorization_signed
boolean

HIPAA authorization (release of info) signed (per source PMS)

hipaa_authorization_date
string or null <date>

Date HIPAA authorization was signed

hipaa_privacy_practices_signed
boolean

HIPAA notice of privacy practices acknowledged (per source PMS)

hipaa_privacy_practices_date
string or null <date>

Date HIPAA notice of privacy practices was acknowledged

custom_data
any

Responses

Request samples

Content type
{
  • "first_name": "string",
  • "last_name": "string",
  • "preferred_name": "string",
  • "email": "user@example.com",
  • "date_of_birth": "2019-08-24",
  • "gender": "male",
  • "status": "active",
  • "phone_home": "string",
  • "phone_work": "string",
  • "phone_mobile": "string",
  • "address": "string",
  • "address2": "string",
  • "city": "string",
  • "state": "string",
  • "zip_code": "string",
  • "primary_provider": "be2be9e9-c010-46fe-8c1e-a13cbc4f6d37",
  • "secondary_provider": "777f5dc9-f0f1-403f-9363-1023b8767d88",
  • "balance_current": "string",
  • "last_recall_date": "2019-08-24",
  • "next_recall_date": "2019-08-24",
  • "prefers_email": true,
  • "prefers_sms": true,
  • "hipaa_consent_signed": true,
  • "hipaa_consent_date": "2019-08-24",
  • "hipaa_authorization_signed": true,
  • "hipaa_authorization_date": "2019-08-24",
  • "hipaa_privacy_practices_signed": true,
  • "hipaa_privacy_practices_date": "2019-08-24",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "first_name": "string",
  • "last_name": "string",
  • "preferred_name": "string",
  • "email": "user@example.com",
  • "date_of_birth": "2019-08-24",
  • "gender": "male",
  • "status": "active",
  • "phone_home": "string",
  • "phone_work": "string",
  • "phone_mobile": "string",
  • "address": "string",
  • "address2": "string",
  • "city": "string",
  • "state": "string",
  • "zip_code": "string",
  • "primary_provider": "be2be9e9-c010-46fe-8c1e-a13cbc4f6d37",
  • "secondary_provider": "777f5dc9-f0f1-403f-9363-1023b8767d88",
  • "last_medical_review": "2019-08-24",
  • "last_medical_review_by": "32e17085-58ec-492b-b21e-23eca3985cd7",
  • "last_medical_review_by_name": "string",
  • "balance_current": "string",
  • "last_recall_date": "2019-08-24",
  • "next_recall_date": "2019-08-24",
  • "prefers_email": true,
  • "prefers_sms": true,
  • "hipaa_consent_signed": true,
  • "hipaa_consent_date": "2019-08-24",
  • "hipaa_authorization_signed": true,
  • "hipaa_authorization_date": "2019-08-24",
  • "hipaa_privacy_practices_signed": true,
  • "hipaa_privacy_practices_date": "2019-08-24",
  • "custom_data": null,
  • "referral_source": "string"
}

practice_patient_bulk_partial_update

Handle PATCH on the list endpoint for bulk updates.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
first_name
string [ 1 .. 100 ] characters
last_name
string [ 1 .. 100 ] characters
preferred_name
string <= 100 characters
email
string <email> <= 254 characters
date_of_birth
string or null <date>
gender
string (GenderEnum)
Enum: "male" "female" "other" "unknown"
  • male - Male
  • female - Female
  • other - Other
  • unknown - Unknown
status
string (PatientStatusEnum)
Enum: "active" "inactive" "archived" "deceased" "prospective"
  • active - Active
  • inactive - Inactive
  • archived - Archived
  • deceased - Deceased
  • prospective - Prospective
phone_home
string or null
phone_work
string or null
phone_mobile
string or null
address
string <= 255 characters
address2
string <= 255 characters
city
string <= 100 characters
state
string <= 50 characters
zip_code
string <= 10 characters ^\d{5}(-\d{4})?$
primary_provider
string or null <uuid>
secondary_provider
string or null <uuid>
balance_current
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Current account balance, denormalized from the ledger for fast list rendering.

last_recall_date
string or null <date>

Most recent recall appointment date from the source PMS

next_recall_date
string or null <date>

Next scheduled recall appointment date from the source PMS

prefers_email
boolean

Patient opts in to email communications (per source PMS)

prefers_sms
boolean

Patient opts in to SMS/text communications (per source PMS)

hipaa_consent_signed
boolean

HIPAA treatment consent signed (per source PMS)

hipaa_consent_date
string or null <date>

Date HIPAA treatment consent was signed

hipaa_authorization_signed
boolean

HIPAA authorization (release of info) signed (per source PMS)

hipaa_authorization_date
string or null <date>

Date HIPAA authorization was signed

hipaa_privacy_practices_signed
boolean

HIPAA notice of privacy practices acknowledged (per source PMS)

hipaa_privacy_practices_date
string or null <date>

Date HIPAA notice of privacy practices was acknowledged

custom_data
any

Responses

Request samples

Content type
{
  • "first_name": "string",
  • "last_name": "string",
  • "preferred_name": "string",
  • "email": "user@example.com",
  • "date_of_birth": "2019-08-24",
  • "gender": "male",
  • "status": "active",
  • "phone_home": "string",
  • "phone_work": "string",
  • "phone_mobile": "string",
  • "address": "string",
  • "address2": "string",
  • "city": "string",
  • "state": "string",
  • "zip_code": "string",
  • "primary_provider": "be2be9e9-c010-46fe-8c1e-a13cbc4f6d37",
  • "secondary_provider": "777f5dc9-f0f1-403f-9363-1023b8767d88",
  • "balance_current": "string",
  • "last_recall_date": "2019-08-24",
  • "next_recall_date": "2019-08-24",
  • "prefers_email": true,
  • "prefers_sms": true,
  • "hipaa_consent_signed": true,
  • "hipaa_consent_date": "2019-08-24",
  • "hipaa_authorization_signed": true,
  • "hipaa_authorization_date": "2019-08-24",
  • "hipaa_privacy_practices_signed": true,
  • "hipaa_privacy_practices_date": "2019-08-24",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "first_name": "string",
  • "last_name": "string",
  • "preferred_name": "string",
  • "email": "user@example.com",
  • "date_of_birth": "2019-08-24",
  • "gender": "male",
  • "status": "active",
  • "phone_home": "string",
  • "phone_work": "string",
  • "phone_mobile": "string",
  • "address": "string",
  • "address2": "string",
  • "city": "string",
  • "state": "string",
  • "zip_code": "string",
  • "primary_provider": "be2be9e9-c010-46fe-8c1e-a13cbc4f6d37",
  • "secondary_provider": "777f5dc9-f0f1-403f-9363-1023b8767d88",
  • "last_medical_review": "2019-08-24",
  • "last_medical_review_by": "32e17085-58ec-492b-b21e-23eca3985cd7",
  • "last_medical_review_by_name": "string",
  • "balance_current": "string",
  • "last_recall_date": "2019-08-24",
  • "next_recall_date": "2019-08-24",
  • "prefers_email": true,
  • "prefers_sms": true,
  • "hipaa_consent_signed": true,
  • "hipaa_consent_date": "2019-08-24",
  • "hipaa_authorization_signed": true,
  • "hipaa_authorization_date": "2019-08-24",
  • "hipaa_privacy_practices_signed": true,
  • "hipaa_privacy_practices_date": "2019-08-24",
  • "custom_data": null,
  • "referral_source": "string"
}

practice_patient_referral_source_bulk_partial_update

Handle PATCH on the list endpoint for bulk updates.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
first_name
string <= 100 characters
last_name
string <= 100 characters
specialty
string <= 100 characters
phone
string <= 20 characters
email
string <email> <= 254 characters
npi
string <= 20 characters
is_doctor
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "first_name": "string",
  • "last_name": "string",
  • "specialty": "string",
  • "phone": "string",
  • "email": "user@example.com",
  • "npi": "string",
  • "is_doctor": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "first_name": "string",
  • "last_name": "string",
  • "specialty": "string",
  • "phone": "string",
  • "email": "user@example.com",
  • "npi": "string",
  • "is_doctor": true,
  • "custom_data": null,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_patient_stats_retrieve

Quick stats for the practice's patient data. Staff-only.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Clinical

Notes, procedures, treatment plans, perio, vitals, conditions, medications, allergies

practice_clinical_alerts_retrieve

Batch medical alert summaries for multiple patients.

GET /practice//clinical/alerts/?patient_ids=1,2,3

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

List chairside auto-note macros for a practice.

Returns the practice's catalog of operator-built chairside macros (#periomax -> a perio-eval template) for the chart-note editor's autocomplete surface. Paginated with :class:config.pagination.DefaultPageNumberPagination (stable ordering via pk tiebreaker).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

search
string

Case-insensitive substring search across name and body.

Responses

Response samples

Content type
application/json
{}

Create or upsert an auto-note macro.

Creates a new auto-note macro, or updates the existing row when (practice, name) already exists. This is the idempotent landing path for the Eaglesoft / OpenDental converters (escape-tools#205, escape-tools#206): re-running an import will refresh the body / prompts instead of returning HTTP 400 from the unique constraint.

Returns 201 Created for new rows and 200 OK for updates.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 128 ] characters

Operator-visible macro label, e.g. 'Perio Max'.

body
required
string non-empty

Template body with single-braced {key} placeholders matched against prompts[].key.

category
string <= 64 characters

Free-form grouping (e.g. 'Hygiene', 'Endo'). PMS-supplied; not enumerated.

Array of objects

Operator-fill widget specs. See AutoNote model docs for shape.

custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "body": "string",
  • "category": "string",
  • "prompts": [
    ],
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "body": "string",
  • "category": "string",
  • "prompts": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_clinical_auto_note_retrieve

Retrieve, update, or delete a single :class:AutoNote.

Hard delete is correct here -- auto-notes are authoring aids, not patient data, so HIPAA immutability does not apply.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
auto_note_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "body": "string",
  • "category": "string",
  • "prompts": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_clinical_auto_notes_update

Retrieve, update, or delete a single :class:AutoNote.

Hard delete is correct here -- auto-notes are authoring aids, not patient data, so HIPAA immutability does not apply.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
auto_note_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 128 ] characters

Operator-visible macro label, e.g. 'Perio Max'.

body
required
string non-empty

Template body with single-braced {key} placeholders matched against prompts[].key.

category
string <= 64 characters

Free-form grouping (e.g. 'Hygiene', 'Endo'). PMS-supplied; not enumerated.

Array of objects

Operator-fill widget specs. See AutoNote model docs for shape.

custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "body": "string",
  • "category": "string",
  • "prompts": [
    ],
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "body": "string",
  • "category": "string",
  • "prompts": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_clinical_auto_note_partial_update

Retrieve, update, or delete a single :class:AutoNote.

Hard delete is correct here -- auto-notes are authoring aids, not patient data, so HIPAA immutability does not apply.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
auto_note_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
name
string [ 1 .. 128 ] characters

Operator-visible macro label, e.g. 'Perio Max'.

body
string non-empty

Template body with single-braced {key} placeholders matched against prompts[].key.

category
string <= 64 characters

Free-form grouping (e.g. 'Hygiene', 'Endo'). PMS-supplied; not enumerated.

Array of objects

Operator-fill widget specs. See AutoNote model docs for shape.

custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "body": "string",
  • "category": "string",
  • "prompts": [
    ],
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "body": "string",
  • "category": "string",
  • "prompts": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_clinical_auto_note_destroy

Retrieve, update, or delete a single :class:AutoNote.

Hard delete is correct here -- auto-notes are authoring aids, not patient data, so HIPAA immutability does not apply.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
auto_note_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_clinical_note_template_list

List and create clinical note templates for a practice.

Supports filtering by category and active status.

Uses :class:ReferenceDataPagination (100/2000) instead of the default 20/100 cap because the web UI loads the full note-template catalog once for typeahead / dropdown rendering inside the chart. A mature practice accumulates hundreds of templates across categories -- paginating 20 at a time would thrash the chart UI. See api#194.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
active
string
Enum: "false" "true"

Filter by active status. Accepts true or false.

category
string
Enum: "endo" "exam" "general" "hygiene" "oral_surgery"

Filter by template category.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{}

practice_clinical_note_template_create

List and create clinical note templates for a practice.

Supports filtering by category and active status.

Uses :class:ReferenceDataPagination (100/2000) instead of the default 20/100 cap because the web UI loads the full note-template catalog once for typeahead / dropdown rendering inside the chart. A mature practice accumulates hundreds of templates across categories -- paginating 20 at a time would thrash the chart UI. See api#194.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 255 ] characters
CategoryEnum (string) or BlankEnum (any)
content
required
string non-empty

Template body. Supports placeholder tokens like {{tooth}}, {{provider}}.

is_active
boolean
sort_order
integer [ 0 .. 2147483647 ]
custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "category": "exam",
  • "content": "string",
  • "is_active": true,
  • "sort_order": 2147483647,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "category": "exam",
  • "content": "string",
  • "is_active": true,
  • "sort_order": 2147483647,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_clinical_procedure_list

Practice-wide procedure list and bulk create.

GET returns all procedures for the practice (paginated, filterable). POST accepts a JSON array for bulk import (up to 5000 records).

Used by escape-opendental, escape-eaglesoft, and escape-backup tools.

Uses PageNumberPagination instead of the default CursorPagination because bulk-imported procedures may have NULL created timestamps, which causes CursorPagination to crash with a 500.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
date_from
string <date>

Inclusive lower bound on proc_date (ISO 8601 date).

date_to
string <date>

Inclusive upper bound on proc_date (ISO 8601 date).

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

patient
string <uuid>

Filter to procedures for a single patient UUID.

provider
string <uuid>

Filter by provider UUID.

status
string
Enum: "complete" "existing_current" "existing_other"

Filter by procedure status. Common values are complete, existing_current, and existing_other; free-text is accepted for legacy PMS imports.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_clinical_procedure_create

Practice-wide procedure list and bulk create.

GET returns all procedures for the practice (paginated, filterable). POST accepts a JSON array for bulk import (up to 5000 records).

Used by escape-opendental, escape-eaglesoft, and escape-backup tools.

Uses PageNumberPagination instead of the default CursorPagination because bulk-imported procedures may have NULL created timestamps, which causes CursorPagination to crash with a 500.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
patient
required
string <uuid>
provider
string or null <uuid>
appointment
string or null <uuid>
procedure_code
string or null <uuid>
proc_code
string <= 20 characters
description
string <= 255 characters
proc_date
string or null <date>
date_complete
string or null <date>
proc_fee
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
status
string <= 30 characters

complete, existing_current, existing_other

tooth_num
string <= 10 characters
surface
string <= 20 characters
discount
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
unit_qty
integer [ 0 .. 2147483647 ]
custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "proc_code": "string",
  • "description": "string",
  • "proc_date": "2019-08-24",
  • "date_complete": "2019-08-24",
  • "proc_fee": "string",
  • "status": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "discount": "string",
  • "unit_qty": 2147483647,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "proc_code": "string",
  • "description": "string",
  • "proc_date": "2019-08-24",
  • "date_complete": "2019-08-24",
  • "proc_fee": "string",
  • "status": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "discount": "string",
  • "unit_qty": 2147483647,
  • "custom_data": null
}

practice_clinical_procedure_code_list

List and create procedure codes for a practice. Searchable by code/description.

Uses :class:ReferenceDataPagination (100/2000) instead of the default 20/100 cap because the web UI loads the full catalog once for local typeahead and service-type filtering across dropdowns. A typical practice catalog is 1K-4K ADA codes -- paginating 20 at a time would require dozens of round-trips and break the Service Codes screen / checkout dialog procedure search.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
active
string
Enum: "false" "true"

Filter by active status. Accepts true or false.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

search
string

Case-insensitive substring search across code, description, and abbreviation.

service_type
string
Enum: "adjunctive" "basic" "diagnostic" "endodontics" "major" "oral_surgery" "orthodontics" "other" "periodontics" "preventive" "prosthodontics"

Filter by ADA service type classification.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_clinical_procedure_code_create

List and create procedure codes for a practice. Searchable by code/description.

Uses :class:ReferenceDataPagination (100/2000) instead of the default 20/100 cap because the web UI loads the full catalog once for local typeahead and service-type filtering across dropdowns. A typical practice catalog is 1K-4K ADA codes -- paginating 20 at a time would require dozens of round-trips and break the Service Codes screen / checkout dialog procedure search.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
code
required
string [ 1 .. 20 ] characters
description
string <= 255 characters
abbreviation
string <= 100 characters
ServiceTypeEnum (string) or BlankEnum (any)
default_fee
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Practice UCR fee

default_duration_minutes
integer [ 0 .. 2147483647 ]

Default appointment block size

generate_recall
boolean

Triggers recall scheduling when completed

is_active
boolean
ada_code
string <= 20 characters

ADA/CDT code reference (insurance module)

custom_data
any

Responses

Request samples

Content type
{
  • "code": "string",
  • "description": "string",
  • "abbreviation": "string",
  • "service_type": "diagnostic",
  • "default_fee": "string",
  • "default_duration_minutes": 2147483647,
  • "generate_recall": true,
  • "is_active": true,
  • "ada_code": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "code": "string",
  • "description": "string",
  • "abbreviation": "string",
  • "service_type": "diagnostic",
  • "default_fee": "string",
  • "default_duration_minutes": 2147483647,
  • "generate_recall": true,
  • "is_active": true,
  • "ada_code": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_clinical_procedure_code_bulk_partial_update

Handle PATCH on the list endpoint for bulk updates.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
code
string [ 1 .. 20 ] characters
description
string <= 255 characters
abbreviation
string <= 100 characters
ServiceTypeEnum (string) or BlankEnum (any)
default_fee
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Practice UCR fee

default_duration_minutes
integer [ 0 .. 2147483647 ]

Default appointment block size

generate_recall
boolean

Triggers recall scheduling when completed

is_active
boolean
ada_code
string <= 20 characters

ADA/CDT code reference (insurance module)

custom_data
any

Responses

Request samples

Content type
{
  • "code": "string",
  • "description": "string",
  • "abbreviation": "string",
  • "service_type": "diagnostic",
  • "default_fee": "string",
  • "default_duration_minutes": 2147483647,
  • "generate_recall": true,
  • "is_active": true,
  • "ada_code": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "code": "string",
  • "description": "string",
  • "abbreviation": "string",
  • "service_type": "diagnostic",
  • "default_fee": "string",
  • "default_duration_minutes": 2147483647,
  • "generate_recall": true,
  • "is_active": true,
  • "ada_code": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_clinical_procedure_code_suggest_retrieve

Suggest an appropriate CDT code based on patient clinical history.

GET /practice//clinical/procedure-code/suggest/?patient_id=

Checks if the patient has any completed D4341/D4342 (SRP) procedures. If yes, suggests D4910 (perio maintenance) instead of D1110 (prophylaxis).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
query
string

Search query for procedure code suggestions

Responses

practice_patient_clinical_alerts_retrieve

Single-patient medical alert summary.

GET /practice//patient//clinical/alerts/

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

practice_patient_clinical_anesthesia_list

List and create anesthesia records for a patient.

Supports filtering by appointment and date range.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
appointment
string <uuid>

Filter records to a single appointment UUID.

date_from
string <date>

Inclusive lower bound on administered_at (ISO 8601 date). Interpreted in the practice's local timezone.

date_to
string <date>

Inclusive upper bound on administered_at (ISO 8601 date). Interpreted in the practice's local timezone.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_clinical_anesthesia_create

List and create anesthesia records for a patient.

Supports filtering by appointment and date range.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
appointment
string or null <uuid>
provider
string or null <uuid>
agent
required
string (AgentEnum)
Enum: "lidocaine_epi" "lidocaine" "articaine_epi" "articaine_epi_200" "mepivacaine_epi" "mepivacaine" "bupivacaine_epi" "prilocaine_epi" "prilocaine" "topical_benzocaine" "topical_lidocaine" "nitrous" "other"
  • lidocaine_epi - Lidocaine 2% with Epinephrine 1:100,000
  • lidocaine - Lidocaine 2% (plain)
  • articaine_epi - Articaine 4% with Epinephrine 1:100,000
  • articaine_epi_200 - Articaine 4% with Epinephrine 1:200,000
  • mepivacaine_epi - Mepivacaine 2% with Levonordefrin 1:20,000
  • mepivacaine - Mepivacaine 3% (plain)
  • bupivacaine_epi - Bupivacaine 0.5% with Epinephrine 1:200,000
  • prilocaine_epi - Prilocaine 4% with Epinephrine 1:200,000
  • prilocaine - Prilocaine 4% (plain)
  • topical_benzocaine - Topical Benzocaine 20%
  • topical_lidocaine - Topical Lidocaine 5%
  • nitrous - Nitrous Oxide / Oxygen
  • other - Other
agent_other
string <= 100 characters

If agent=other, specify here

route
string (RouteEnum)
Enum: "infiltration" "block" "topical" "inhalation"
  • infiltration - Infiltration
  • block - Block
  • topical - Topical
  • inhalation - Inhalation
site
string <= 100 characters

e.g. #14 buccal infiltration, right IAN block

carpules
string <decimal> ^-?\d{0,2}(?:\.\d{0,1})?$

Number of carpules administered

lot_number
string <= 50 characters
expiration_date
string or null <date>
administered_at
required
string <date-time>

When the anesthesia was administered

note
string

Complications, reactions, or additional notes

custom_data
any

Responses

Request samples

Content type
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "agent": "lidocaine_epi",
  • "agent_other": "string",
  • "route": "infiltration",
  • "site": "string",
  • "carpules": "string",
  • "lot_number": "string",
  • "expiration_date": "2019-08-24",
  • "administered_at": "2019-08-24T14:15:22Z",
  • "note": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "agent": "lidocaine_epi",
  • "agent_other": "string",
  • "route": "infiltration",
  • "site": "string",
  • "carpules": "string",
  • "lot_number": "string",
  • "expiration_date": "2019-08-24",
  • "administered_at": "2019-08-24T14:15:22Z",
  • "note": "string",
  • "custom_data": null
}

practice_patient_clinical_confirm_medical_review_create

Confirm that a patient's medical history has been reviewed.

POST sets patient.last_medical_review to today and patient.last_medical_review_by to the authenticated user.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_clinical_education_list

List and create patient education records for a patient.

Supports filtering by appointment, topic, and date range.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
appointment
string <uuid>

Filter records to a single appointment UUID.

date_from
string <date>

Inclusive lower bound on education_date (ISO 8601 date).

date_to
string <date>

Inclusive upper bound on education_date (ISO 8601 date).

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

topic
string
Enum: "brushing" "bruxism" "caries_risk" "diet_counseling" "dry_mouth" "electric_toothbrush" "flossing" "fluoride" "implant_care" "interproximal" "oral_hygiene" "ortho_care" "other" "perio_disease" "post_op" "pre_med" "sensitivity" "tobacco_cessation" "whitening"

Filter by education topic.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_clinical_education_create

List and create patient education records for a patient.

Supports filtering by appointment, topic, and date range.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
appointment
string or null <uuid>
provider
string or null <uuid>
topic
required
string (TopicEnum)
Enum: "oral_hygiene" "brushing" "flossing" "interproximal" "electric_toothbrush" "fluoride" "diet_counseling" "tobacco_cessation" "perio_disease" "caries_risk" "dry_mouth" "bruxism" "sensitivity" "whitening" "ortho_care" "implant_care" "post_op" "pre_med" "other"
  • oral_hygiene - Oral Hygiene Instructions
  • brushing - Brushing Technique
  • flossing - Flossing Technique
  • interproximal - Interproximal Cleaning
  • electric_toothbrush - Electric Toothbrush
  • fluoride - Fluoride Use
  • diet_counseling - Diet Counseling
  • tobacco_cessation - Tobacco Cessation
  • perio_disease - Periodontal Disease
  • caries_risk - Caries Risk
  • dry_mouth - Dry Mouth / Xerostomia
  • bruxism - Bruxism / Night Guard
  • sensitivity - Sensitivity
  • whitening - Whitening Options
  • ortho_care - Orthodontic Care
  • implant_care - Implant Care
  • post_op - Post-Operative Instructions
  • pre_med - Premedication Reminder
  • other - Other
detail
string

Specific instructions or notes about what was discussed

products_recommended
string <= 255 characters

e.g. Sonicare, Waterpik, MI Paste

education_date
required
string <date>
compliance_note
string

Patient response, compliance observations

send_to_portal
boolean

Make available in patient portal

custom_data
any

Responses

Request samples

Content type
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "topic": "oral_hygiene",
  • "detail": "string",
  • "products_recommended": "string",
  • "education_date": "2019-08-24",
  • "compliance_note": "string",
  • "send_to_portal": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "topic": "oral_hygiene",
  • "detail": "string",
  • "products_recommended": "string",
  • "education_date": "2019-08-24",
  • "compliance_note": "string",
  • "send_to_portal": true,
  • "custom_data": null
}

practice_patient_clinical_note_list

List and create clinical notes for a patient.

Supports filtering by note_type, provider, date range, and free-text search.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
date_from
string <date>

Inclusive lower bound on note_date (ISO 8601 date, e.g. 2025-01-15).

date_to
string <date>

Inclusive upper bound on note_date (ISO 8601 date).

note_type
string
Enum: "clinical" "consult" "exam" "hygiene" "lab" "other" "phone"

Filter by note type.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

provider
string <uuid>

Filter by provider UUID.

search
string

Case-insensitive substring search across subject and content.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_clinical_note_create

List and create clinical notes for a patient.

Supports filtering by note_type, provider, date range, and free-text search.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
appointment
string or null <uuid>
provider
string or null <uuid>
template
string or null <uuid>

Template used to create this note (reference only, content is copied)

note_type
string (NoteTypeEnum)
Enum: "clinical" "exam" "hygiene" "consult" "phone" "lab" "other"
  • clinical - Clinical Note
  • exam - Exam Note
  • hygiene - Hygiene Note
  • consult - Consult Note
  • phone - Phone Note
  • lab - Lab Note
  • other - Other
subject
string <= 200 characters
content
string

Plain text or structured note content

note_date
string or null <date>
is_addendum
boolean

Addendum to a previous note

parent_note
string or null <uuid>

If is_addendum=True, the original note this amends

custom_data
any

Responses

Request samples

Content type
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "note_type": "clinical",
  • "subject": "string",
  • "content": "string",
  • "note_date": "2019-08-24",
  • "is_addendum": true,
  • "parent_note": "47e0a283-e822-462a-a025-efa34db2b778",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "note_type": "clinical",
  • "subject": "string",
  • "content": "string",
  • "note_date": "2019-08-24",
  • "is_addendum": true,
  • "parent_note": "47e0a283-e822-462a-a025-efa34db2b778",
  • "custom_data": null
}

practice_patient_clinical_note_sign_create

Sign a clinical note (irreversible HIPAA action).

POST signs the note, setting is_signed=True, signed_by, and signed_at. Once signed, the note content becomes immutable.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
note_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_clinical_perio_readings_update

Bulk upsert perio readings for an exam.

PUT accepts an array of reading objects keyed by tooth_num. Uses update_or_create per tooth within the exam. Returns the full exam with nested readings after save.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
perio_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_clinical_perio_compare_retrieve

Compare two perio exams side by side.

GET /...perio/compare/?exam1=&exam2= Validates both exams belong to the same practice and patient.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
exam1
required
string <uuid>

First perio exam UUID to compare.

exam2
required
string <uuid>

Second perio exam UUID to compare.

Responses

practice_patient_clinical_procedure_list

List and create procedures for a patient.

Supports filtering by provider, date range, status, and free-text search.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
date_from
string <date>

Inclusive lower bound on proc_date (ISO 8601 date).

date_to
string <date>

Inclusive upper bound on proc_date (ISO 8601 date).

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

provider
string <uuid>

Filter by provider UUID.

search
string

Case-insensitive substring search across proc_code and description.

status
string
Enum: "complete" "existing_current" "existing_other"

Filter by procedure status. Common values are complete, existing_current, and existing_other; free-text is accepted for legacy PMS imports.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_clinical_procedure_create

List and create procedures for a patient.

Supports filtering by provider, date range, status, and free-text search.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
provider
string or null <uuid>
appointment
string or null <uuid>
procedure_code
string or null <uuid>
proc_code
string <= 20 characters
description
string <= 255 characters
proc_date
string or null <date>
proc_fee
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
status
string <= 30 characters

complete, existing_current, existing_other

tooth_num
string <= 10 characters
surface
string <= 20 characters
discount
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
unit_qty
integer [ 0 .. 2147483647 ]
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "proc_code": "string",
  • "description": "string",
  • "proc_date": "2019-08-24",
  • "proc_fee": "string",
  • "status": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "discount": "string",
  • "unit_qty": 2147483647,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "proc_code": "string",
  • "description": "string",
  • "proc_date": "2019-08-24",
  • "proc_fee": "string",
  • "status": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "discount": "string",
  • "unit_qty": 2147483647,
  • "custom_data": null
}

practice_patient_clinical_procedure_bulk_partial_update

Handle PATCH on the list endpoint for bulk updates.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
custom_data
any

Responses

Request samples

Content type
{
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "procedure_code": {
    },
  • "proc_code": "string",
  • "description": "string",
  • "proc_date": "2019-08-24",
  • "date_complete": "2019-08-24",
  • "proc_fee": "string",
  • "status": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "discount": "string",
  • "unit_qty": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_timeline_retrieve

Unified chronological feed for a patient.

Combines procedures, clinical notes, perio exams, treatment plans, imaging exams, communication logs, and appointments into a single sorted timeline. Paginated, newest first.

Accepts an optional event_type query parameter (comma-separated) to filter to specific event types.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
event_type
string

Comma-separated list of event types to include. Valid values: procedure, note, perio_exam, treatment_plan, imaging, communication, appointment. Omit to include all types.

page
integer

Page number (1-indexed)

page_size
integer

Number of events per page (default 50, max 200)

Responses

practice_patient_clinical_tooth_list

List and create tooth conditions for a patient.

Defaults to current conditions only (is_current=True). Supports filtering by tooth_num and overriding is_current.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
is_current
string
Enum: "all" "false"

Filter by current status. Defaults to current-only. Accepts false to return non-current conditions, or all to return every condition.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

tooth_num
string

Filter by tooth number (Universal Numbering System, e.g. 14).

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_clinical_tooth_create

List and create tooth conditions for a patient.

Defaults to current conditions only (is_current=True). Supports filtering by tooth_num and overriding is_current.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
tooth_num
required
string [ 1 .. 5 ] characters

Universal numbering: 1-32 (permanent), A-T (primary)

condition
required
string (ConditionEnum)
Enum: "missing" "implant" "crown" "bridge_abutment" "bridge_pontic" "veneer" "root_canal" "extraction_planned" "impacted" "unerupted" "supernumerary" "deciduous" "denture" "partial_denture" "caries" "filling" "sealant" "fracture" "watch"
  • missing - Missing
  • implant - Implant
  • crown - Crown
  • bridge_abutment - Bridge Abutment
  • bridge_pontic - Bridge Pontic
  • veneer - Veneer
  • root_canal - Root Canal
  • extraction_planned - Extraction Planned
  • impacted - Impacted
  • unerupted - Unerupted
  • supernumerary - Supernumerary
  • deciduous - Deciduous / Primary
  • denture - Denture
  • partial_denture - Partial Denture
  • caries - Caries
  • filling - Filling
  • sealant - Sealant
  • fracture - Fracture
  • watch - Watch
dentition
string (DentitionEnum)
Enum: "permanent" "primary"
  • permanent - Permanent
  • primary - Primary
surfaces
string <= 10 characters

Affected surfaces: M, O, D, B/F, L, I (e.g. 'MOD')

material
string <= 50 characters

e.g. PFM, zirconia, amalgam, composite

note
string
date_identified
string or null <date>
is_current
boolean

False = historical condition superseded by a newer one

custom_data
any

Responses

Request samples

Content type
{
  • "tooth_num": "strin",
  • "condition": "missing",
  • "dentition": "permanent",
  • "surfaces": "string",
  • "material": "string",
  • "note": "string",
  • "date_identified": "2019-08-24",
  • "is_current": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "tooth_num": "strin",
  • "condition": "missing",
  • "dentition": "permanent",
  • "surfaces": "string",
  • "material": "string",
  • "note": "string",
  • "date_identified": "2019-08-24",
  • "is_current": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_tooth_summary_retrieve

Aggregated tooth chart for the odontogram.

Returns all current conditions grouped by tooth number. Response: {"teeth": {"1": [conditions...], "14": [conditions...]}}

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

practice_patient_clinical_treatment_plan_list

List and create treatment plans for a patient.

Supports filtering by status.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

status
string
Enum: "accepted" "active" "archived" "completed" "declined"

Filter by treatment plan status.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_clinical_treatment_plan_create

List and create treatment plans for a patient.

Supports filtering by status.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
provider
string or null <uuid>
name
required
string [ 1 .. 200 ] characters
note
string
status
string (TreatmentPlanStatusEnum)
Enum: "active" "accepted" "declined" "completed" "archived"
  • active - Active
  • accepted - Accepted
  • declined - Declined
  • completed - Completed
  • archived - Archived
date_accepted
string or null <date>
custom_data
any
Array of objects (TreatmentPlanItemWriteRequest)

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "name": "string",
  • "note": "string",
  • "status": "active",
  • "date_accepted": "2019-08-24",
  • "custom_data": null,
  • "items": [
    ]
}

Response samples

Content type
application/json
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "name": "string",
  • "note": "string",
  • "status": "active",
  • "date_accepted": "2019-08-24",
  • "custom_data": null,
  • "items": [
    ]
}

practice_patient_clinical_treatment_plan_accept_create

Accept a treatment plan. Sets status=accepted and date_accepted=today.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_clinical_treatment_plan_decline_create

Decline a treatment plan. Sets status=declined.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_clinical_treatment_plan_estimate_create

Estimate insurance benefits for all items in a treatment plan.

Calls the insurance estimation service with all plan items as a batch so deductible and annual max accumulate correctly across lines. Persists the results back to each TreatmentPlanItem and returns the updated plan.

POST /patient/{patient_id}/clinical/treatment-plan/{pk}/estimate/ Optional body: {"explain": true} for step-by-step calculation details.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_clinical_treatment_plan_schedule_create

Create an appointment from treatment plan items.

POST accepts: provider, operatory, date_time, duration_minutes, item_ids (optional). If item_ids is omitted, all plan items are scheduled.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_clinical_vital_sign_list

List and create vital sign readings for a patient.

Supports filtering by appointment and date range. Ordered by most recent reading first.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
appointment
string <uuid>

Filter readings to a single appointment UUID.

date_from
string <date>

Inclusive lower bound on reading_date (ISO 8601 date). Interpreted in the practice's local timezone.

date_to
string <date>

Inclusive upper bound on reading_date (ISO 8601 date). Interpreted in the practice's local timezone.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_clinical_vital_sign_create

List and create vital sign readings for a patient.

Supports filtering by appointment and date range. Ordered by most recent reading first.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
appointment
string or null <uuid>
provider
string or null <uuid>
reading_date
required
string <date-time>

When the vitals were taken

bp_systolic
integer or null [ 0 .. 32767 ]

Systolic blood pressure (mmHg)

bp_diastolic
integer or null [ 0 .. 32767 ]

Diastolic blood pressure (mmHg)

pulse
integer or null [ 0 .. 32767 ]

Pulse rate (bpm)

respiration
integer or null [ 0 .. 32767 ]

Respiration rate (breaths/min)

o2_saturation
integer or null [ 0 .. 32767 ]

Oxygen saturation (%)

temperature
string or null <decimal> ^-?\d{0,3}(?:\.\d{0,1})?$

Temperature (F)

note
string
custom_data
any

Responses

Request samples

Content type
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "reading_date": "2019-08-24T14:15:22Z",
  • "bp_systolic": 32767,
  • "bp_diastolic": 32767,
  • "pulse": 32767,
  • "respiration": 32767,
  • "o2_saturation": 32767,
  • "temperature": "string",
  • "note": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "reading_date": "2019-08-24T14:15:22Z",
  • "bp_systolic": 32767,
  • "bp_diastolic": 32767,
  • "pulse": 32767,
  • "respiration": 32767,
  • "o2_saturation": 32767,
  • "temperature": "string",
  • "note": "string",
  • "custom_data": null
}

Insurance

Carriers, plans, benefits, fee schedules, claims, estimation

practice_insurance_carrier_list

List and create insurance carriers for a practice.

Uses :class:ReferenceDataPagination (100/2000) instead of the default 20/100 cap because the web UI loads the full carrier catalog once for local typeahead on plan / fee-schedule / claim forms. A group practice with years of imported history can easily carry hundreds of (mostly inactive) carriers. See api#194.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
active
string
Value: "true"

Filter by active status. Only true is honored -- when supplied, inactive carriers are hidden. Omit to return every carrier regardless of status.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

search
string

Case-insensitive substring search on name.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_insurance_carrier_create

List and create insurance carriers for a practice.

Uses :class:ReferenceDataPagination (100/2000) instead of the default 20/100 cap because the web UI loads the full carrier catalog once for local typeahead on plan / fee-schedule / claim forms. A group practice with years of imported history can easily carry hundreds of (mostly inactive) carriers. See api#194.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 255 ] characters
phone
string <= 20 characters
website
string <uri> <= 200 characters
address_line1
string <= 255 characters
address_line2
string <= 255 characters
city
string <= 100 characters
state
string <= 2 characters
zip_code
string <= 10 characters
payer_id
string <= 50 characters

EDI payer ID for clearinghouse submission

claim_office_id
string <= 50 characters

Separate claim submission office ID

hpid
string <= 50 characters

Health Plan Identifier

payment_source
string <= 50 characters

check, eft, virtual_card

notes
string
is_active
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "phone": "string",
  • "website": "http://example.com",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "payer_id": "string",
  • "claim_office_id": "string",
  • "hpid": "string",
  • "payment_source": "string",
  • "notes": "string",
  • "is_active": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "phone": "string",
  • "website": "http://example.com",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "payer_id": "string",
  • "claim_office_id": "string",
  • "hpid": "string",
  • "payment_source": "string",
  • "notes": "string",
  • "is_active": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_insurance_claim_list

Practice-wide claims list with filtering. For the claims management page.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
date_from
string <date>

Inclusive lower bound on date_service (ISO 8601 date, e.g. 2025-01-15).

date_to
string <date>

Inclusive upper bound on date_service (ISO 8601 date).

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

provider
string <uuid>

Filter claims by the rendering provider UUID.

search
string

Case-insensitive substring search across the patient's first_name and last_name.

status
string
Enum: "accepted" "appealed" "denied" "draft" "imported" "paid" "partial" "rejected" "resubmitted" "submitted" "void"

Filter claims by their current state-machine status.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_insurance_claims_summary_retrieve

Aggregate claims counts and dollar amounts grouped by status.

Returns per-status breakdowns (count, total_fee, total_paid) and practice-wide totals including outstanding balance.

GET /practice//insurance/claims/summary/

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

practice_insurance_fee_schedule_list

List and create fee schedules for a practice.

Uses :class:ReferenceDataPagination (100/2000) instead of the default 20/100 cap because the web UI loads the full fee-schedule catalog once for local dropdown rendering on insurance / plan admin screens. See api#194.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
carrier
string <uuid>

Filter fee schedules by the associated insurance carrier UUID.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

search
string

Case-insensitive substring search across name, carrier__name, and notes.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_insurance_fee_schedule_create

List and create fee schedules for a practice.

Uses :class:ReferenceDataPagination (100/2000) instead of the default 20/100 cap because the web UI loads the full fee-schedule catalog once for local dropdown rendering on insurance / plan admin screens. See api#194.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
carrier
string or null <uuid>
name
required
string [ 1 .. 255 ] characters
effective_date
string or null <date>
expiration_date
string or null <date>
notes
string
custom_data
any

Responses

Request samples

Content type
{
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "name": "string",
  • "effective_date": "2019-08-24",
  • "expiration_date": "2019-08-24",
  • "notes": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "carrier_name": "string",
  • "name": "string",
  • "effective_date": "2019-08-24",
  • "expiration_date": "2019-08-24",
  • "notes": "string",
  • "entry_count": 0,
  • "entries": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_insurance_fee_schedule_entry_bulk_create

Bulk create/update fee schedule entries. Accepts a list of {proc_code, allowed_amount, description?}.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
fee_schedule_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
proc_code
required
string [ 1 .. 20 ] characters
allowed_amount
required
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
description
string <= 255 characters

Override description, falls back to ProcedureCode

custom_data
any

Responses

Request samples

Content type
{
  • "proc_code": "string",
  • "allowed_amount": "string",
  • "description": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "proc_code": "string",
  • "allowed_amount": "string",
  • "description": "string",
  • "custom_data": null
}

practice_insurance_patient_insurance_list

Practice-wide patient-insurance list and bulk create.

GET returns all PatientInsurance records for the practice (paginated, filterable by patient, carrier, ordinal). POST accepts a JSON array for bulk import (up to 5000 records). Each record must include patient since the endpoint is not patient-scoped. PATCH accepts a JSON array of {id, ...} objects for bulk update.

Carrier resolution: if a POSTed record includes carrier_name but no carrier FK, the serializer resolves-or-creates an :class:InsuranceCarrier row in the current practice (case-insensitive match on name) and links the enrollment to it. This replaces the previous behavior where sync tools had to pre-create carriers themselves.

Used by escape-eaglesoft and escape-opendental sync tools to avoid the per-patient loop against patient/<uid>/insurance/plan/.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
carrier
string <uuid>

Filter enrollments by the associated insurance carrier UUID.

ordinal
integer

Filter by coverage ordinal. 1 = primary coverage, 2 = secondary coverage. Higher values are accepted for practices that track tertiary+ coverage.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

patient
string <uuid>

Filter enrollments down to a single patient by patient UUID.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_insurance_patient_insurance_create

Practice-wide patient-insurance list and bulk create.

GET returns all PatientInsurance records for the practice (paginated, filterable by patient, carrier, ordinal). POST accepts a JSON array for bulk import (up to 5000 records). Each record must include patient since the endpoint is not patient-scoped. PATCH accepts a JSON array of {id, ...} objects for bulk update.

Carrier resolution: if a POSTed record includes carrier_name but no carrier FK, the serializer resolves-or-creates an :class:InsuranceCarrier row in the current practice (case-insensitive match on name) and links the enrollment to it. This replaces the previous behavior where sync tools had to pre-create carriers themselves.

Used by escape-eaglesoft and escape-opendental sync tools to avoid the per-patient loop against patient/<uid>/insurance/plan/.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
patient
required
string <uuid>
insurance_plan
string or null <uuid>
carrier_name
required
string [ 1 .. 255 ] characters
carrier
string or null <uuid>
fee_schedule
string or null <uuid>

Fee schedule used for benefit estimation under this plan

group_number
string <= 100 characters
subscriber_id
string <= 100 characters
subscriber_name
string <= 255 characters

Policy holder name if different from patient

ordinal
integer [ 0 .. 32767 ]

1=primary, 2=secondary

RelationshipToSubscriberEnum (string) or BlankEnum (any)
effective_date
string or null <date>
termination_date
string or null <date>
custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "carrier_name": "string",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "group_number": "string",
  • "subscriber_id": "string",
  • "subscriber_name": "string",
  • "ordinal": 32767,
  • "relationship_to_subscriber": "self",
  • "effective_date": "2019-08-24",
  • "termination_date": "2019-08-24",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "carrier_name": "string",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "group_number": "string",
  • "subscriber_id": "string",
  • "subscriber_name": "string",
  • "ordinal": 32767,
  • "relationship_to_subscriber": "self",
  • "effective_date": "2019-08-24",
  • "termination_date": "2019-08-24",
  • "custom_data": null
}

practice_insurance_plan_list

List and create insurance plans for a practice. Supports bulk create (POST array) and bulk update (PATCH array).

Uses :class:ReferenceDataPagination (100/2000) instead of the default 20/100 cap because the web UI loads the full plan catalog once for local typeahead on patient-insurance, verification, and claim forms. Practices routinely accumulate thousands of employer/plan combinations over the lifetime of the office. See api#194.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
active
string
Value: "true"

Filter by active status. Only true is honored -- when supplied, inactive plans are hidden. Omit to return every plan regardless of status.

carrier
string <uuid>

Filter plans by the associated insurance carrier UUID.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

search
string

Case-insensitive substring search across plan_name, group_name, employer_name, and group_number.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_insurance_plan_create

List and create insurance plans for a practice. Supports bulk create (POST array) and bulk update (PATCH array).

Uses :class:ReferenceDataPagination (100/2000) instead of the default 20/100 cap because the web UI loads the full plan catalog once for local typeahead on patient-insurance, verification, and claim forms. Practices routinely accumulate thousands of employer/plan combinations over the lifetime of the office. See api#194.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
carrier
string or null <uuid>
plan_name
string <= 255 characters
group_name
string <= 255 characters
group_number
string <= 100 characters
employer_name
string <= 255 characters
PlanTypeEnum (string) or BlankEnum (any)
annual_maximum
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
individual_deductible
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
family_deductible
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
plan_year_begin_month
integer or null [ 0 .. 32767 ]

Month (1-12) when the plan year resets

fee_schedule
string or null <uuid>

Carrier-specific fee schedule (allowed amounts) for this plan

notes
string
is_active
boolean
Array of objects (InsuranceBenefitWriteRequest)
custom_data
any

Responses

Request samples

Content type
{
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "plan_name": "string",
  • "group_name": "string",
  • "group_number": "string",
  • "employer_name": "string",
  • "plan_type": "ppo",
  • "annual_maximum": "string",
  • "individual_deductible": "string",
  • "family_deductible": "string",
  • "plan_year_begin_month": 32767,
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "notes": "string",
  • "is_active": true,
  • "benefits": [
    ],
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "carrier_name": "string",
  • "plan_name": "string",
  • "group_name": "string",
  • "group_number": "string",
  • "employer_name": "string",
  • "plan_type": "ppo",
  • "annual_maximum": "string",
  • "individual_deductible": "string",
  • "family_deductible": "string",
  • "plan_year_begin_month": 32767,
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "notes": "string",
  • "is_active": true,
  • "benefits": [
    ],
  • "enrollment_count": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_insurance_plan_bulk_partial_update

Handle PATCH on the list endpoint for bulk updates.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
carrier
string or null <uuid>
plan_name
string <= 255 characters
group_name
string <= 255 characters
group_number
string <= 100 characters
employer_name
string <= 255 characters
PlanTypeEnum (string) or BlankEnum (any)
annual_maximum
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
individual_deductible
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
family_deductible
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
plan_year_begin_month
integer or null [ 0 .. 32767 ]

Month (1-12) when the plan year resets

fee_schedule
string or null <uuid>

Carrier-specific fee schedule (allowed amounts) for this plan

notes
string
is_active
boolean
Array of objects (InsuranceBenefitWriteRequest)
custom_data
any

Responses

Request samples

Content type
{
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "plan_name": "string",
  • "group_name": "string",
  • "group_number": "string",
  • "employer_name": "string",
  • "plan_type": "ppo",
  • "annual_maximum": "string",
  • "individual_deductible": "string",
  • "family_deductible": "string",
  • "plan_year_begin_month": 32767,
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "notes": "string",
  • "is_active": true,
  • "benefits": [
    ],
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "carrier_name": "string",
  • "plan_name": "string",
  • "group_name": "string",
  • "group_number": "string",
  • "employer_name": "string",
  • "plan_type": "ppo",
  • "annual_maximum": "string",
  • "individual_deductible": "string",
  • "family_deductible": "string",
  • "plan_year_begin_month": 32767,
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "notes": "string",
  • "is_active": true,
  • "benefits": [
    ],
  • "enrollment_count": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_insurance_plan_benefit_list

List benefits attached to a specific insurance plan. Scope is fixed by the plan_id path parameter; the filter set is intentionally empty -- narrow the result set by choosing a different plan rather than by query string. Standard page / page_size pagination applies.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
plan_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_insurance_plan_benefit_create

List and create benefits for an insurance plan.

Uses :class:ReferenceDataPagination (100/2000) instead of the default 20/100 cap because the web UI fetches every benefit for a plan in one request to render the full coverage grid (per-category + per-procedure overrides). Imported plans from legacy PMS can carry hundreds of benefit rows per plan. See api#194.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
plan_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
insurance_plan
string or null <uuid>
BenefitTypeEnum (string) or BlankEnum (any)
CoverageCategoryEnum (string) or BlankEnum (any)
percent
string <decimal> ^-?\d{0,3}(?:\.\d{0,2})?$
monetary_amt
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
TimePeriodEnum (string) or BlankEnum (any)
proc_code
string <= 20 characters

Benefit tied to a specific procedure code

procedure_code
string or null <uuid>
min_age
integer or null [ 0 .. 32767 ]

Minimum patient age (inclusive) for this benefit to apply

max_age
integer or null [ 0 .. 32767 ]

Maximum patient age (inclusive) for this benefit to apply

waiting_period_months
integer or null [ 0 .. 32767 ]

Months from effective date before this benefit is available

custom_data
any

Responses

Request samples

Content type
{
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "benefit_type": "percentage",
  • "coverage_category": "diagnostic",
  • "percent": "string",
  • "monetary_amt": "string",
  • "time_period": "calendar_year",
  • "proc_code": "string",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "min_age": 32767,
  • "max_age": 32767,
  • "waiting_period_months": 32767,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "benefit_type": "percentage",
  • "coverage_category": "diagnostic",
  • "percent": "string",
  • "monetary_amt": "string",
  • "time_period": "calendar_year",
  • "proc_code": "string",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "min_age": 32767,
  • "max_age": 32767,
  • "waiting_period_months": 32767,
  • "custom_data": null
}

practice_insurance_verification_list

List and create insurance verifications for a practice.

Filters (all optional, combinable):

  • patient -- UUID
  • insurance_plan -- UUID
  • verified_between -- from,to ISO 8601 datetimes (inclusive)

Emits insurance.verification_viewed on GET and insurance.verification_created on POST.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
insurance_plan
string <uuid>

Filter verifications by the associated insurance plan UUID.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

patient
string <uuid>

Filter verifications down to a single patient by patient UUID.

verified_between
string

Restrict results to verifications whose verified_at falls inside a comma-separated ISO 8601 datetime range, e.g. 2026-04-01T00:00:00Z,2026-04-23T23:59:59Z. Both bounds are inclusive; omit this filter to retrieve every verification.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_insurance_verification_create

Record a new insurance verification. Verifications are append-only: this endpoint has no PUT/PATCH/DELETE counterpart. Re-verifying coverage creates a new row so the audit trail of what the payer said, and when, is preserved.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
patient
required
string <uuid>
insurance_plan
required
string <uuid>
verified_at
required
string <date-time>

When the verification was obtained from the payer / portal.

source
required
string (InsuranceVerificationSourceEnum)
Enum: "phone" "portal" "clearinghouse"
  • phone - Phone
  • portal - Portal
  • clearinghouse - Clearinghouse
raw_response
any

Raw payer/clearinghouse/portal blob (270/271, screen scrape, etc).

annual_max
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Annual maximum benefit in dollars, if quoted. NULL = not provided.

deductible_total
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Total deductible for the plan year, if quoted. NULL = not provided.

deductible_met
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Portion of the deductible already met, if quoted. NULL = not provided.

waiting_period_notes
string

Free-text notes on waiting periods (e.g. 'major services 6mo WP remaining').

frequency_limits
any

Structured frequency limitations, e.g. {'D1110': '2 per calendar year'}. Defaults to empty dict so callers can merge without None-checks.

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "verified_at": "2019-08-24T14:15:22Z",
  • "source": "phone",
  • "raw_response": null,
  • "annual_max": "string",
  • "deductible_total": "string",
  • "deductible_met": "string",
  • "waiting_period_notes": "string",
  • "frequency_limits": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "verified_by": "8c493be0-efe2-4a3e-bdbd-7af0eab50aa2",
  • "verified_at": "2019-08-24T14:15:22Z",
  • "source": "phone",
  • "raw_response": null,
  • "annual_max": "string",
  • "deductible_total": "string",
  • "deductible_met": "string",
  • "waiting_period_notes": "string",
  • "frequency_limits": null,
  • "plan": {
    },
  • "patient_summary": {
    },
  • "verified_by_summary": {
    },
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_patient_insurance_claim_list

Insurance claims for a patient. POST to create a new claim in draft status.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

status
string
Enum: "accepted" "appealed" "denied" "draft" "imported" "paid" "partial" "rejected" "resubmitted" "submitted" "void"

Filter claims by their current state-machine status.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_insurance_claim_create

Insurance claims for a patient. POST to create a new claim in draft status.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
provider
string or null <uuid>
patient_insurance
string or null <uuid>
date_service
string or null <date>
date_sent
string or null <date>
claim_fee
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
ins_pay_est
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
ins_pay_amt
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
ded_applied
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
write_off
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
Array of objects (ClaimProcedureWriteRequest)
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "patient_insurance": "e396a8de-c249-4467-871f-c8b5f28219f1",
  • "date_service": "2019-08-24",
  • "date_sent": "2019-08-24",
  • "claim_fee": "string",
  • "ins_pay_est": "string",
  • "ins_pay_amt": "string",
  • "ded_applied": "string",
  • "write_off": "string",
  • "procedures": [
    ],
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "patient_insurance": "e396a8de-c249-4467-871f-c8b5f28219f1",
  • "date_service": "2019-08-24",
  • "date_sent": "2019-08-24",
  • "claim_fee": "string",
  • "ins_pay_est": "string",
  • "ins_pay_amt": "string",
  • "ded_applied": "string",
  • "write_off": "string",
  • "procedures": [
    ],
  • "custom_data": null
}

practice_patient_insurance_claim_transition_create

Transition a claim's status through the state machine.

POST /practice//patient//insurance/claim//transition/ Body: {"new_status": "submitted", "note": "Sent to Delta Dental"}

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
claim_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
new_status
required
string (ClaimStatusEnum)
Enum: "draft" "submitted" "accepted" "rejected" "resubmitted" "paid" "partial" "denied" "appealed" "void" "imported"
  • draft - Draft
  • submitted - Submitted
  • accepted - Accepted
  • rejected - Rejected
  • resubmitted - Resubmitted
  • paid - Paid
  • partial - Partially Paid
  • denied - Denied
  • appealed - Appealed
  • void - Void
  • imported - Imported
note
string
Default: ""

Responses

Request samples

Content type
{
  • "new_status": "draft",
  • "note": ""
}

Response samples

Content type
application/json
{
  • "new_status": "draft",
  • "note": ""
}

practice_patient_insurance_estimate_create

Estimate insurance coverage for proposed procedures.

POST /practice/{uid}/patient/{patient_id}/insurance/estimate/ Body: { "procedures": [{ "proc_code": "D2391", "fee": "450.00" }] }

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_insurance_estimate_explain_create

Verbose step-by-step insurance estimation with explanation.

POST /practice/{uid}/patient/{patient_id}/insurance/estimate-explain/ Body: { "procedures": [{ "proc_code": "D2391", "fee": "450.00" }] }

Returns the same structure as the standard estimate endpoint, plus an 'explanation' key containing global and per-line calculation steps.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_insurance_plan_list

List a patient's insurance enrollments (PatientInsurance rows). Scope is fixed by the patient_id path parameter; the filter set is intentionally empty -- use the practice-wide endpoint (/insurance/patient-insurance/) if cross-patient filtering is required. Standard page / page_size pagination applies.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_insurance_plan_create

List and create insurance plans for a patient.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
insurance_plan
string or null <uuid>
carrier_name
required
string [ 1 .. 255 ] characters
carrier
string or null <uuid>
fee_schedule
string or null <uuid>

Fee schedule used for benefit estimation under this plan

group_number
string <= 100 characters
subscriber_id
string <= 100 characters
subscriber_name
string <= 255 characters

Policy holder name if different from patient

ordinal
integer [ 0 .. 32767 ]

1=primary, 2=secondary

RelationshipToSubscriberEnum (string) or BlankEnum (any)
effective_date
string or null <date>
termination_date
string or null <date>
custom_data
any

Responses

Request samples

Content type
{
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "carrier_name": "string",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "group_number": "string",
  • "subscriber_id": "string",
  • "subscriber_name": "string",
  • "ordinal": 32767,
  • "relationship_to_subscriber": "self",
  • "effective_date": "2019-08-24",
  • "termination_date": "2019-08-24",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "carrier_name": "string",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "group_number": "string",
  • "subscriber_id": "string",
  • "subscriber_name": "string",
  • "ordinal": 32767,
  • "relationship_to_subscriber": "self",
  • "effective_date": "2019-08-24",
  • "termination_date": "2019-08-24",
  • "custom_data": null
}

practice_patient_insurance_plan_benefit_list

List benefits attached to a patient's insurance enrollment. Scope is fixed by the patient_id and plan_id path parameters; the filter set is intentionally empty -- all relevant narrowing is already expressed by the URL. Standard page / page_size pagination applies.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_insurance_plan_benefit_create

List and create benefits for a patient insurance plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
insurance_plan
string or null <uuid>
BenefitTypeEnum (string) or BlankEnum (any)
CoverageCategoryEnum (string) or BlankEnum (any)
percent
string <decimal> ^-?\d{0,3}(?:\.\d{0,2})?$
monetary_amt
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
TimePeriodEnum (string) or BlankEnum (any)
proc_code
string <= 20 characters

Benefit tied to a specific procedure code

procedure_code
string or null <uuid>
min_age
integer or null [ 0 .. 32767 ]

Minimum patient age (inclusive) for this benefit to apply

max_age
integer or null [ 0 .. 32767 ]

Maximum patient age (inclusive) for this benefit to apply

waiting_period_months
integer or null [ 0 .. 32767 ]

Months from effective date before this benefit is available

custom_data
any

Responses

Request samples

Content type
{
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "benefit_type": "percentage",
  • "coverage_category": "diagnostic",
  • "percent": "string",
  • "monetary_amt": "string",
  • "time_period": "calendar_year",
  • "proc_code": "string",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "min_age": 32767,
  • "max_age": 32767,
  • "waiting_period_months": 32767,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "benefit_type": "percentage",
  • "coverage_category": "diagnostic",
  • "percent": "string",
  • "monetary_amt": "string",
  • "time_period": "calendar_year",
  • "proc_code": "string",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "min_age": 32767,
  • "max_age": 32767,
  • "waiting_period_months": 32767,
  • "custom_data": null
}

Billing

Balances, payments, adjustments, checkout, production reports

client_billing_portal_session_create

Mint a Stripe-hosted billing portal session for the caller's Client.

POST /api/v1/client//billing/portal-session/

The Stripe billing portal lets customers update their payment method, download past invoices, and cancel / resume their subscription. Letting Stripe host the surface is the standard self-service pattern and keeps PCI scope at SAQ-A.

Permissions: the caller must hold a membership on the target Client (direct ClientMembership or via a PracticeMembership on one of the Client's practices). Cross-tenant UID guesses get a 404 so we never leak Client existence.

No PHI is sent to Stripe (the existing ensure_customer helper only ships the business name + client_uid metadata). The signed portal URL is not audit-logged because it carries a single-use token; we record the create event with the Client + return_url only.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_uid
required
string <uuid>
Request Body schema:
return_url
string <uri> non-empty

Responses

Request samples

Content type
{}

Response samples

Content type
application/json

practice_billing_adjustment_list

Practice-wide adjustment list (api#185).

Backs the Adjustments report (web#154). Supports date_from / date_to (inclusive, practice TZ), repeated provider and adj_type params, and an optional single patient filter. POST creates an adjustment with patient provided in the request body (the URL is not patient-scoped).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
adj_type
Array of strings

Filter by the free-text adj_type string. Repeat the parameter to include multiple types (?adj_type=discount&adj_type=writeoff).

date_from
string <date>

Inclusive lower bound on adj_date (YYYY-MM-DD, practice TZ). Omit to return adjustments with any date.

date_to
string <date>

Inclusive upper bound on adj_date (YYYY-MM-DD, practice TZ). Omit to return adjustments with any date.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

patient
string <uuid>

Filter adjustments to a single patient by patient UUID. Omit to return every adjustment across the practice.

provider
Array of strings <uuid> [ items <uuid > ]

Filter by provider UUID. Repeat the parameter to include multiple providers (?provider=<uid>&provider=<uid>).

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_billing_adjustment_create

Practice-wide adjustment list (api#185).

Backs the Adjustments report (web#154). Supports date_from / date_to (inclusive, practice TZ), repeated provider and adj_type params, and an optional single patient filter. POST creates an adjustment with patient provided in the request body (the URL is not patient-scoped).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
patient
required
string <uuid>
adj_date
string or null <date>
adj_amount
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
adj_type
string <= 100 characters
adj_note
string
provider
string or null <uuid>
custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "adj_date": "2019-08-24",
  • "adj_amount": "string",
  • "adj_type": "string",
  • "adj_note": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "adj_date": "2019-08-24",
  • "adj_amount": "string",
  • "adj_type": "string",
  • "adj_note": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "custom_data": null
}

practice_billing_payment_list

Practice-wide payment list. GET all payments, POST to create (patient in body).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
date_from
string <date>

Earliest pay_date to include (inclusive, YYYY-MM-DD).

date_to
string <date>

Latest pay_date to include (inclusive, YYYY-MM-DD).

method
Array of strings

Filter by payment-method bucket. Repeatable. One of cash/check/card/insurance/other; the server maps the bucket to the set of raw PMS pay_type strings (visa, mc, carecredit etc.).

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

patient
string <uuid>

Filter payments to a single patient by patient UUID. Omit to return every payment across the practice.

provider
Array of strings <uuid> [ items <uuid > ]

Filter by provider UUID. Repeatable — e.g. ?provider=<a>&provider=<b> narrows to payments booked against either provider.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_billing_payment_create

Practice-wide payment list. GET all payments, POST to create (patient in body).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
patient
required
string <uuid>
pay_date
string or null <date>
pay_amount
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
pay_type
string <= 100 characters
pay_note
string
provider
string or null <uuid>
custom_data
any
Array of objects (PaymentSplitWriteRequest)

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "pay_date": "2019-08-24",
  • "pay_amount": "string",
  • "pay_type": "string",
  • "pay_note": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "custom_data": null,
  • "splits": [
    ]
}

Response samples

Content type
application/json
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "pay_date": "2019-08-24",
  • "pay_amount": "string",
  • "pay_type": "string",
  • "pay_note": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "custom_data": null,
  • "splits": [
    ]
}

practice_billing_reports_aging_retrieve

A/R aging report — practice-wide summary, top 25 balances, plus by_provider and by_insurance breakdowns (api#303). Per-row bucket totals in the breakdowns reconcile with the summary because both reuse the same FIFO-allocated per-patient numbers.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
as_of_date
string <date>

Reference date for age calculation (YYYY-MM-DD, practice-local). Defaults to today. as_of is accepted as an alias.

include_archived
boolean

When true, include inactive patients in the aggregation. Defaults to false (active only).

Responses

Response samples

Content type
application/json
{
  • "summary": {
    },
  • "top_balances": [
    ],
  • "by_provider": [
    ],
  • "by_insurance": [
    ]
}

practice_billing_reports_aging_jobs_retrieve

Poll for an async aging report result.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

practice_billing_reports_aging_jobs_create

Kick off an async aging report computation.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_billing_reports_aging_jobs_retrieve_2

Poll for an async aging report result.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
as_of_date
required
string
practice_uid
required
string <uuid>

Responses

practice_billing_reports_aging_jobs_create_2

Kick off an async aging report computation.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
as_of_date
required
string
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_billing_reports_patient_balance_retrieve

GET practice-wide patient-balance report with aging buckets (api#152).

Backs the Patient Balance report UI (web#128). Returns one paginated row per patient with a non-trivial balance, each row carrying the four aging-bucket amounts (0-30 / 31-60 / 61-90 / over-90), the computed balance_total, last-payment metadata, and enough patient info for the table to render without a second round-trip.

Aging buckets are computed from live Procedure / PaymentRecord / Adjustment / InsuranceClaim data (not the stored :class:PatientBalance snapshot) so the as_of parameter is honored. Buckets start as gross completed charges in each age range and are then reduced oldest-first by the net of payments, adjustments, and insurance-paid amounts so the summed buckets always reconcile with balance_total — the convention every PMS aging report uses.

Query params: as_of (YYYY-MM-DD, default today) — reference date for ages bucket (0_30 | 31_60 | 61_90 | over_90) — post-allocation filter min_balance (decimal, default 0.01) — drops zero / credit balances provider (UUID) — restrict to patients with this primary provider carrier (UUID) — restrict to patients whose primary insurance PatientInsurance (ordinal=1) points at this carrier; malformed UUIDs return 400. Backs the A/R aging drill-down (web#327) for scoping by carrier. status (active | inactive | any, default active)

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
as_of
string <date>

Reference date for age calculation (YYYY-MM-DD, practice TZ). Defaults to today.

bucket
string

Filter to a single aging bucket after allocation. One of 0_30 / 31_60 / 61_90 / over_90. Returns only patients with a positive net balance in the named bucket.

carrier
string <uuid>

Restrict to patients whose primary insurance (PatientInsurance.ordinal=1) points at this InsuranceCarrier UUID. Malformed UUID returns 400. Backs the A/R aging drill-down (web#327).

min_balance
number <double>

Exclude rows whose balance_total is below this threshold. Defaults to 0.01.

provider
string <uuid>

Restrict to patients whose primary_provider matches this UUID.

status
string

Patient status filter: active (default) / inactive / any.

Responses

Response samples

Content type
application/json
{
  • "count": 0,
  • "next": "string",
  • "previous": "string",
  • "results": [
    ],
  • "summary": {
    }
}

practice_billing_reports_production_retrieve

GET production report aggregated across a date range.

Practice-scoped (not patient-scoped). Returns total production, collections, adjustments, net production, and procedure count — both as a summary and broken down by provider. Also exposes a per-procedure rollup (by_procedure) and splits scheduled_production vs completed_production on each by_provider row so the Production Report UI (web#151) can surface pipeline work alongside collected work.

Procedures tied to cancelled appointments are pulled out of every bucket — the same rule as the trending report in :mod:apps.billing.reports.

Query params: date_from (YYYY-MM-DD) — defaults to 30 days ago date_to (YYYY-MM-DD) — defaults to today provider (UUID, repeatable) — narrows the summary totals and the by_provider / by_procedure breakdowns; null-provider rows are excluded when the filter is active.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
date_from
required
string <date>

Start date (YYYY-MM-DD)

date_to
required
string <date>

End date (YYYY-MM-DD)

provider
Array of strings <uuid> [ items <uuid > ]

Filter to these providers only. Repeatable (?provider=<a>&provider=<b>). Narrows the summary totals and the by_provider / by_procedure breakdowns.

Responses

Response samples

Content type
application/json
{
  • "date_from": "string",
  • "date_to": "string",
  • "summary": {
    },
  • "by_provider": [
    ],
  • "by_procedure": [
    ]
}

practice_patient_billing_adjustment_list

Paginated adjustment history for a patient. Scope is fixed by the patient_id path parameter; the filter set is intentionally empty. Standard page / page_size pagination applies.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_billing_adjustment_create

Paginated adjustment history for a patient. POST to create a new adjustment.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
adj_date
string or null <date>
adj_amount
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
adj_type
string <= 100 characters
adj_note
string
provider
string or null <uuid>
custom_data
any

Responses

Request samples

Content type
{
  • "adj_date": "2019-08-24",
  • "adj_amount": "string",
  • "adj_type": "string",
  • "adj_note": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "adj_date": "2019-08-24",
  • "adj_amount": "string",
  • "adj_type": "string",
  • "adj_note": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "custom_data": null
}

practice_patient_billing_balance_summary_retrieve

GET computed balance from actual ledger data (not stored snapshot).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "total_charges": "string",
  • "total_payments": "string",
  • "total_adjustments": "string",
  • "insurance_paid": "string",
  • "insurance_estimate": "string",
  • "balance": "string"
}

practice_patient_billing_checkout_create

POST checkout/walkout — complete an appointment with procedures, payment, and optional claim.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
appointment_id
required
string <uuid>
required
Array of objects (CheckoutProcedureRequest)
object or null

Optional payment collected at checkout.

create_claim
boolean
Default: true

Responses

Request samples

Content type
{
  • "appointment_id": "21634f0d-2156-4d4b-a142-2e7c783a9212",
  • "procedures": [
    ],
  • "payment": {
    },
  • "create_claim": true
}

Response samples

Content type
application/json
{
  • "procedures_count": 0,
  • "payment_amount": "string",
  • "claim_id": "string",
  • "balance_summary": {
    }
}

practice_patient_billing_payment_list

Paginated payment history for a patient. Scope is fixed by the patient_id path parameter; the filter set is intentionally empty -- use the practice-wide endpoint (/billing/payment/) when cross-patient filtering is required. Standard page / page_size pagination applies.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_billing_payment_create

Paginated payment history for a patient. POST to create a new payment.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
pay_date
string or null <date>
pay_amount
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
pay_type
string <= 100 characters
pay_note
string
provider
string or null <uuid>
custom_data
any
Array of objects (PaymentSplitWriteRequest)

Responses

Request samples

Content type
{
  • "pay_date": "2019-08-24",
  • "pay_amount": "string",
  • "pay_type": "string",
  • "pay_note": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "custom_data": null,
  • "splits": [
    ]
}

Response samples

Content type
application/json
{
  • "pay_date": "2019-08-24",
  • "pay_amount": "string",
  • "pay_type": "string",
  • "pay_note": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "custom_data": null,
  • "splits": [
    ]
}

practice_patient_billing_payment_plan_list

Payment plans for a patient. Scope is fixed by the patient_id path parameter; the filter set is intentionally empty. Standard page / page_size pagination applies.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_billing_payment_plan_create

Payment plans for a patient. Unpaginated. POST to create a new plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
guarantor
string or null <uuid>
plan_date
string or null <date>
apr
string <decimal> ^-?\d{0,3}(?:\.\d{0,2})?$
completed_amt
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
is_closed
boolean
Array of objects (PaymentPlanChargeWriteRequest)
custom_data
any

Responses

Request samples

Content type
{
  • "guarantor": "2dc581b4-936d-4ab3-8a7d-1fc8f857bc6f",
  • "plan_date": "2019-08-24",
  • "apr": "string",
  • "completed_amt": "string",
  • "is_closed": true,
  • "charges": [
    ],
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "guarantor": "2dc581b4-936d-4ab3-8a7d-1fc8f857bc6f",
  • "plan_date": "2019-08-24",
  • "apr": "string",
  • "completed_amt": "string",
  • "is_closed": true,
  • "charges": [
    ],
  • "custom_data": null
}

Imaging

Sources, exam templates, exams, images, x-ray capture

practice_imaging_capture_token_create

Create a capture session and return a one-time token.

Called by the web app when staff clicks "Capture X-Rays". The token is passed to the desktop app via escape-xrays://capture?token=....

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

xrays_sessions_complete_create

Mark a capture session as complete.

Called by the desktop app when the user clicks "Complete". Sets Exam.is_complete = True.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
session_uid
required
string <uuid>

Responses

xrays_token_exchange_create

Exchange a one-time capture token for an OAuth2 access token.

Called by the desktop app after receiving the escape-xrays:// URL. No prior authentication is required — the token IS the auth.

Authorizations:
jwtAuthbearerAuthoauth2None

Responses

Documents

Document center, inbox, scan-to-email

desktop_documents_sessions_complete_create

Mark a desktop capture session as complete.

Called by the desktop app when the user clicks "Done".

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
session_uid
required
string <uuid>

Responses

desktop_documents_sessions_upload_create

Upload a document to a desktop capture session.

Called by the desktop app for each scanned/selected file. Files are stored as InboxItem rows on the session's practice with source=API and source_application pointing at the OAuth2 app that minted the upload token.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
session_uid
required
string <uuid>

Responses

desktop_documents_token_exchange_create

Exchange a one-time capture token for an OAuth2 access token.

Called by the desktop app after receiving the escape-documents:// URL. No prior authentication is required — the token IS the auth.

A token may only be exchanged once. Replay or expired tokens return 410 Gone and are audited via doccenter.upload_session_rejected.

Authorizations:
jwtAuthbearerAuthoauth2None

Responses

practice_doccenter_capture_token_create

Create a document capture session and return a one-time token.

Called by the web app when staff clicks "Scan Documents". The token is passed to the desktop app via escape-documents://capture?token=....

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_doccenter_document_list

List practice-level documents (no patient). Filter by ?category=.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
category
string <uuid>

Filter by document category UID. Categories are returned by GET /api/v1/practice/{practice_uid}/doccenter/category/ and include both system (practice is null) and practice-custom entries.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_doccenter_document_delete_destroy

Soft-delete a document (HIPAA retention).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
doc_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

Search documents by full-text content with highlights

Full-text search across document titles, descriptions, filenames, and OCR-extracted body text within a practice. Results are ranked by Elasticsearch relevance score and include highlighted snippets around matched terms.

HIPAA scoping — results are always restricted to the practice in the URL. Cross-practice leakage is a critical bug; the practice filter is enforced at the Elasticsearch query layer and cannot be bypassed via query parameters.

Pass patient_id to scope to a single patient (patient docs tab), or omit it for practice-wide search. Pass category (slug) to narrow to one document category.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
category
string

Optional category slug (e.g. insurance, referrals). Resolved against system + practice-custom categories.

page
integer

1-based page number for pagination.

page_size
integer

Page size (max 100, default 20).

patient_id
string <uuid>

Optional patient UID — narrows to one patient's documents.

q
required
string

Search query. Required. Must be at least 2 characters.

Responses

Response samples

Content type
application/json
{
  • "count": 0,
  • "next": "string",
  • "previous": "string",
  • "results": [
    ]
}

practice_doccenter_document_upload_create

Upload a practice-level document.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_doccenter_inbox_accept_create

Convert an inbox item to a permanent Document.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
inbox_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_doccenter_inbox_reject_destroy

Hard-delete an inbox item and its S3 file.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
inbox_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_doccenter_inbox_upload_create

Upload a file to the inbox.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_doccenter_scan_to_email_retrieve

GET: return config. POST: enable scan-to-email. DELETE: disable.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

practice_doccenter_scan_to_email_create

GET: return config. POST: enable scan-to-email. DELETE: disable.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_doccenter_scan_to_email_destroy

GET: return config. POST: enable scan-to-email. DELETE: disable.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

Voicemail inbox — un-linked voicemails with patient suggestions

Returns voicemail recordings (Document rows under the system voicemail category) for the practice, ranked with caller-ID patient suggestions. Default scope is unlinked — voicemails with patient is None. Operators confirm a suggestion via PATCH /doccenter/document/<doc_id>/ setting patient (the existing audit-emitting Document update endpoint).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

status
string
Enum: "all" "linked" "unlinked"

Filter by link state: unlinked (default — no patient yet), linked (already linked to a patient), or all.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

File a voicemail against the practice (resolve without a patient)

Marks the voicemail Document as resolved against the practice — it drops out of GET /doccenter/voicemail-inbox/ (default status=unlinked) without being deleted. Idempotent: re-posting on an already-resolved row refreshes the actor + timestamp. Reversible via DELETE.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
doc_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "category": "86d23d13-9dbb-46f3-82d0-25253c7750c3",
  • "title": "string",
  • "description": "string",
  • "original_filename": "string",
  • "mime_type": "string",
  • "file_size": 0,
  • "page_count": 0,
  • "uploaded_by": "e134ce2c-a199-4e99-9c11-627b70a7ff28",
  • "source_application": 0,
  • "is_deleted": true,
  • "deleted_at": "2019-08-24T14:15:22Z",
  • "deleted_by": "d7d7cfa2-327b-4733-8887-d09252b40b06",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolved_by": "d0d57369-b08b-4db8-8952-8cdeedd9aebc",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "download_url": "string",
  • "patient_name": "string",
  • "category_label": "string",
  • "uploaded_by_name": "string",
  • "caller_id": "string",
  • "processing_state": "pending",
  • "processing_error": "string",
  • "processing_updated_at": "2019-08-24T14:15:22Z",
  • "transcript": "string",
  • "transcript_confidence": "string",
  • "custom_data": null
}

Un-resolve a voicemail filed against the practice

Clears the resolved_at flag, returning the voicemail to the default unlinked queue. Used by the triage UI's undo affordance.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
doc_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "category": "86d23d13-9dbb-46f3-82d0-25253c7750c3",
  • "title": "string",
  • "description": "string",
  • "original_filename": "string",
  • "mime_type": "string",
  • "file_size": 0,
  • "page_count": 0,
  • "uploaded_by": "e134ce2c-a199-4e99-9c11-627b70a7ff28",
  • "source_application": 0,
  • "is_deleted": true,
  • "deleted_at": "2019-08-24T14:15:22Z",
  • "deleted_by": "d7d7cfa2-327b-4733-8887-d09252b40b06",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolved_by": "d0d57369-b08b-4db8-8952-8cdeedd9aebc",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "download_url": "string",
  • "patient_name": "string",
  • "category_label": "string",
  • "uploaded_by_name": "string",
  • "caller_id": "string",
  • "processing_state": "pending",
  • "processing_error": "string",
  • "processing_updated_at": "2019-08-24T14:15:22Z",
  • "transcript": "string",
  • "transcript_confidence": "string",
  • "custom_data": null
}

practice_patient_doccenter_list

List documents for a specific patient. Filter by ?category=.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
category
string <uuid>

Filter patient documents by category UID. Categories are returned by GET /api/v1/practice/{practice_uid}/doccenter/category/.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_doccenter_delete_destroy

Soft-delete a document (HIPAA retention).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
doc_id
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_doccenter_upload_create

Upload a document associated with a patient.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

Providers

Providers and operatories

practice_provider_list

List and create providers for a practice.

The list endpoint currently returns every provider for the practice without server-side filtering; clients (e.g. the staff web app) filter in-memory by is_active / is_hidden for dropdown rendering. If server-side filtering becomes a hot path, add explicit OpenApiParameter entries here so the schema stays honest.

Uses :class:ReferenceDataPagination (100/2000) instead of the default 20/100 cap because every staff surface (schedule, checkout, claim, chart) needs the full provider roster for local filtering. Historical imports can push a DSO's combined roster past the 100-row default. See api#194.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_provider_create

List and create providers for a practice.

The list endpoint currently returns every provider for the practice without server-side filtering; clients (e.g. the staff web app) filter in-memory by is_active / is_hidden for dropdown rendering. If server-side filtering becomes a hot path, add explicit OpenApiParameter entries here so the schema stays honest.

Uses :class:ReferenceDataPagination (100/2000) instead of the default 20/100 cap because every staff surface (schedule, checkout, claim, chart) needs the full provider roster for local filtering. Historical imports can push a DSO's combined roster past the 100-row default. See api#194.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
first_name
required
string [ 1 .. 100 ] characters
last_name
required
string [ 1 .. 100 ] characters
abbreviation
string <= 20 characters
specialty
string <= 100 characters
provider_type
string (ProviderTypeEnum)
Enum: "dentist" "hygienist" "assistant" "other"
  • dentist - Dentist
  • hygienist - Hygienist
  • assistant - Assistant
  • other - Other
color
string <= 7 characters

Hex color for calendar rendering, e.g. #3B82F6

npi
string <= 10 characters

National Provider Identifier

dea_number
string <= 9 characters

DEA registration number (2 letters + 7 digits, e.g. AB1234567). Required on paper controlled-substance prescriptions. Not required for non-controlled prescriptions. Added as part of the prescriptions module (escape#136 / api#482).

is_hidden
boolean

Hidden from dropdowns but visible on historical records

is_secondary
boolean

Legacy import field — use provider_type instead

is_active
boolean

Currently employed at this practice

is_web_sched
boolean

Available for patient online scheduling.

custom_data
any

Responses

Request samples

Content type
{
  • "first_name": "string",
  • "last_name": "string",
  • "abbreviation": "string",
  • "specialty": "string",
  • "provider_type": "dentist",
  • "color": "string",
  • "npi": "string",
  • "dea_number": "string",
  • "is_hidden": true,
  • "is_secondary": true,
  • "is_active": true,
  • "is_web_sched": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "first_name": "string",
  • "last_name": "string",
  • "abbreviation": "string",
  • "specialty": "string",
  • "provider_type": "dentist",
  • "color": "string",
  • "npi": "string",
  • "dea_number": "string",
  • "is_hidden": true,
  • "is_secondary": true,
  • "is_active": true,
  • "is_web_sched": true,
  • "custom_data": null
}

practice_provider_bulk_partial_update

Handle PATCH on the list endpoint for bulk updates.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
first_name
string [ 1 .. 100 ] characters
last_name
string [ 1 .. 100 ] characters
abbreviation
string <= 20 characters
specialty
string <= 100 characters
provider_type
string (ProviderTypeEnum)
Enum: "dentist" "hygienist" "assistant" "other"
  • dentist - Dentist
  • hygienist - Hygienist
  • assistant - Assistant
  • other - Other
color
string <= 7 characters

Hex color for calendar rendering, e.g. #3B82F6

npi
string <= 10 characters

National Provider Identifier

dea_number
string <= 9 characters

DEA registration number (2 letters + 7 digits, e.g. AB1234567). Required on paper controlled-substance prescriptions. Not required for non-controlled prescriptions. Added as part of the prescriptions module (escape#136 / api#482).

is_hidden
boolean

Hidden from dropdowns but visible on historical records

is_secondary
boolean

Legacy import field — use provider_type instead

is_active
boolean

Currently employed at this practice

is_web_sched
boolean

Available for patient online scheduling.

custom_data
any

Responses

Request samples

Content type
{
  • "first_name": "string",
  • "last_name": "string",
  • "abbreviation": "string",
  • "specialty": "string",
  • "provider_type": "dentist",
  • "color": "string",
  • "npi": "string",
  • "dea_number": "string",
  • "is_hidden": true,
  • "is_secondary": true,
  • "is_active": true,
  • "is_web_sched": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "first_name": "string",
  • "last_name": "string",
  • "abbreviation": "string",
  • "specialty": "string",
  • "provider_type": "dentist",
  • "color": "string",
  • "npi": "string",
  • "dea_number": "string",
  • "is_hidden": true,
  • "is_secondary": true,
  • "is_active": true,
  • "is_web_sched": true,
  • "custom_data": null
}

practice_provider_operatory_list

List and create operatories for a practice.

Returns every operatory for the practice; clients filter client-side for schedule rendering (is_hygiene, is_hidden, is_web_sched). Add OpenApiParameter entries here if server-side filters are introduced.

Uses :class:ReferenceDataPagination (100/2000) instead of the default 20/100 cap because the schedule grid needs every operatory (including hidden / legacy ones for historical appointment context) in one request. See api#194.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_provider_operatory_create

List and create operatories for a practice.

Returns every operatory for the practice; clients filter client-side for schedule rendering (is_hygiene, is_hidden, is_web_sched). Add OpenApiParameter entries here if server-side filters are introduced.

Uses :class:ReferenceDataPagination (100/2000) instead of the default 20/100 cap because the schedule grid needs every operatory (including hidden / legacy ones for historical appointment context) in one request. See api#194.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 100 ] characters
abbreviation
string <= 20 characters
provider_dentist
string or null <uuid>

Default dentist assigned to this chair

provider_hygienist
string or null <uuid>

Default hygienist assigned to this chair

is_hygiene
boolean
is_hidden
boolean
is_bookable
boolean

Operatories where is_bookable=False are skipped by the slot-finder. Used for PMS 'overflow' or 'notes-only' pseudo-chairs that host free-text annotations but aren't real rooms.

sort_order
integer [ 0 .. 2147483647 ]

Display ordering in schedule views

is_web_sched
boolean

Available for patient online scheduling

custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "abbreviation": "string",
  • "provider_dentist": "e47c6d02-29ee-4cef-ae75-7c7efebcc8cb",
  • "provider_hygienist": "cc1b609c-8966-4136-9bf1-9a022231718a",
  • "is_hygiene": true,
  • "is_hidden": true,
  • "is_bookable": true,
  • "sort_order": 2147483647,
  • "is_web_sched": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "abbreviation": "string",
  • "provider_dentist": "e47c6d02-29ee-4cef-ae75-7c7efebcc8cb",
  • "provider_dentist_name": "string",
  • "provider_hygienist": "cc1b609c-8966-4136-9bf1-9a022231718a",
  • "provider_hygienist_name": "string",
  • "is_hygiene": true,
  • "is_hidden": true,
  • "is_bookable": true,
  • "sort_order": 2147483647,
  • "is_web_sched": true,
  • "custom_data": null
}

practice_provider_operatory_bulk_partial_update

Handle PATCH on the list endpoint for bulk updates.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
name
string [ 1 .. 100 ] characters
abbreviation
string <= 20 characters
provider_dentist
string or null <uuid>

Default dentist assigned to this chair

provider_hygienist
string or null <uuid>

Default hygienist assigned to this chair

is_hygiene
boolean
is_hidden
boolean
is_bookable
boolean

Operatories where is_bookable=False are skipped by the slot-finder. Used for PMS 'overflow' or 'notes-only' pseudo-chairs that host free-text annotations but aren't real rooms.

sort_order
integer [ 0 .. 2147483647 ]

Display ordering in schedule views

is_web_sched
boolean

Available for patient online scheduling

custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "abbreviation": "string",
  • "provider_dentist": "e47c6d02-29ee-4cef-ae75-7c7efebcc8cb",
  • "provider_hygienist": "cc1b609c-8966-4136-9bf1-9a022231718a",
  • "is_hygiene": true,
  • "is_hidden": true,
  • "is_bookable": true,
  • "sort_order": 2147483647,
  • "is_web_sched": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "abbreviation": "string",
  • "provider_dentist": "e47c6d02-29ee-4cef-ae75-7c7efebcc8cb",
  • "provider_dentist_name": "string",
  • "provider_hygienist": "cc1b609c-8966-4136-9bf1-9a022231718a",
  • "provider_hygienist_name": "string",
  • "is_hygiene": true,
  • "is_hidden": true,
  • "is_bookable": true,
  • "sort_order": 2147483647,
  • "is_web_sched": true,
  • "custom_data": null
}

Staff

Practice members, invitations, roles

practice_staff_invitations_list

List or create practice invitations.

Returns every PracticeInvitation attached to the practice -- the staff UI filters by status (PENDING / ACCEPTED / REVOKED / EXPIRED) client- side. pagination_class = None keeps the response a flat array.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

practice_staff_invitations_create

List or create practice invitations.

Returns every PracticeInvitation attached to the practice -- the staff UI filters by status (PENDING / ACCEPTED / REVOKED / EXPIRED) client- side. pagination_class = None keeps the response a flat array.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
email
required
string <email> non-empty
role
required
string non-empty

Responses

Request samples

Content type
{
  • "email": "user@example.com",
  • "role": "string"
}

Response samples

Content type
application/json
{
  • "email": "user@example.com",
  • "role": "string"
}

practice_staff_invitations_revoke_create

Revoke a pending practice invitation.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
invitation_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_staff_members_list

List everyone with access to a practice.

Returns the union of:

  • every :class:PracticeMembership for the practice (direct members, active and deactivated alike), serialized with via_practice=True;
  • every :class:ClientMembership of the practice's parent client (organization-level admins -- OWNER / BILLING / TECHNICAL), serialized with via_client=True so the UI can tag the row with an "Inherited from organization" badge.

The two tables don't share a common id space, so the union happens at the serializer-output level rather than as a SQL UNION. The response stays a flat JSON array (pagination_class = None) so the staff UI can render the members table in one pass and the web usePracticeMembers hook can keep typing it as T[].

Dedup (api#570): when a user holds BOTH a PracticeMembership for this practice AND a ClientMembership for its parent client, only one row is emitted. The direct PracticeMembership row wins (its per- practice role is concrete and primary) and via_client=True is set on that row so the UI can still surface the "also has client-level access" signal. This prevents the duplicate row Aaron screenshotted in escapedental/escape#169.

Practice members are emitted first (sorted by display name), client-only members second (also sorted by display name). Display name is the user's full name with the email as a fallback, so ordering stays deterministic even before the user has filled in their profile.

Read access is open to any authenticated staff user with effective access to the practice -- including users whose only membership is at the client level (api#557). Mutating endpoints continue to gate on practice admin roles via :class:PracticeMemberDetailView.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

List per-practice user grants

Returns every :class:PracticeUserGrant row attached to the practice. Optional ?user=<uuid> and ?grant_type=<perm> filters narrow the result set; when both are supplied they are AND-ed. grant_type accepts the canonical permission string (e.g. patient.can_share, reports.production).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create a per-practice user grant

Adds a new grant for the given user + permission pair. The view sets practice from the URL and granted_by from the requesting user, so the body only carries the target user, the permission, an optional granted boolean (defaults True), and an optional free-text note. Returns the full grant on success.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
user
required
string <uuid>
permission
required
string (PermissionEnum)
Enum: "patient.can_share" "reports.all" "reports.production" "reports.ar" "reports.patients" "reports.operations" "reports.compliance"
  • patient.can_share - Patient: Can Share
  • reports.all - Reports: All Categories
  • reports.production - Reports: Production
  • reports.ar - Reports: A/R
  • reports.patients - Reports: Patients
  • reports.operations - Reports: Operations
  • reports.compliance - Reports: Compliance
granted
boolean
Default: true

True forces the permission ON; False forces it OFF.

note
string

Optional reason for the grant (e.g. 'covering for OM on leave').

Responses

Request samples

Content type
{
  • "user": "76f62a58-5404-486d-9afc-07bded328704",
  • "permission": "patient.can_share",
  • "granted": true,
  • "note": "string"
}

Response samples

Content type
application/json
{
  • "user": "76f62a58-5404-486d-9afc-07bded328704",
  • "permission": "patient.can_share",
  • "granted": true,
  • "note": "string"
}

Revoke a per-practice user grant

Permanently removes the grant row. The resolution helper in :mod:apps.sharing.permissions falls back to the role default once the row is gone, so a deleted grant returns the user to the role-default permission state.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
grant_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

Account

User profile, passkeys, preferences

account_invite_codes_list

List or mint invite codes.

GET Returns the codes attributed to the caller's accessible clients. Staff users may pass ?client=<uid> to scope to one specific Client; without the filter, staff see codes for every client they can access (and superusers see them all).

Paginated with the project default :class:`StandardPageNumberPagination`
(20 per page, ``?page_size=`` capped at 100, ``?page=N`` to walk
further pages).  The response is the standard DRF envelope:
``{count, next, previous, results}``.  See GH-463 — bulk staff-minted
codes will eventually outgrow a single page and the project rule is
"never remove backend pagination."

POST Staff-only. Body {"client": "<uid>"|null} -- a null/missing client mints a staff-bulk code that any sign-up can redeem.

Authorizations:
jwtAuthbearerAuthoauth2
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

account_invite_codes_create

List or mint invite codes.

GET Returns the codes attributed to the caller's accessible clients. Staff users may pass ?client=<uid> to scope to one specific Client; without the filter, staff see codes for every client they can access (and superusers see them all).

Paginated with the project default :class:`StandardPageNumberPagination`
(20 per page, ``?page_size=`` capped at 100, ``?page=N`` to walk
further pages).  The response is the standard DRF envelope:
``{count, next, previous, results}``.  See GH-463 — bulk staff-minted
codes will eventually outgrow a single page and the project rule is
"never remove backend pagination."

POST Staff-only. Body {"client": "<uid>"|null} -- a null/missing client mints a staff-bulk code that any sign-up can redeem.

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
client
string or null <uuid>

Responses

Request samples

Content type
{
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8"
}

Response samples

Content type
application/json
{
  • "code": "string",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "created_at": "2019-08-24T14:15:22Z"
}

account_invite_codes_revoke_create

Revoke an invite code.

Members of the issuer Client (or staff) may revoke a code. Returns 409 if the code is already revoked or already redeemed. Codes are looked up case-insensitively to match the redeem flow.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
code
required
string

Responses

account_invite_codes_validate_retrieve

Public invite-code validation -- no auth required.

Used by the sign-up form's pre-submit check (escape#127 / api#440). The response shape is intentionally minimal -- we never leak the issuer Client, the creator user, or the expiration date, just a boolean and a coarse error code so the form can render the right message.

Authorizations:
bearerAuthoauth2None

Responses

Response samples

Content type
application/json
{
  • "valid": true,
  • "error": "string"
}

account_me_retrieve

Return the authenticated user's own profile.

The new scope taxonomy (api#124) does not yet name a per-user "profile" scope, so this view continues to honour the legacy profile:read (or umbrella read) catalog entries via :class:HasScope's any_scope=True mode. Session / JWT auth bypasses the scope check; third-party OAuth tokens carrying neither scope receive 403 — which is the contract callers from before GH-387 were already coded against.

Authorizations:
jwtAuthbearerAuthoauth2

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "email": "user@example.com",
  • "first_name": "string",
  • "last_name": "string",
  • "is_patient": true,
  • "is_staff": true,
  • "is_superuser": true,
  • "is_active": true,
  • "date_joined": "2019-08-24T14:15:22Z",
  • "last_login": "2019-08-24T14:15:22Z",
  • "last_seen_at": "2019-08-24T14:15:22Z",
  • "first_run_tour_completed_at": "2019-08-24T14:15:22Z",
  • "preference_data": "string",
  • "memberships": [
    ],
  • "client_memberships": [
    ],
  • "max_session_hours": "string",
  • "current_practice_id": "edf1be34-8ae4-41f5-bad6-133af3513eac",
  • "practice_timezone": "string"
}

account_me_first_run_tour_complete_create

Mark the in-app first-run guided tour as completed for the caller.

POST /api/v1/account/me/first-run-tour/complete/ (GH-661).

Stamps :attr:User.first_run_tour_completed_at to now() the first time it's called for an account. Subsequent calls return 200 with the existing timestamp so the client can retry safely across flaky networks or two browser tabs racing the completion callback -- the column is a monotonic latch and never gets re-armed by this endpoint.

Scoped implicitly to request.user: there is no path parameter and the queryset is never widened, so a session for user A cannot flip the latch on user B's account.

Audits user.first_run_tour_completed (category auth) with metadata.already_completed set so operators can distinguish a genuine first-time completion from a redundant retry without pulling the row.

Authorizations:
jwtAuthbearerAuthoauth2

Responses

Response samples

Content type
application/json
{
  • "first_run_tour_completed_at": "2019-08-24T14:15:22Z",
  • "already_completed": true
}

account_me_preferences_retrieve

Read or write the authenticated user's preferences for the current OAuth2 application (the one the access token was issued to). The data blob is opaque to the API -- callers own its schema. For cross-application preferences such as theme, use /me/preferences/global/ instead.

Authorizations:
jwtAuthbearerAuthoauth2

Responses

Response samples

Content type
application/json

Per-OAuth2-application preferences are an opaque JSON blob from the API's perspective. Schema and key conventions are owned by the calling application; theme lives on the global row, not here.

{
  • "id": "11111111-1111-4111-8111-111111111111",
  • "data": {
    },
  • "created": "2026-04-25T14:30:00Z",
  • "modified": "2026-04-25T14:30:00Z"
}

account_me_preferences_update

Read or write the authenticated user's preferences for the current OAuth2 application (the one the access token was issued to). The data blob is opaque to the API -- callers own its schema. For cross-application preferences such as theme, use /me/preferences/global/ instead.

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
data
any

Responses

Request samples

Content type

PUT replaces the entire data object for the current OAuth2 application.

{
  • "data": {
    }
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "data": null,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

account_me_preferences_partial_update

Read or write the authenticated user's preferences for the current OAuth2 application (the one the access token was issued to). The data blob is opaque to the API -- callers own its schema. For cross-application preferences such as theme, use /me/preferences/global/ instead.

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
data
any

Responses

Request samples

Content type
{
  • "data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "data": null,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

account_me_preferences_destroy

Read or write the authenticated user's preferences for the current OAuth2 application (the one the access token was issued to). The data blob is opaque to the API -- callers own its schema. For cross-application preferences such as theme, use /me/preferences/global/ instead.

Authorizations:
jwtAuthbearerAuthoauth2

Responses

account_me_preferences_global_retrieve

Read or write the authenticated user's global preferences row (application=NULL). This row holds cross-application preferences such as the user's theme.

Documented keys on data:

  • theme -- one of light, dark, or system. Any other value (including missing) is treated as system when the value is read back, so the OS-level prefers-color-scheme setting wins. The web app and the Security Nexus both read and write this same key so a single user-facing toggle controls both surfaces.

Additional keys may be added by first-party clients over time and are preserved verbatim by PATCH; PUT replaces the object wholesale.

Authorizations:
jwtAuthbearerAuthoauth2

Responses

Response samples

Content type
application/json

Typical response for a user who has selected a non-default theme. The web app and the Security Nexus both read this row to render in the requested mode.

{
  • "id": "11111111-1111-4111-8111-111111111111",
  • "data": {
    },
  • "created": "2026-04-25T14:30:00Z",
  • "modified": "2026-04-25T14:30:00Z"
}

account_me_preferences_global_update

Read or write the authenticated user's global preferences row (application=NULL). This row holds cross-application preferences such as the user's theme.

Documented keys on data:

  • theme -- one of light, dark, or system. Any other value (including missing) is treated as system when the value is read back, so the OS-level prefers-color-scheme setting wins. The web app and the Security Nexus both read and write this same key so a single user-facing toggle controls both surfaces.

Additional keys may be added by first-party clients over time and are preserved verbatim by PATCH; PUT replaces the object wholesale.

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
data
any

Responses

Request samples

Content type

PUT replaces the entire data object. Allowed values for theme are light, dark, and system; any other value is treated as system when the theme is read back by the Nexus or the web app.

{
  • "data": {
    }
}

Response samples

Content type
application/json

Returned after a successful PUT or PATCH that updated the theme.

{
  • "id": "11111111-1111-4111-8111-111111111111",
  • "data": {
    },
  • "created": "2026-04-25T14:30:00Z",
  • "modified": "2026-04-25T14:31:12Z"
}

account_me_preferences_global_partial_update

Read or write the authenticated user's global preferences row (application=NULL). This row holds cross-application preferences such as the user's theme.

Documented keys on data:

  • theme -- one of light, dark, or system. Any other value (including missing) is treated as system when the value is read back, so the OS-level prefers-color-scheme setting wins. The web app and the Security Nexus both read and write this same key so a single user-facing toggle controls both surfaces.

Additional keys may be added by first-party clients over time and are preserved verbatim by PATCH; PUT replaces the object wholesale.

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
data
any

Responses

Request samples

Content type

PATCH shallow-merges into the existing data object, so other keys (locale, timezone, ...) on the global row are preserved. Allowed values for theme are light, dark, and system.

{
  • "data": {
    }
}

Response samples

Content type
application/json

Returned after a successful PUT or PATCH that updated the theme.

{
  • "id": "11111111-1111-4111-8111-111111111111",
  • "data": {
    },
  • "created": "2026-04-25T14:30:00Z",
  • "modified": "2026-04-25T14:31:12Z"
}

account_signup_create

Public self-service signup with optional invite-code gating (GH-440).

POST /api/v1/account/signup/ Body::

{
    "email": "owner@newpractice.test",
    "first_name": "Pat",
    "last_name": "Ient",
    "client_name": "New Practice DSO",
    "invite_code": "ABCDEFGH2345"   // optional unless flag is on
}

Behaviour

  • Always :class:AllowAny -- this is the entry point into the product for new tenants. Throttled by the project-wide anon scope so it can't be turned into a Client-creation cannon.

  • When the invited_signup_required Waffle flag is off for the request, invite_code is ignored -- a missing or invalid code does not block signup. This is the day-one default.

  • When the flag is on, invite_code is required and is atomically redeemed inside the same transaction that creates the User, Client, and ClientMembership. The redemption uses select_for_update (see :meth:InviteCode.redeem) so two simultaneous signups racing for the same code can't both win -- one gets the new account, the other gets a 400.

Atomic boundary

Everything happens inside a single transaction.atomic block:

  1. Create the new :class:apps.practices.models.Client.
  2. Create the new :class:User (passwordless -- the next step in the signup wizard is magic-link → passkey enrolment).
  3. Create the :class:ClientMembership with role OWNER.
  4. (When the flag is on) atomically redeem the invite code.

If step 4 raises -- e.g. someone revoked the code between pre-flight validation and the POST landing -- the whole transaction rolls back: no orphan Client, no orphan User, no leaked email collision.

Authorizations:
bearerAuthoauth2None
Request Body schema:
required
email
required
string <email> non-empty
first_name
required
string [ 1 .. 150 ] characters
last_name
required
string [ 1 .. 150 ] characters
client_name
required
string [ 1 .. 255 ] characters

Display name for the new business entity (DSO or solo practitioner).

invite_code
string

Required only when the invited_signup_required Waffle flag is on. Single-use; consumed atomically on successful signup.

npi
string^\d{10}$

10-digit National Provider Identifier. Required when the npi_verification_required Waffle flag is on.

state
string <= 2 characters

Two-letter US state code where the practice operates. Required when the npi_verification_required Waffle flag is on; matched case-insensitively against the NPI Registry's address rows.

Responses

Request samples

Content type
{
  • "email": "user@example.com",
  • "first_name": "string",
  • "last_name": "string",
  • "client_name": "string",
  • "invite_code": "string",
  • "npi": "string",
  • "state": "st"
}

Response samples

Content type
application/json
{
  • "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
  • "email": "user@example.com",
  • "client_id": "5b3fa7ba-57d3-4017-a65b-d57dcd2db643"
}

account_token_logout_create

Revoke tokens and flush all Django sessions for the user.

Accepts a refresh token from any of:

  • The HttpOnly escape_refresh_token cookie (preferred — set by the API on login, cleared on logout, never visible to JS).
  • A SimpleJWT refresh token in the body ({"refresh": "..."}) for backward compatibility with clients that have not yet switched to the cookie flow.
  • An OAuth2 access token via the Authorization header (older script tooling).

In every case, all Django sessions for the identified user are flushed so the Nexus session cookie is invalidated, and the refresh-token cookie is unset on the response.

Authorizations:
jwtAuthbearerAuthoauth2None

Responses

account_token_refresh_create

Cookie-aware wrapper around SimpleJWT's :class:TokenRefreshView.

Behavioural differences from the base class:

  • If the request body has no refresh field, the view falls back to reading the escape_refresh_token HttpOnly cookie and forwards it to the serializer. This is the common path for the web SPA after GH-293.
  • On a successful 200 response, the rotated refresh token is written to the cookie and stripped from the response body so no JS-readable copy is ever returned to the browser. The access token stays in the body where the SPA can stash it in memory (or component state) for the short access-token TTL.
  • Body-based callers (curl, integration tests, legacy clients) that POST a refresh field still see the rotated refresh token in the response so they keep working during the rollout window.
  • The serializer is overridden to :class:apps.accounts.jwt_tokens.ChainCappedTokenRefreshSerializer (GH-564) so the rotation chain inherits an absolute lifetime cap. An active polling client can no longer keep refreshing forever just by exchanging tokens within the per-token lifetime — the chain dies once the configured absolute window elapses, anchored to the original login.
Authorizations:
bearerAuthoauth2
Request Body schema:
required
refresh
required
string non-empty

Responses

Request samples

Content type
{
  • "refresh": "string"
}

Response samples

Content type
application/json
{
  • "refresh": "string",
  • "access": "string"
}

client_invite_codes_list

List or mint invite codes scoped to a single Client (GH-649).

GET /api/v1/client//invite-codes/ Returns the codes attributed to client_uid. Same shape as the legacy GET /api/v1/account/invite-codes/ endpoint but always pre-filtered to the URL Client so the frontend doesn't have to know whether the caller is staff (and would otherwise see codes for every Client they can access).

Visible to any user who can read the Client's data -- the
existing :func:`_user_can_see_client_codes` rule applies (staff
OR an active ``ClientMembership`` at this Client).  Cross-tenant
UID guesses get a 404 indistinguishable from a non-existent
Client.

POST /api/v1/client//invite-codes/ Mints a fresh code attributed to client_uid with created_by set to the caller. Gated by :func:_user_can_mint_for_client (staff / OWNER / admin / OM / dentist) and rate-limited per Client to :data:CLIENT_INVITE_CODE_MONTHLY_LIMIT codes per calendar month. Hit the cap and the response is 429 with body {"detail": "...", "limit": <int>, "period_start": "<iso>"}.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

client_invite_codes_create

List or mint invite codes scoped to a single Client (GH-649).

GET /api/v1/client//invite-codes/ Returns the codes attributed to client_uid. Same shape as the legacy GET /api/v1/account/invite-codes/ endpoint but always pre-filtered to the URL Client so the frontend doesn't have to know whether the caller is staff (and would otherwise see codes for every Client they can access).

Visible to any user who can read the Client's data -- the
existing :func:`_user_can_see_client_codes` rule applies (staff
OR an active ``ClientMembership`` at this Client).  Cross-tenant
UID guesses get a 404 indistinguishable from a non-existent
Client.

POST /api/v1/client//invite-codes/ Mints a fresh code attributed to client_uid with created_by set to the caller. Gated by :func:_user_can_mint_for_client (staff / OWNER / admin / OM / dentist) and rate-limited per Client to :data:CLIENT_INVITE_CODE_MONTHLY_LIMIT codes per calendar month. Hit the cap and the response is 429 with body {"detail": "...", "limit": <int>, "period_start": "<iso>"}.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "code": "string",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "created_at": "2019-08-24T14:15:22Z"
}

Practices

Practice management and logo upload

client_create

Create a new organization (Client) for the authenticated staff user.

Creates the :class:Client row, then mints an OWNER :class:~apps.accounts.models.ClientMembership so the user immediately has full control. New clients are automatically assigned the free plan by :meth:Client.save.

Returns HTTP 201 with the new client payload on success. Returns HTTP 409 if the user already belongs to at least one active client — the getting-started wizard guards against this case on the frontend, but the API enforces it so the endpoint can't be used as an org-creation cannon.

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema: application/json
name
required
string

Organization name

Responses

Request samples

Content type
application/json
{
  • "name": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "logo_url": "string",
  • "accent_color": "string",
  • "scheduling_enabled": true,
  • "clinical_enabled": true,
  • "imaging_enabled": true,
  • "insurance_enabled": true,
  • "billing_enabled": true,
  • "doccenter_enabled": true,
  • "portal_enabled": true,
  • "sync_enabled": true,
  • "max_session_hours": 32767,
  • "is_active": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null,
  • "active_banners": "string"
}

practice_retrieve

Retrieve or update a specific practice by its UUID.

Addressed by /api/v1/practice/<practice_uid>/ (the non-scoped root). Access is restricted to authenticated staff users whose accessible practices include the target UID. Cross-tenant UID guesses receive a 404 so the endpoint does not leak the existence of other tenants' practices.

PATCH-writable fields include the practice's name, address, phone, timezone, settings, and the three production-goal fields. Every update emits a practice.updated audit event mirroring PracticeDetailView.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "client_name": "string",
  • "name": "string",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "phone": "string",
  • "timezone": "string",
  • "settings": null,
  • "production_goal_daily": "string",
  • "production_goal_weekly": "string",
  • "production_goal_monthly": "string",
  • "is_active": true,
  • "logo_url": "string",
  • "client_logo_url": "string",
  • "effective_logo_url": "string",
  • "client_accent_color": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null,
  • "active_banners": "string",
  • "inbound_document_email": "string"
}

practice_update

Retrieve or update a specific practice by its UUID.

Addressed by /api/v1/practice/<practice_uid>/ (the non-scoped root). Access is restricted to authenticated staff users whose accessible practices include the target UID. Cross-tenant UID guesses receive a 404 so the endpoint does not leak the existence of other tenants' practices.

PATCH-writable fields include the practice's name, address, phone, timezone, settings, and the three production-goal fields. Every update emits a practice.updated audit event mirroring PracticeDetailView.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
client
string or null <uuid>
name
required
string [ 1 .. 255 ] characters
address_line1
string <= 255 characters
address_line2
string <= 255 characters
city
string <= 100 characters
state
string <= 2 characters
zip_code
string <= 10 characters ^\d{5}(-\d{4})?$
phone
string <= 128 characters
timezone
string [ 1 .. 50 ] characters
settings
any

Practice-specific configuration.

production_goal_daily
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Daily production goal in USD. Null = no goal set.

production_goal_weekly
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Weekly production goal in USD. Null = no goal set.

production_goal_monthly
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Monthly production goal in USD. Null = no goal set.

is_active
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "name": "string",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "phone": "string",
  • "timezone": "string",
  • "settings": null,
  • "production_goal_daily": "string",
  • "production_goal_weekly": "string",
  • "production_goal_monthly": "string",
  • "is_active": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "client_name": "string",
  • "name": "string",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "phone": "string",
  • "timezone": "string",
  • "settings": null,
  • "production_goal_daily": "string",
  • "production_goal_weekly": "string",
  • "production_goal_monthly": "string",
  • "is_active": true,
  • "logo_url": "string",
  • "client_logo_url": "string",
  • "effective_logo_url": "string",
  • "client_accent_color": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null,
  • "active_banners": "string",
  • "inbound_document_email": "string"
}

practice_partial_update

Retrieve or update a specific practice by its UUID.

Addressed by /api/v1/practice/<practice_uid>/ (the non-scoped root). Access is restricted to authenticated staff users whose accessible practices include the target UID. Cross-tenant UID guesses receive a 404 so the endpoint does not leak the existence of other tenants' practices.

PATCH-writable fields include the practice's name, address, phone, timezone, settings, and the three production-goal fields. Every update emits a practice.updated audit event mirroring PracticeDetailView.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
client
string or null <uuid>
name
string [ 1 .. 255 ] characters
address_line1
string <= 255 characters
address_line2
string <= 255 characters
city
string <= 100 characters
state
string <= 2 characters
zip_code
string <= 10 characters ^\d{5}(-\d{4})?$
phone
string <= 128 characters
timezone
string [ 1 .. 50 ] characters
settings
any

Practice-specific configuration.

production_goal_daily
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Daily production goal in USD. Null = no goal set.

production_goal_weekly
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Weekly production goal in USD. Null = no goal set.

production_goal_monthly
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Monthly production goal in USD. Null = no goal set.

is_active
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "name": "string",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "phone": "string",
  • "timezone": "string",
  • "settings": null,
  • "production_goal_daily": "string",
  • "production_goal_weekly": "string",
  • "production_goal_monthly": "string",
  • "is_active": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "client_name": "string",
  • "name": "string",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "phone": "string",
  • "timezone": "string",
  • "settings": null,
  • "production_goal_daily": "string",
  • "production_goal_weekly": "string",
  • "production_goal_monthly": "string",
  • "is_active": true,
  • "logo_url": "string",
  • "client_logo_url": "string",
  • "effective_logo_url": "string",
  • "client_accent_color": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null,
  • "active_banners": "string",
  • "inbound_document_email": "string"
}

practice_logo_create

Upload or delete the logo for a practice.

POST /api/v1/practice/{uid}/logo/ -- upload a new logo image DELETE /api/v1/practice/{uid}/logo/ -- remove the current logo

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema: multipart/form-data
required
file
required
string <binary>

Responses

Response samples

Content type
application/json
{}

practice_logo_destroy

Upload or delete the logo for a practice.

POST /api/v1/practice/{uid}/logo/ -- upload a new logo image DELETE /api/v1/practice/{uid}/logo/ -- remove the current logo

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_logo_client_create

Upload or delete the logo for the client that owns a practice.

POST /api/v1/practice/{uid}/logo/client/ -- upload a new client logo DELETE /api/v1/practice/{uid}/logo/client/ -- remove the current client logo

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema: multipart/form-data
required
file
required
string <binary>

Responses

Response samples

Content type
application/json
{}

practice_logo_client_destroy

Upload or delete the logo for the client that owns a practice.

POST /api/v1/practice/{uid}/logo/client/ -- upload a new client logo DELETE /api/v1/practice/{uid}/logo/client/ -- remove the current client logo

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

Read the per-practice messaging inbox owners.

GET / PATCH the named messaging inbox owners for a practice.

See module docstring for the auth / validation / audit contract.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "inbox_owner_user_ids": [
    ],
  • "inbox_owner_users": [
    ]
}

Replace the per-practice messaging inbox owners.

GET / PATCH the named messaging inbox owners for a practice.

See module docstring for the auth / validation / audit contract.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
inbox_owner_user_ids
Array of strings <uuid> [ items <uuid > ]

Users to route new patient-portal threads to. Empty list restores the historical ADMIN / OFFICE_MANAGER fan-out.

Responses

Request samples

Content type
{
  • "inbox_owner_user_ids": [
    ]
}

Response samples

Content type
application/json
{
  • "inbox_owner_user_ids": [
    ],
  • "inbox_owner_users": [
    ]
}

practice_privacy_config_retrieve

Return the privacy configuration for the practice's state.

Looks up the StatePrivacyConfig for the practice's state and returns the full config object. If the state has no privacy law on file, returns an empty config dict.

Staff-auth required; practice-scoped via PracticeScopedMixin.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "state": "string",
  • "state_name": "string",
  • "config": null,
  • "is_active": true
}

practice_create_create

Create a new practice during import onboarding.

If the authenticated user does not yet have a Client, one is created automatically using the practice name. The new practice is then associated with the user's client.

The import:write scope (legacy catalog entry, still issued to the first-party migration tools — escape-importer / escape-backup / escape-restore) gates this endpoint. The new-taxonomy sync:* scopes are reserved for a future tightening; until any first-party tool actually ships with a sync:patients token, requiring it here would lock the importer out of practice onboarding.

Authorizations:
jwtAuthbearerAuthoauth2

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "client_name": "string",
  • "name": "string",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "phone": "string",
  • "timezone": "string",
  • "settings": null,
  • "production_goal_daily": "string",
  • "production_goal_weekly": "string",
  • "production_goal_monthly": "string",
  • "is_active": true,
  • "logo_url": "string",
  • "client_logo_url": "string",
  • "effective_logo_url": "string",
  • "client_accent_color": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null,
  • "active_banners": "string",
  • "inbound_document_email": "string"
}

Import

Data migration sessions and batches

practice_sync_export_retrieve

Stream all practice data as a JSON download.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

practice_sync_export_counts_retrieve

Return entity counts for a practice (lightweight preview).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "practice_name": "string",
  • "counts": {
    },
  • "total_records": 0
}

practice_sync_import_create

Receive a batch of records for a given entity type.

Records are bulk-created with ignore_conflicts=True so re-running a migration is safe.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
entity_type
required
string
practice_uid
required
string <uuid>
Request Body schema:
required
session_id
required
string <uuid>
entity_type
required
string (EntityTypeEnum)
Enum: "definitions" "providers" "operatories" "patients" "recalls" "appointments" "balances" "payments" "insurance" "commlogs" "procedure_codes" "schedules" "planned_services" "eod" "procedures" "adjustments" "claims" "treatment_plans" "benefits" "referrals" "medical_history" "payment_plans" "patient_notes" "carriers" "appointment_procedures" "treatment_plan_items" "conditions" "allergies" "medications" "vital_signs" "tooth_conditions" "perio_exams" "perio_readings" "clinical_notes" "note_templates" "patient_education" "anesthesia_records" "payment_records" "payment_splits" "payment_plan_charges" "insurance_carriers" "insurance_plans" "fee_schedules" "fee_schedule_entries" "patient_insurance" "insurance_claims" "claim_procedures" "insurance_benefits" "comm_logs" "schedule_templates" "schedule_overrides" "referral_sources" "patient_referrals" "portal_messages" "imaging_sources" "exam_templates" "exam_template_slots" "imaging_exams" "imaging_exam_images"
  • definitions - definitions
  • providers - providers
  • operatories - operatories
  • patients - patients
  • recalls - recalls
  • appointments - appointments
  • balances - balances
  • payments - payments
  • insurance - insurance
  • commlogs - commlogs
  • procedure_codes - procedure_codes
  • schedules - schedules
  • planned_services - planned_services
  • eod - eod
  • procedures - procedures
  • adjustments - adjustments
  • claims - claims
  • treatment_plans - treatment_plans
  • benefits - benefits
  • referrals - referrals
  • medical_history - medical_history
  • payment_plans - payment_plans
  • patient_notes - patient_notes
  • carriers - carriers
  • appointment_procedures - appointment_procedures
  • treatment_plan_items - treatment_plan_items
  • conditions - conditions
  • allergies - allergies
  • medications - medications
  • vital_signs - vital_signs
  • tooth_conditions - tooth_conditions
  • perio_exams - perio_exams
  • perio_readings - perio_readings
  • clinical_notes - clinical_notes
  • note_templates - note_templates
  • patient_education - patient_education
  • anesthesia_records - anesthesia_records
  • payment_records - payment_records
  • payment_splits - payment_splits
  • payment_plan_charges - payment_plan_charges
  • insurance_carriers - insurance_carriers
  • insurance_plans - insurance_plans
  • fee_schedules - fee_schedules
  • fee_schedule_entries - fee_schedule_entries
  • patient_insurance - patient_insurance
  • insurance_claims - insurance_claims
  • claim_procedures - claim_procedures
  • insurance_benefits - insurance_benefits
  • comm_logs - comm_logs
  • schedule_templates - schedule_templates
  • schedule_overrides - schedule_overrides
  • referral_sources - referral_sources
  • patient_referrals - patient_referrals
  • portal_messages - portal_messages
  • imaging_sources - imaging_sources
  • exam_templates - exam_templates
  • exam_template_slots - exam_template_slots
  • imaging_exams - imaging_exams
  • imaging_exam_images - imaging_exam_images
required
Array of objects

Responses

Request samples

Content type
{
  • "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
  • "entity_type": "definitions",
  • "records": [
    ]
}

Response samples

Content type
application/json
{
  • "created": 0,
  • "skipped": 0,
  • "errors": 0,
  • "error_messages": [
    ]
}

practice_sync_import_session_list

List import sessions (GET) or create a new one (POST).

GET is open to any authenticated caller — listing one's own import sessions is non-sensitive metadata. POST is restricted to sync tools via the sync:patients gate (first-party bypass keeps the migration tools working; third-party apps cannot request sync:* scopes).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

practice_sync_import_session_create

List import sessions (GET) or create a new one (POST).

GET is open to any authenticated caller — listing one's own import sessions is non-sensitive metadata. POST is restricted to sync tools via the sync:patients gate (first-party bypass keeps the migration tools working; third-party apps cannot request sync:* scopes).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
source
required
string (ImportSessionCreateSourceEnum)
Enum: "opendental" "eaglesoft" "dentrix" "restore" "faker"
  • opendental - OpenDental
  • eaglesoft - Eaglesoft
  • dentrix - Dentrix
  • restore - Backup Restore
  • faker - Demo Data

Responses

Request samples

Content type
{
  • "source": "opendental"
}

Response samples

Content type
application/json
{
  • "session_id": "string",
  • "practice_id": 0,
  • "practice_name": "string"
}

practice_sync_import_session_retrieve

Retrieve session detail with conversion progress (GET) or delete (DELETE).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
session_id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "source": "string",
  • "status": "string",
  • "started_at": "string",
  • "completed_at": "string",
  • "created_by": "user@example.com",
  • "record_counts": {
    },
  • "total_records": 0,
  • "conversion_error_count": 0,
  • "import_report": {
    },
  • "import_error_details": [
    ],
  • "has_schema": true,
  • "conversion": {
    }
}

practice_sync_import_session_destroy

Retrieve session detail with conversion progress (GET) or delete (DELETE).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
session_id
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_sync_import_session_accept_create

Accept conversion results (even with errors) and mark session as converted.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
session_id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "detail": "string",
  • "session_id": "string"
}

practice_sync_import_session_complete_create

Mark an import session as completed.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
session_id
required
string <uuid>
Request Body schema:
session_id
string <uuid>
Array of objects
object

Responses

Request samples

Content type
{
  • "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
  • "results": [
    ],
  • "report": {
    }
}

Response samples

Content type
application/json
{
  • "session_id": "string",
  • "status": "string",
  • "completed_at": "string",
  • "record_counts": {
    }
}

practice_sync_import_session_convert_create

Trigger conversion of a completed import session to live data.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
session_id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "detail": "string",
  • "session_id": "string"
}

practice_sync_import_session_error_report_retrieve

Download a conversion error report as JSON or CSV.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
session_id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "records": [
    ]
}

practice_sync_import_session_rollback_create

Delete all normalized data for this session and reset to uploaded status.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
session_id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "detail": "string"
}

practice_sync_import_session_schema_create

Upload a source PMS schema dump for an import session.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
session_id
required
string <uuid>
Request Body schema:
required
schema_text
required
string non-empty
source_type
required
string [ 1 .. 20 ] characters
object

Responses

Request samples

Content type
{
  • "schema_text": "string",
  • "source_type": "string",
  • "metadata": {
    }
}

Response samples

Content type
application/json
{
  • "detail": "string"
}

practice_sync_ping_retrieve

Simple authentication check.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "status": "string"
}

practice_sync_status_list

List all sync status records for a practice.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

practice_sync_status_retrieve

Get or update a sync status record for a specific entity type.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
entity_type
required
string
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "entity_type": "string",
  • "last_synced_at": "string",
  • "last_record_count": 0,
  • "is_running": true,
  • "error_message": "string"
}

practice_sync_status_create

Get or update a sync status record for a specific entity type.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
entity_type
required
string
practice_uid
required
string <uuid>
Request Body schema:
last_synced_at
string or null <date-time>
last_record_count
integer
Default: 0
is_running
boolean
Default: false
error_message
string
Default: ""

Responses

Request samples

Content type
{
  • "last_synced_at": "2019-08-24T14:15:22Z",
  • "last_record_count": 0,
  • "is_running": false,
  • "error_message": ""
}

Response samples

Content type
application/json
{
  • "entity_type": "string",
  • "last_synced_at": "string",
  • "last_record_count": 0,
  • "is_running": true,
  • "error_message": "string"
}

Webhooks

Webhook subscriptions and delivery

webhooks_events_retrieve

Public endpoint returning all registered webhook events grouped by category.

No authentication required — this is a discovery endpoint for developers building integrations against the Escape Dental API.

Authorizations:
jwtAuthbearerAuthoauth2None

Responses

webhooks_subscriptions_test_create

Send a test ping delivery to a subscription's target URL.

Creates a WebhookDelivery with event type 'test.ping' and enqueues it for immediate delivery via Celery.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
subscription_uid
required
string <uuid>

Responses

webhooks_subscriptions_verify_create

Trigger URL ownership verification for a subscription.

Enqueues a Celery task that sends a challenge request to the target URL. The subscription's is_verified flag is set to True only after the endpoint echoes the challenge back correctly.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
subscription_uid
required
string <uuid>

Responses

OAuth2

Authorization and token management

account

account_passkey_retrieve

List the authenticated user's registered passkeys.

GET /api/v1/account/passkey/

Authorizations:
jwtAuthbearerAuthoauth2

Responses

account_passkey_destroy

Delete a registered passkey.

DELETE /api/v1/account/passkey//

Returns 400 if this is the user's only passkey (last-passkey protection).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
passkey_uid
required
string <uuid>

Responses

account_passkey_rename_partial_update

Rename a registered passkey.

PATCH /api/v1/account/passkey//rename/ Body: { "name": "New Name" }

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
passkey_uid
required
string <uuid>

Responses

account_passkey_auth_begin_create

Begin passkey authentication ceremony.

POST /api/v1/account/passkey/auth/begin/ Body: { "email": "user@example.com" } (optional)

If email is provided, returns allowCredentials scoped to that user. If email is omitted, returns empty allowCredentials for discoverable credential / conditional UI flow.

Authorizations:
jwtAuthbearerAuthoauth2None

Responses

account_passkey_auth_complete_create

Complete passkey authentication ceremony.

POST /api/v1/account/passkey/auth/complete/ Body: { "assertion": {...}, "challenge_key": "..." }

On success, returns JWT access + refresh tokens.

Authorizations:
jwtAuthbearerAuthoauth2None

Responses

account_passkey_register_begin_create

Begin passkey registration ceremony.

POST /api/v1/account/passkey/register/begin/ Auth: Bearer token (setup or full session)

Authorizations:
jwtAuthbearerAuthoauth2

Responses

account_passkey_register_complete_create

Complete passkey registration ceremony.

POST /api/v1/account/passkey/register/complete/ Auth: Bearer token (setup or full session) Body: { "credential": {...}, "name": "My Passkey" }

On success during setup session: auto-upgrades to full session.

Authorizations:
jwtAuthbearerAuthoauth2

Responses

account_token_verify_create

Takes a token and indicates if it is valid. This view provides no information about a token's fitness for a particular use.

Authorizations:
bearerAuthoauth2
Request Body schema:
required
token
required
string non-empty

Responses

Request samples

Content type
{
  • "token": "string"
}

account_user_list

List users visible to the authenticated user (scoped by practice membership).

Optional boolean filters (?is_staff=true|false and ?is_superuser=true|false) let callers narrow the result to the staff / superuser populations (or exclude them). Both filters accept the strings "true" and "false" (case-insensitive); any other value is ignored so unknown params never surface as a 500.

Authorizations:
jwtAuthbearerAuthoauth2
query Parameters
cursor
string

The pagination cursor value.

Responses

Response samples

Content type
application/json
{
  • "results": [
    ]
}

account_user_retrieve

Retrieve or update a user by ID (scoped to client).

Reads are allowed for any authenticated user within the same client. Writes are restricted: users can update their own profile, but only admins can update other users' profiles.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
user_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "email": "user@example.com",
  • "first_name": "string",
  • "last_name": "string",
  • "is_patient": true,
  • "is_staff": true,
  • "is_superuser": true,
  • "is_active": true,
  • "date_joined": "2019-08-24T14:15:22Z",
  • "last_login": "2019-08-24T14:15:22Z",
  • "last_seen_at": "2019-08-24T14:15:22Z",
  • "first_run_tour_completed_at": "2019-08-24T14:15:22Z",
  • "preference_data": "string",
  • "memberships": [
    ],
  • "client_memberships": [
    ],
  • "max_session_hours": "string",
  • "current_practice_id": "edf1be34-8ae4-41f5-bad6-133af3513eac",
  • "practice_timezone": "string"
}

account_user_update

Retrieve or update a user by ID (scoped to client).

Reads are allowed for any authenticated user within the same client. Writes are restricted: users can update their own profile, but only admins can update other users' profiles.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
user_uid
required
string <uuid>
Request Body schema:
required
first_name
required
string [ 1 .. 150 ] characters
last_name
required
string [ 1 .. 150 ] characters

Responses

Request samples

Content type
{
  • "first_name": "string",
  • "last_name": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "email": "user@example.com",
  • "first_name": "string",
  • "last_name": "string",
  • "is_patient": true,
  • "is_staff": true,
  • "is_superuser": true,
  • "is_active": true,
  • "date_joined": "2019-08-24T14:15:22Z",
  • "last_login": "2019-08-24T14:15:22Z",
  • "last_seen_at": "2019-08-24T14:15:22Z",
  • "first_run_tour_completed_at": "2019-08-24T14:15:22Z",
  • "preference_data": "string",
  • "memberships": [
    ],
  • "client_memberships": [
    ],
  • "max_session_hours": "string",
  • "current_practice_id": "edf1be34-8ae4-41f5-bad6-133af3513eac",
  • "practice_timezone": "string"
}

account_user_partial_update

Retrieve or update a user by ID (scoped to client).

Reads are allowed for any authenticated user within the same client. Writes are restricted: users can update their own profile, but only admins can update other users' profiles.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
user_uid
required
string <uuid>
Request Body schema:
first_name
string [ 1 .. 150 ] characters
last_name
string [ 1 .. 150 ] characters

Responses

Request samples

Content type
{
  • "first_name": "string",
  • "last_name": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "email": "user@example.com",
  • "first_name": "string",
  • "last_name": "string",
  • "is_patient": true,
  • "is_staff": true,
  • "is_superuser": true,
  • "is_active": true,
  • "date_joined": "2019-08-24T14:15:22Z",
  • "last_login": "2019-08-24T14:15:22Z",
  • "last_seen_at": "2019-08-24T14:15:22Z",
  • "first_run_tour_completed_at": "2019-08-24T14:15:22Z",
  • "preference_data": "string",
  • "memberships": [
    ],
  • "client_memberships": [
    ],
  • "max_session_hours": "string",
  • "current_practice_id": "edf1be34-8ae4-41f5-bad6-133af3513eac",
  • "practice_timezone": "string"
}

Admin

Read OAuth API usage rollups

Aggregate the OAuthAppUsageMetric rollup table by scope, method, and window. Staff-only. Powers the support-tool API stats dashboard.

Authorizations:
jwtAuthbearerAuthoauth2
query Parameters
from
string <date>

Inclusive lower bound on bucket_start (UTC date, YYYY-MM-DD).

method
string
Enum: "DELETE" "GET" "HEAD" "OPTIONS" "PATCH" "POST" "PUT"

HTTP method. GET/HEAD/OPTIONS map to the GET bucket; POST/PUT/PATCH/DELETE map to the WRITE bucket.

page
integer

1-indexed page number.

page_size
integer

Page size, default 20, max 100.

scope
string
Enum: "app" "client" "practice" "user"

Scope dimension to filter on.

scope_id
string

Denormalized scope identifier. UUID for client/practice/user, OAuth client_id for app. Requires scope to be set.

to
string <date>

Inclusive upper bound on bucket_start (UTC date, YYYY-MM-DD).

window
string
Enum: "day" "hour" "month" "week"

Bucket size. Defaults to hour.

Responses

Response samples

Content type
application/json
{}

List audit events

Paginated, filterable read of the audit-events-* Elasticsearch index. Staff-only. Powers the support-tool audit-log panel. Filters are AND-combined; missing filters are open-ended. Page size defaults to 50, max 100.

Authorizations:
jwtAuthbearerAuthoauth2
query Parameters
actor_email
string

Exact-match actor email; matched against the keyword field actor.email.

event_type
string

Dotted-name event type (e.g. patient.viewed).

page
integer

1-indexed page number. Defaults to 1.

page_size
integer

Page size, default 50, max 100 (clamped).

practice
string <uuid>

Practice UUID — only events tagged with this practice_id are returned.

since
string <date-time>

ISO8601 lower bound (inclusive) on timestamp.

until
string <date-time>

ISO8601 upper bound (inclusive) on timestamp.

Responses

Response samples

Content type
application/json
[
  • {
    }
]

admin_client_partial_update

Toggle is_active on a Client.

Staff-only (is_staff=True). Sets the is_active flag on the Client model. Deactivating a client effectively disables all practices under it.

Idempotent: re-submitting the current state is a no-op that still writes an audit entry (with no_op=True) so the attempt itself is recorded.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string <uuid>
Request Body schema:
is_active
boolean

Set to true to enable, false to disable.

reason
string [ 5 .. 1024 ] characters

Free-text justification recorded in the audit log (min 5 chars).

Responses

Request samples

Content type
{
  • "is_active": true,
  • "reason": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "is_active": true
}

List the canonical MCP tool catalog

Read-only list of every key registered in apps.mcp.tools.registry.REGISTRY. Staff-only. Returns name, description, required_scopes, and pass_context. Used by the support UI to render every gating row even when no PracticeToolGate exists yet for the practice in view.

Authorizations:
jwtAuthbearerAuthoauth2

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get OAuth application detail

Return the public payload for a single OAuth application.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_id
required
string

Responses

Response samples

Content type
application/json
{
  • "client_id": "string",
  • "name": "string",
  • "throttle_mode": "string",
  • "is_first_party": true,
  • "approval_status": "string",
  • "request_count_24h": 0,
  • "audit_throttle_hits_24h": 0,
  • "enforce_throttle_hits_24h": 0,
  • "slots": [
    ],
  • "url_template": "",
  • "approved_at": "2019-08-24T14:15:22Z",
  • "approved_by_email": "string"
}

Update OAuth application throttle mode and / or slot manifest

Either flips the per-app throttle override (throttle_mode + reason body) or updates the slot manifest (slots / url_template body) — or both in a single request. At least one set of fields must be present. Staff-only.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_id
required
string
Request Body schema:
throttle_mode
string
Enum: "default" "audit" "enforce"

Target throttle mode. default clears any per-app override and inherits the global setting.

  • default - Default (inherit global)
  • audit - Audit
  • enforce - Enforce
reason
string [ 5 .. 1024 ] characters

Free-text justification recorded in the audit log (min 5 chars).

Responses

Request samples

Content type
{
  • "throttle_mode": "default",
  • "reason": "string"
}

Response samples

Content type
application/json
{
  • "client_id": "string",
  • "name": "string",
  • "throttle_mode": "string",
  • "is_first_party": true,
  • "approval_status": "string",
  • "request_count_24h": 0,
  • "audit_throttle_hits_24h": 0,
  • "enforce_throttle_hits_24h": 0,
  • "slots": [
    ],
  • "url_template": "",
  • "approved_at": "2019-08-24T14:15:22Z",
  • "approved_by_email": "string"
}

admin_practice_partial_update

Toggle is_active on a Practice.

Staff-only (is_staff=True). Sets the is_active flag on the Practice model.

Idempotent: re-submitting the current state is a no-op that still writes an audit entry (with no_op=True).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string <uuid>
Request Body schema:
is_active
boolean

Set to true to enable, false to disable.

reason
string [ 5 .. 1024 ] characters

Free-text justification recorded in the audit log (min 5 chars).

Responses

Request samples

Content type
{
  • "is_active": true,
  • "reason": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "is_active": true
}

admin_practice_ocr_backfill_create

Queue OCR + Elasticsearch indexing for documents in the given practice that pre-date the OCR pipeline. Idempotent: skips documents that already have a DocumentOcrResult row unless force is true. Requires reason, which is recorded in the audit log.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string <uuid>
Request Body schema:
required
reason
required
string [ 5 .. 1024 ] characters

Free-text justification recorded in the audit log (min 5 chars).

limit
integer or null [ 1 .. 100000 ]

Cap the number of OCR tasks dispatched. Defaults to no cap.

mime
Array of strings or null[ items [ 1 .. 100 ] characters ]

Override the default mime allow-list. Defaults to ['application/pdf', 'image/jpeg', 'image/png', 'image/tiff', 'image/webp'].

force
boolean
Default: false

Re-OCR documents that already have a DocumentOcrResult row.

dry_run
boolean
Default: false

Compute the would-be queued count without dispatching tasks.

Responses

Request samples

Content type
{
  • "reason": "string",
  • "limit": 1,
  • "mime": [
    ],
  • "force": false,
  • "dry_run": false
}

Response samples

Content type
application/json
{
  • "queued": 0,
  • "errored": 0,
  • "total_matched": 0,
  • "dry_run": true
}

admin_practice_ocr_status_retrieve

Return {documents_total, ocr_results_total, pending} for the practice. Lets the support UI render OCR progress without paginating either list.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "documents_total": 0,
  • "ocr_results_total": 0,
  • "pending": 0
}

Upsert an MCP tool gate for a practice

Create or update a PracticeToolGate row. Fires the model's post_save signal so connected MCP SSE clients receive a notifications/tools/list_changed frame.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_id
required
string <uuid>
tool_key
required
string
Request Body schema:
required
enabled
required
boolean

True to allow the tool, False to hide it from the practice's catalog.

note
string <= 4096 characters
Default: ""

Optional free-text reason surfaced in the support UI.

Responses

Request samples

Content type
{
  • "enabled": true,
  • "note": ""
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "tool_key": "string",
  • "enabled": true,
  • "note": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "created_by_email": "string",
  • "modified_by_email": "string"
}

Remove an MCP tool gate for a practice

Delete the PracticeToolGate row, reverting the tool to its default-enabled state. Fires the model's post_delete signal so connected MCP SSE clients receive a notifications/tools/list_changed frame. Idempotent -- deleting a non-existent gate returns 404.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_id
required
string <uuid>
tool_key
required
string

Responses

admin_user_partial_update

Toggle is_active on a User.

Staff-only (is_staff=True). Sets the is_active flag on the User model.

Only superusers may disable a superuser -- a non-superuser staff member attempting this gets a 403. The support tool enforces the same rule client-side; the server check is the authoritative guard (belt + suspenders against a broken or misbehaving client).

Idempotent: re-submitting the current state is a no-op that still writes an audit entry (with no_op=True).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string <uuid>
Request Body schema:
is_active
boolean

Set to true to enable, false to disable.

reason
string [ 5 .. 1024 ] characters

Free-text justification recorded in the audit log (min 5 chars).

Responses

Request samples

Content type
{
  • "is_active": true,
  • "reason": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "email": "user@example.com",
  • "first_name": "string",
  • "last_name": "string",
  • "is_active": true
}

admin

admin_oauth_app_list

Paginated list of OAuth applications for the support tool.

Cross-tenant — staff operates above the practice-scoping layer, so every Application row is returned. Ordered by name for a stable, human-friendly default; the support UI may later re-sort client-side.

Query parameters (api#408):

  • q — case-insensitive substring match against name OR client_id. Empty/missing means "no filter". Translates to Q(name__icontains=q) | Q(client_id__icontains=q) so the index planner picks the cheaper side.
  • throttle_mode — exact match against :class:OAuthAppProfile.throttle_mode (default / audit / enforce). Apps with NO profile row are treated as default so ?throttle_mode=default returns them too — implemented with a LEFT JOIN + Coalesce annotation rather than a Python-side filter so pagination metadata (count/next/previous) reflects the filtered set.

Both filters AND-combine. An unknown throttle_mode value returns HTTP 400 with a clear error — picked over silently ignoring because a typo on the support tool's side should fail loudly rather than serve up the unfiltered list and look like a pagination bug.

Authorizations:
jwtAuthbearerAuthoauth2
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

admin_oauth_app_approve_create

Approve, reject, or suspend a third-party OAuth application.

POST /api/v1/admin/oauth-app/<client_id>/approve/ POST /api/v1/admin/oauth-app/<client_id>/reject/ POST /api/v1/admin/oauth-app/<client_id>/suspend/

The action kwarg is set by the URL dispatcher (see admin_api/urls.py).

Approve: Sets approval_status=APPROVED, stamps approved_at and approved_by. reason is optional (but logged if supplied). Returns 200 with the updated serializer payload.

Reject / Suspend: Sets the corresponding status. reason is required (≥5 chars) so there is always a human-readable explanation in the audit log. approved_at / approved_by are cleared on reject/suspend so the record accurately reflects the current state.

First-party apps: Always returns 400 — they bypass the approval workflow by design and must not be touched via this endpoint.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_id
required
string

Responses

admin_oauth_app_reject_create

Approve, reject, or suspend a third-party OAuth application.

POST /api/v1/admin/oauth-app/<client_id>/approve/ POST /api/v1/admin/oauth-app/<client_id>/reject/ POST /api/v1/admin/oauth-app/<client_id>/suspend/

The action kwarg is set by the URL dispatcher (see admin_api/urls.py).

Approve: Sets approval_status=APPROVED, stamps approved_at and approved_by. reason is optional (but logged if supplied). Returns 200 with the updated serializer payload.

Reject / Suspend: Sets the corresponding status. reason is required (≥5 chars) so there is always a human-readable explanation in the audit log. approved_at / approved_by are cleared on reject/suspend so the record accurately reflects the current state.

First-party apps: Always returns 400 — they bypass the approval workflow by design and must not be touched via this endpoint.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_id
required
string

Responses

admin_oauth_app_suspend_create

Approve, reject, or suspend a third-party OAuth application.

POST /api/v1/admin/oauth-app/<client_id>/approve/ POST /api/v1/admin/oauth-app/<client_id>/reject/ POST /api/v1/admin/oauth-app/<client_id>/suspend/

The action kwarg is set by the URL dispatcher (see admin_api/urls.py).

Approve: Sets approval_status=APPROVED, stamps approved_at and approved_by. reason is optional (but logged if supplied). Returns 200 with the updated serializer payload.

Reject / Suspend: Sets the corresponding status. reason is required (≥5 chars) so there is always a human-readable explanation in the audit log. approved_at / approved_by are cleared on reject/suspend so the record accurately reflects the current state.

First-party apps: Always returns 400 — they bypass the approval workflow by design and must not be touched via this endpoint.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_id
required
string

Responses

admin_practice_mcp_gates_list

List existing :class:PracticeToolGate rows for one practice.

Empty list means "no overrides -- every tool is default-enabled". Returns the rows in tool_key order so the support UI's rendering is stable across requests.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_id
required
string <uuid>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

admin_support_patients_list

Cross-practice, PHI-free patient search for the support tool.

Staff-only (is_staff=True). Accepts a ?q=<query> parameter:

  • If q is UUID-shaped, does an exact match on Patient.id.
  • Otherwise, performs a case-insensitive prefix match against first_name OR last_name.

The PHI fields are searched server-side -- a tech needs to type a name to find a record -- but the response never contains them. The query string itself is NOT recorded in the audit log, because it may itself be PHI (e.g. a patient's surname).

Authorizations:
jwtAuthbearerAuthoauth2
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

admin_support_patients_retrieve

PHI-free patient detail view for the support tool.

Staff-only (is_staff=True). Exposes the same allow-listed fields as the list view (see :class:SupportPatientSerializer). Emits a support.patient.viewed audit event on every access.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "initials": "string",
  • "practice": {
    },
  • "status": "active",
  • "last_appointment_at": "string",
  • "balance_outstanding": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

Banners

banner_list

CRUD for sign-in / pop-up banners attached to a Client or a Practice.

Permissions (deny-by-default):

  • All requests require an authenticated, non-patient staff user.
  • Read (list/retrieve): any user with an active membership in the banner's owning Client (for client-scoped banners) or Practice (for practice-scoped banners). By default the list returns only currently-active banners; pass ?include_expired=true to include expired and not-yet-started banners (admin role required).
  • Write (create/update/destroy):
    • Banners targeting a Client require an active ClientMembership on that Client with role OWNER or TECHNICAL.
    • Banners targeting a Practice require either:
      • an active PracticeMembership on that Practice with role ADMIN or OFFICE_MANAGER, or
      • an active ClientMembership on the Practice's Client with role OWNER (Owners can manage banners on any of their practices).
    • Crucially, a Practice admin cannot create Client-level banners — that requires explicit Client admin rights.

Cross-tenant safety: get_queryset always restricts to the user's accessible clients and practices, so a user in tenant A cannot see, list, or PATCH a banner in tenant B even by guessing UUIDs.

Authorizations:
jwtAuthbearerAuthoauth2
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

banner_create

CRUD for sign-in / pop-up banners attached to a Client or a Practice.

Permissions (deny-by-default):

  • All requests require an authenticated, non-patient staff user.
  • Read (list/retrieve): any user with an active membership in the banner's owning Client (for client-scoped banners) or Practice (for practice-scoped banners). By default the list returns only currently-active banners; pass ?include_expired=true to include expired and not-yet-started banners (admin role required).
  • Write (create/update/destroy):
    • Banners targeting a Client require an active ClientMembership on that Client with role OWNER or TECHNICAL.
    • Banners targeting a Practice require either:
      • an active PracticeMembership on that Practice with role ADMIN or OFFICE_MANAGER, or
      • an active ClientMembership on the Practice's Client with role OWNER (Owners can manage banners on any of their practices).
    • Crucially, a Practice admin cannot create Client-level banners — that requires explicit Client admin rights.

Cross-tenant safety: get_queryset always restricts to the user's accessible clients and practices, so a user in tenant A cannot see, list, or PATCH a banner in tenant B even by guessing UUIDs.

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
required
title
string <= 120 characters

Optional short heading shown above the message.

message
required
string non-empty

Plain-text banner body. HTML is not rendered by the client.

severity
string
Enum: "info" "warning" "urgent"

Visual treatment hint for the frontend (info/warning/urgent).

  • info - Info
  • warning - Warning
  • urgent - Urgent
starts_at
string <date-time>

UTC datetime the banner becomes active. Defaults to now.

expires_at
required
string <date-time>

UTC datetime after which the banner is no longer active.

client
string or null <uuid>

Client this banner targets. Mutually exclusive with practice.

practice
string or null <uuid>

Practice this banner targets. Mutually exclusive with client.

Responses

Request samples

Content type
{
  • "title": "string",
  • "message": "string",
  • "severity": "info",
  • "starts_at": "2019-08-24T14:15:22Z",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "title": "string",
  • "message": "string",
  • "severity": "info",
  • "starts_at": "2019-08-24T14:15:22Z",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "is_active": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

banner_retrieve

CRUD for sign-in / pop-up banners attached to a Client or a Practice.

Permissions (deny-by-default):

  • All requests require an authenticated, non-patient staff user.
  • Read (list/retrieve): any user with an active membership in the banner's owning Client (for client-scoped banners) or Practice (for practice-scoped banners). By default the list returns only currently-active banners; pass ?include_expired=true to include expired and not-yet-started banners (admin role required).
  • Write (create/update/destroy):
    • Banners targeting a Client require an active ClientMembership on that Client with role OWNER or TECHNICAL.
    • Banners targeting a Practice require either:
      • an active PracticeMembership on that Practice with role ADMIN or OFFICE_MANAGER, or
      • an active ClientMembership on the Practice's Client with role OWNER (Owners can manage banners on any of their practices).
    • Crucially, a Practice admin cannot create Client-level banners — that requires explicit Client admin rights.

Cross-tenant safety: get_queryset always restricts to the user's accessible clients and practices, so a user in tenant A cannot see, list, or PATCH a banner in tenant B even by guessing UUIDs.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string <uuid>

A UUID string identifying this banner.

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "title": "string",
  • "message": "string",
  • "severity": "info",
  • "starts_at": "2019-08-24T14:15:22Z",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "is_active": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

banner_update

CRUD for sign-in / pop-up banners attached to a Client or a Practice.

Permissions (deny-by-default):

  • All requests require an authenticated, non-patient staff user.
  • Read (list/retrieve): any user with an active membership in the banner's owning Client (for client-scoped banners) or Practice (for practice-scoped banners). By default the list returns only currently-active banners; pass ?include_expired=true to include expired and not-yet-started banners (admin role required).
  • Write (create/update/destroy):
    • Banners targeting a Client require an active ClientMembership on that Client with role OWNER or TECHNICAL.
    • Banners targeting a Practice require either:
      • an active PracticeMembership on that Practice with role ADMIN or OFFICE_MANAGER, or
      • an active ClientMembership on the Practice's Client with role OWNER (Owners can manage banners on any of their practices).
    • Crucially, a Practice admin cannot create Client-level banners — that requires explicit Client admin rights.

Cross-tenant safety: get_queryset always restricts to the user's accessible clients and practices, so a user in tenant A cannot see, list, or PATCH a banner in tenant B even by guessing UUIDs.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string <uuid>

A UUID string identifying this banner.

Request Body schema:
required
title
string <= 120 characters

Optional short heading shown above the message.

message
required
string non-empty

Plain-text banner body. HTML is not rendered by the client.

severity
string
Enum: "info" "warning" "urgent"

Visual treatment hint for the frontend (info/warning/urgent).

  • info - Info
  • warning - Warning
  • urgent - Urgent
starts_at
string <date-time>

UTC datetime the banner becomes active. Defaults to now.

expires_at
required
string <date-time>

UTC datetime after which the banner is no longer active.

client
string or null <uuid>

Client this banner targets. Mutually exclusive with practice.

practice
string or null <uuid>

Practice this banner targets. Mutually exclusive with client.

Responses

Request samples

Content type
{
  • "title": "string",
  • "message": "string",
  • "severity": "info",
  • "starts_at": "2019-08-24T14:15:22Z",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "title": "string",
  • "message": "string",
  • "severity": "info",
  • "starts_at": "2019-08-24T14:15:22Z",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "is_active": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

banner_partial_update

CRUD for sign-in / pop-up banners attached to a Client or a Practice.

Permissions (deny-by-default):

  • All requests require an authenticated, non-patient staff user.
  • Read (list/retrieve): any user with an active membership in the banner's owning Client (for client-scoped banners) or Practice (for practice-scoped banners). By default the list returns only currently-active banners; pass ?include_expired=true to include expired and not-yet-started banners (admin role required).
  • Write (create/update/destroy):
    • Banners targeting a Client require an active ClientMembership on that Client with role OWNER or TECHNICAL.
    • Banners targeting a Practice require either:
      • an active PracticeMembership on that Practice with role ADMIN or OFFICE_MANAGER, or
      • an active ClientMembership on the Practice's Client with role OWNER (Owners can manage banners on any of their practices).
    • Crucially, a Practice admin cannot create Client-level banners — that requires explicit Client admin rights.

Cross-tenant safety: get_queryset always restricts to the user's accessible clients and practices, so a user in tenant A cannot see, list, or PATCH a banner in tenant B even by guessing UUIDs.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string <uuid>

A UUID string identifying this banner.

Request Body schema:
title
string <= 120 characters

Optional short heading shown above the message.

message
string non-empty

Plain-text banner body. HTML is not rendered by the client.

severity
string
Enum: "info" "warning" "urgent"

Visual treatment hint for the frontend (info/warning/urgent).

  • info - Info
  • warning - Warning
  • urgent - Urgent
starts_at
string <date-time>

UTC datetime the banner becomes active. Defaults to now.

expires_at
string <date-time>

UTC datetime after which the banner is no longer active.

client
string or null <uuid>

Client this banner targets. Mutually exclusive with practice.

practice
string or null <uuid>

Practice this banner targets. Mutually exclusive with client.

Responses

Request samples

Content type
{
  • "title": "string",
  • "message": "string",
  • "severity": "info",
  • "starts_at": "2019-08-24T14:15:22Z",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "title": "string",
  • "message": "string",
  • "severity": "info",
  • "starts_at": "2019-08-24T14:15:22Z",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "is_active": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

banner_destroy

CRUD for sign-in / pop-up banners attached to a Client or a Practice.

Permissions (deny-by-default):

  • All requests require an authenticated, non-patient staff user.
  • Read (list/retrieve): any user with an active membership in the banner's owning Client (for client-scoped banners) or Practice (for practice-scoped banners). By default the list returns only currently-active banners; pass ?include_expired=true to include expired and not-yet-started banners (admin role required).
  • Write (create/update/destroy):
    • Banners targeting a Client require an active ClientMembership on that Client with role OWNER or TECHNICAL.
    • Banners targeting a Practice require either:
      • an active PracticeMembership on that Practice with role ADMIN or OFFICE_MANAGER, or
      • an active ClientMembership on the Practice's Client with role OWNER (Owners can manage banners on any of their practices).
    • Crucially, a Practice admin cannot create Client-level banners — that requires explicit Client admin rights.

Cross-tenant safety: get_queryset always restricts to the user's accessible clients and practices, so a user in tenant A cannot see, list, or PATCH a banner in tenant B even by guessing UUIDs.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string <uuid>

A UUID string identifying this banner.

Responses

client

client_list

List and create client (organization) records for the current user.

GET /api/v1/client/ -- list the caller's accessible organizations (unchanged behaviour).

POST /api/v1/client/ -- create a new organization for the caller (api#469). Used by the first-run /getting-started wizard when the user has no existing clients. See :meth:post for the full contract.

Authorizations:
jwtAuthbearerAuthoauth2

Responses

Response samples

Content type
application/json
[
  • {
    }
]

DSO Reports

clients_reports_adjustments_retrieve

Per-practice adjustments breakdown by adj_type.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_uid
required
string <uuid>
query Parameters
end_date
string <date>

Inclusive end date (YYYY-MM-DD). Defaults to today.

start_date
string <date>

Inclusive start date (YYYY-MM-DD). Defaults to 30 days before end_date.

Responses

Response samples

Content type
application/json
{
  • "date_from": "string",
  • "date_to": "string",
  • "grand_total": "string",
  • "practices": [
    ]
}

clients_reports_ar_aging_retrieve

Four-bucket AR aging totals + per-practice breakdown.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_uid
required
string <uuid>
query Parameters
as_of
string <date>

Reference date for point-in-time aggregates (YYYY-MM-DD). Defaults to today.

Responses

Response samples

Content type
application/json
{
  • "as_of": "string",
  • "totals": {
    },
  • "practices": [
    ]
}

clients_reports_case_acceptance_retrieve

Per-practice case-acceptance rate with cross-practice rollup.

api#506 adds two pieces on top of the original contract:

  • Per-practice same_visit_accepted_pct and delayed_accepted_pct -- both expressed as a percentage of the presented amount so a stacked bar can read them directly.
  • ?procedure_category= -- comma-separated set of :class:apps.clinical.models.ServiceType codes (e.g. major,endodontics) that narrows the queryset to plan items whose linked :class:ProcedureCode.service_type is in the set. Items with no linked code are excluded once a filter is supplied.
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_uid
required
string <uuid>
query Parameters
end_date
string <date>

Inclusive end date (YYYY-MM-DD). Defaults to today.

procedure_category
string

Comma-separated list of ServiceType codes (diagnostic, preventive, basic, major, endodontics, periodontics, oral_surgery, orthodontics, prosthodontics, adjunctive, other). Narrows the queryset to plan items whose linked ProcedureCode.service_type falls in the supplied set.

start_date
string <date>

Inclusive start date (YYYY-MM-DD). Defaults to 30 days before end_date.

Responses

Response samples

Content type
application/json
{
  • "date_from": "string",
  • "date_to": "string",
  • "totals": {
    },
  • "practices": [
    ]
}

clients_reports_hygiene_recare_retrieve

Per-practice hygiene-recare compliance counts and rate.

api#507 adds two pieces:

  • avg_days_late_among_non_compliant per practice -- the mean number of days past date_due across the practice's overdue patients. Surfaces "narrowly missed" vs "long lost".
  • ?include_without_active_recare=true -- widens the denominator to include active patients with no recall row at all. Returned as a separate without_active_recare_count bucket so consumers can show "of every active patient, what fraction are actually on a recare track".
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_uid
required
string <uuid>
query Parameters
as_of
string <date>

Reference date for point-in-time aggregates (YYYY-MM-DD). Defaults to today.

include_without_active_recare
boolean

When true, widens the denominator to include active patients with no active recall row. These patients show up in a separate without_active_recare_count bucket and depress the compliance rate accordingly. Default false preserves the legacy denominator (active recall rows only).

Responses

Response samples

Content type
application/json
{
  • "as_of": "string",
  • "totals": {
    },
  • "practices": [
    ]
}

clients_reports_overview_retrieve

KPI tiles for the DSO landing page.

Returns four numbers per practice -- today's production, the trailing-week production, current AR total, and the 30-day no-show rate -- plus an org-wide totals block that sums the dollar values and computes a weighted no-show rate so the rollup tile isn't dominated by an outlier practice.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_uid
required
string <uuid>
query Parameters
as_of
string <date>

Reference date for point-in-time aggregates (YYYY-MM-DD). Defaults to today.

Responses

Response samples

Content type
application/json
{
  • "as_of": "string",
  • "totals": {
    },
  • "practices": [
    ]
}

clients_reports_payer_mix_retrieve

Per-practice payer mix derived from each patient's primary insurance.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "practices": [
    ]
}

clients_reports_production_by_provider_retrieve

Per-practice / per-provider production with production-per-hour.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_uid
required
string <uuid>
query Parameters
end_date
string <date>

Inclusive end date (YYYY-MM-DD). Defaults to today.

start_date
string <date>

Inclusive start date (YYYY-MM-DD). Defaults to 30 days before end_date.

Responses

Response samples

Content type
application/json
{
  • "date_from": "string",
  • "date_to": "string",
  • "practices": [
    ]
}

clients_reports_production_vs_collections_retrieve

Per-practice production / collections / adjustments table.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_uid
required
string <uuid>
query Parameters
end_date
string <date>

Inclusive end date (YYYY-MM-DD). Defaults to today.

start_date
string <date>

Inclusive start date (YYYY-MM-DD). Defaults to 30 days before end_date.

Responses

Response samples

Content type
application/json
{
  • "date_from": "string",
  • "date_to": "string",
  • "totals": {
    },
  • "practices": [
    ]
}

desktop

desktop_documents_sessions_retrieve

Get capture session status for crash recovery.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
session_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "status": "pending",
  • "workstation_name": "string",
  • "item_count": "string",
  • "created": "2019-08-24T14:15:22Z"
}

feedback

List feedback submissions (internal staff only).

Filters: ?status= (new / triaged / resolved), ?user= (submitter UUID), ?practice= (practice UUID), ?client= (client UUID), ?occurred_from= / ?occurred_to= (calendar-day range on created, UTC, inclusive of both endpoints, YYYY-MM-DD). Ordered by -created (newest first). Returns the compact list shape; open the detail view to read the full submission including the signed screenshot URL.

Authorizations:
jwtAuthbearerAuthoauth2
query Parameters
client
string <uuid>

Filter by client UUID.

occurred_from
string <date>

Filter rows whose created timestamp (UTC) falls on or after this calendar date (YYYY-MM-DD). Invalid date format returns 400.

occurred_to
string <date>

Filter rows whose created timestamp (UTC) falls on or before this calendar date (YYYY-MM-DD); the endpoint is inclusive of the entire day. Invalid date format returns 400.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

practice
string <uuid>

Filter by practice UUID.

status
string

Filter by triage status: new / triaged / resolved.

user
string <uuid>

Filter by submitter user UUID.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

Submit in-app feedback (any authenticated staff user).

Accepts a feedback submission from the staff feedback widget. Body may be either application/json (no screenshot) or multipart/form-data (screenshot attached as the screenshot field). The submitting user is set server-side from request.user -- a client-supplied user value is ignored. The row is treated as PHI on the read side.

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
required
practice
string or null <uuid>

Practice context at submission time, when known.

title
required
string [ 1 .. 80 ] characters

One-line summary the submitter typed into the feedback widget.

details
required
string non-empty

Long-form description of the issue.

screenshot
string <binary>

Optional screenshot of the page the bug was observed on (private bucket).

url
string <= 2000 characters

Page URL the feedback was submitted from.

viewport
any

Browser viewport metadata (width / height / devicePixelRatio).

user_agent
string <= 1024 characters

User-Agent string at submission time.

js_errors
any

Recent JS console errors with timestamps (widget-owned shape).

Responses

Request samples

Content type
{
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "title": "string",
  • "details": "string",
  • "screenshot": "string",
  • "url": "string",
  • "viewport": null,
  • "user_agent": "string",
  • "js_errors": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "user": "76f62a58-5404-486d-9afc-07bded328704",
  • "submitter_email": "user@example.com",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "title": "string",
  • "details": "string",
  • "screenshot_url": "string",
  • "url": "string",
  • "viewport": null,
  • "user_agent": "string",
  • "js_errors": null,
  • "status": "new",
  • "triaged_by": "918c35b9-bedc-437d-84b5-ebe932e91c8b",
  • "triaged_by_email": "user@example.com",
  • "triaged_at": "2019-08-24T14:15:22Z",
  • "resolved_by": "d0d57369-b08b-4db8-8952-8cdeedd9aebc",
  • "resolved_by_email": "user@example.com",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolution_note": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

Read a single feedback submission (internal staff only).

Returns the full row, including a short-lived signed URL for the screenshot when one was attached. Every read fires a feedback.viewed audit event because the row may carry incidentally captured PHI.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
feedback_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "user": "76f62a58-5404-486d-9afc-07bded328704",
  • "submitter_email": "user@example.com",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "title": "string",
  • "details": "string",
  • "screenshot_url": "string",
  • "url": "string",
  • "viewport": null,
  • "user_agent": "string",
  • "js_errors": null,
  • "status": "new",
  • "triaged_by": "918c35b9-bedc-437d-84b5-ebe932e91c8b",
  • "triaged_by_email": "user@example.com",
  • "triaged_at": "2019-08-24T14:15:22Z",
  • "resolved_by": "d0d57369-b08b-4db8-8952-8cdeedd9aebc",
  • "resolved_by_email": "user@example.com",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolution_note": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

Transition a feedback row's status (internal staff only).

Valid target statuses: new / triaged / resolved. Side effects: moving out of new for the first time stamps triaged_by / triaged_at; moving to resolved stamps resolved_by / resolved_at; bouncing back to new or triaged clears the resolved-stamp pair so the field always reflects the current state.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
feedback_uid
required
string <uuid>
Request Body schema:
required
status
required
string (FeedbackStatusEnum)
Enum: "new" "triaged" "resolved"
  • new - New
  • triaged - Triaged
  • resolved - Resolved
resolution_note
string
Default: ""

Responses

Request samples

Content type
{
  • "status": "new",
  • "resolution_note": ""
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "user": "76f62a58-5404-486d-9afc-07bded328704",
  • "submitter_email": "user@example.com",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "title": "string",
  • "details": "string",
  • "screenshot_url": "string",
  • "url": "string",
  • "viewport": null,
  • "user_agent": "string",
  • "js_errors": null,
  • "status": "new",
  • "triaged_by": "918c35b9-bedc-437d-84b5-ebe932e91c8b",
  • "triaged_by_email": "user@example.com",
  • "triaged_at": "2019-08-24T14:15:22Z",
  • "resolved_by": "d0d57369-b08b-4db8-8952-8cdeedd9aebc",
  • "resolved_by_email": "user@example.com",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolution_note": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

FHIR Bulk Data

Kick off a FHIR Bulk Data ($export) job.

System-level FHIR Bulk Data Access $export. Returns 202 with a Content-Location header pointing at the poll URL. The job runs asynchronously and writes one NDJSON file per requested resource type to private object storage.

Authorizations:
jwtAuthbearerAuthoauth2
query Parameters
_since
string <date-time>

Only emit resources modified at or after this ISO-8601 datetime (must be tz-aware).

_type
string

Comma-separated FHIR resource types to export. Defaults to all supported types.

header Parameters
X-Practice-UID
string <uuid>

Practice UUID; required when the token grants access to multiple practices.

Responses

Response samples

Content type
application/json
{
  • "property1": null,
  • "property2": null
}

Poll a FHIR Bulk Data ($export) job.

Returns 202 + X-Progress header while the job is running; 200 with the IG-defined manifest when complete; 200 with an empty output when the job was cancelled or failed.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
job_uid
required
string <uuid>
header Parameters
X-Practice-UID
string <uuid>

Practice UUID; required when the token grants access to multiple practices.

Responses

Response samples

Content type
application/json
{
  • "property1": null,
  • "property2": null
}

Cancel a FHIR Bulk Data ($export) job.

Marks the job as cancelled. The Celery worker checks the row's status between resource types and exits cleanly.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
job_uid
required
string <uuid>
header Parameters
X-Practice-UID
string <uuid>

Practice UUID; required when the token grants access to multiple practices.

Responses

Response samples

Content type
application/json
{
  • "property1": null,
  • "property2": null
}

Forms

forms_kiosk_retrieve

GET /api/v1/forms/kiosk/<token>/

Token-scoped read. Returns the kiosk session state, the currently- loaded sendout (if any), and the templates the device should render. A request against an ended / idled-out session returns 410 Gone.

The state read DOES bump last_activity_at — a tablet that polls every few seconds keeps the session alive, which is the intended UX: idle timeout only fires when the patient walks away.

Authorizations:
bearerAuthoauth2
path Parameters
token
required
string

Responses

forms_kiosk_submit_create

POST /api/v1/forms/kiosk/<token>/submit/

Body shape mirrors :class:PublicSubmitView{ "submissions": [...] }. Differences from the patient-portal public submit:

  • The session must be active; an expired session returns 410 Gone.
  • A loaded :class:FormSendOut is required; submitting against a session with current_sendout=None is a 400 (the kiosk shouldn't be rendering a form yet anyway).
  • Submissions are tagged submitted_via='kiosk'; the submitted_via field in the payload is ignored if present.
  • The sendout's status is NOT flipped to submitted: staff may want to load another form on the same kiosk for the same patient, so closing the sendout here would force the staff client to mint a fresh sendout for every form. Staff close out the sendout from their UI when the visit ends.
  • Every accepted submission stamps last_activity_at on the kiosk session so a fast-filling patient keeps the deadline pushed out.

Note: the chart-attach + mapping-proposal signals fire on every :class:FormSubmission regardless of channel, so kiosk submissions get the same downstream pipeline (PDF in the chart, staged patient- record writes) as portal / signed-link submissions.

Authorizations:
bearerAuthoauth2
path Parameters
token
required
string

Responses

forms_public_retrieve

GET /api/v1/forms/public// — render template + in-progress state.

No auth. Open access is intentional: the token IS the credential. The token is single-use only in the sense that status=submitted rejects further submissions; reads (this endpoint) stay available so the patient can review what they sent.

Authorizations:
bearerAuthoauth2
path Parameters
token
required
string

Responses

forms_public_submit_create

POST /api/v1/forms/public//submit/

Body shape: { "submissions": [ { "template_id": "<uuid>", "submitted_via": "link|portal|kiosk", "responses": [ { "field_id": "<uuid>", "value": "..." } ] } ] }

The endpoint pins each submission to the exact :class:FormTemplate row served by the public GET endpoint, so a staff edit landing mid-fill does not retroactively rewrite the patient's responses.

Authorizations:
bearerAuthoauth2
path Parameters
token
required
string

Responses

practice_forms_bundles_list

List or create form bundles.

GET is open to any authenticated staff (no role check). POST is gated to manager-or-above via :class:IsManagerOrAbove — same write-side guardrail the spec for api#769 requires. The IsManagerOrAbove permission allows safe methods through unconditionally, so a single permission_classes list covers both cases without a per-method override.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_forms_bundles_create

List or create form bundles.

GET is open to any authenticated staff (no role check). POST is gated to manager-or-above via :class:IsManagerOrAbove — same write-side guardrail the spec for api#769 requires. The IsManagerOrAbove permission allows safe methods through unconditionally, so a single permission_classes list covers both cases without a per-method override.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 200 ] characters
description
string
is_default_new_patient
boolean

When true, this bundle is the practice's default new-patient intake packet (api#769). Setting this true on a row clears the flag on any sibling bundle in the same practice — at most one default per practice. False on any number of rows is fine.

template_ids
Array of strings <uuid> [ items <uuid > ]

Ordered list of FormTemplate UUIDs to include.

Responses

Request samples

Content type
{
  • "name": "string",
  • "description": "string",
  • "is_default_new_patient": true,
  • "template_ids": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "description": "string",
  • "is_default_new_patient": true,
  • "items": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_forms_bundles_retrieve

Retrieve, update, or delete a form bundle.

Update + delete are gated to manager-or-above (api#769); retrieve stays open to any authenticated staff thanks to :class:IsManagerOrAbove letting safe methods through.

Delete cascades to :class:FormBundleItem rows (the FK is CASCADE) but PROTECTs against orphaning a :class:FormSendOut that still references the bundle — staff must archive the sendout first. The PROTECT raises :class:django.db.models.ProtectedError, which DRF's default exception handler maps to 409 Conflict.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
bundle_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "description": "string",
  • "is_default_new_patient": true,
  • "items": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_forms_bundles_partial_update

Retrieve, update, or delete a form bundle.

Update + delete are gated to manager-or-above (api#769); retrieve stays open to any authenticated staff thanks to :class:IsManagerOrAbove letting safe methods through.

Delete cascades to :class:FormBundleItem rows (the FK is CASCADE) but PROTECTs against orphaning a :class:FormSendOut that still references the bundle — staff must archive the sendout first. The PROTECT raises :class:django.db.models.ProtectedError, which DRF's default exception handler maps to 409 Conflict.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
bundle_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
name
string [ 1 .. 200 ] characters
description
string
is_default_new_patient
boolean

When true, this bundle is the practice's default new-patient intake packet (api#769). Setting this true on a row clears the flag on any sibling bundle in the same practice — at most one default per practice. False on any number of rows is fine.

template_ids
Array of strings <uuid> [ items <uuid > ]

Ordered list of FormTemplate UUIDs to include.

Responses

Request samples

Content type
{
  • "name": "string",
  • "description": "string",
  • "is_default_new_patient": true,
  • "template_ids": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "description": "string",
  • "is_default_new_patient": true,
  • "items": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_forms_bundles_destroy

Retrieve, update, or delete a form bundle.

Update + delete are gated to manager-or-above (api#769); retrieve stays open to any authenticated staff thanks to :class:IsManagerOrAbove letting safe methods through.

Delete cascades to :class:FormBundleItem rows (the FK is CASCADE) but PROTECTs against orphaning a :class:FormSendOut that still references the bundle — staff must archive the sendout first. The PROTECT raises :class:django.db.models.ProtectedError, which DRF's default exception handler maps to 409 Conflict.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
bundle_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_forms_bundles_default_new_patient_retrieve

Return the practice's default new-patient bundle (api#769).

Convenience endpoint for the staff web's "Send new patient forms" entry point — saves a list-then-filter round-trip. Returns 404 if no bundle on this practice has is_default_new_patient=True.

Read access is open to any authenticated staff; there is no write surface on this URL — flipping the flag goes through :class:FormBundleDetailView PATCH.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "description": "string",
  • "is_default_new_patient": true,
  • "items": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_forms_kiosk_sessions_list

GET / POST /api/v1/practice/<uid>/forms/kiosk-sessions/

GET lists kiosk sessions for the practice (most-recent first). POST mints a fresh device-bound session — body accepts device_label and idle_timeout_seconds (both optional); token and kiosk_url come back in the response so the staff client can immediately point a tablet at the URL.

Only one server-side endpoint creates kiosk rows; the public token path never produces them. This keeps the create path firmly behind staff auth + the practice scope check.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_forms_kiosk_sessions_create

GET / POST /api/v1/practice/<uid>/forms/kiosk-sessions/

GET lists kiosk sessions for the practice (most-recent first). POST mints a fresh device-bound session — body accepts device_label and idle_timeout_seconds (both optional); token and kiosk_url come back in the response so the staff client can immediately point a tablet at the URL.

Only one server-side endpoint creates kiosk rows; the public token path never produces them. This keeps the create path firmly behind staff auth + the practice scope check.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
device_label
string <= 120 characters

Optional human-readable label, e.g. 'Front desk tablet 1'.

idle_timeout_seconds
integer [ 0 .. 2147483647 ]

Seconds of inactivity after which the session is considered expired (default 10 minutes).

Responses

Request samples

Content type
{
  • "device_label": "string",
  • "idle_timeout_seconds": 2147483647
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "device_label": "string",
  • "idle_timeout_seconds": 2147483647,
  • "token": "b5507016-7da2-4777-a161-1e8042a6a377",
  • "started_at": "2019-08-24T14:15:22Z",
  • "last_activity_at": "2019-08-24T14:15:22Z",
  • "ended_at": "2019-08-24T14:15:22Z",
  • "current_sendout": "5fd310e5-0160-4f65-852a-6661765cf842",
  • "kiosk_url": "string"
}

practice_forms_kiosk_sessions_retrieve

GET /api/v1/practice/<uid>/forms/kiosk-sessions/<id>/

Staff-facing retrieve. Mutations live on dedicated action endpoints (/load-sendout/ and /end/) so each verb carries its own audit event and validation rules.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
session_id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "device_label": "string",
  • "idle_timeout_seconds": 0,
  • "token": "b5507016-7da2-4777-a161-1e8042a6a377",
  • "started_at": "2019-08-24T14:15:22Z",
  • "last_activity_at": "2019-08-24T14:15:22Z",
  • "ended_at": "2019-08-24T14:15:22Z",
  • "is_active": true,
  • "current_sendout": "5fd310e5-0160-4f65-852a-6661765cf842",
  • "kiosk_url": "string"
}

practice_forms_kiosk_sessions_end_create

POST /api/v1/practice/<uid>/forms/kiosk-sessions/<id>/end/

Explicitly terminates a kiosk session. Idempotent — re-ending a session that already ended is a 200 with the existing row, not a 409 or 410 (the staff client may double-click the End button).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
session_id
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_forms_kiosk_sessions_load_sendout_create

POST /api/v1/practice/<uid>/forms/kiosk-sessions/<id>/load-sendout/

Assigns a :class:FormSendOut to the kiosk session so the device can pull it on the next public state read. The sendout must belong to the same practice as the kiosk and must not already be submitted or expired — those would render an empty form.

Loading a new sendout on a session that already had one is allowed (and intentional: the kiosk flow is "patient finishes form, staff walks over and taps Load Next Form" — the same session can host a series of submissions for one patient).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
session_id
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_forms_mapping_proposals_list

GET /api/v1/practice/<uid>/forms/mapping-proposals/

Filterable by ?submission=<uuid>, ?status=<pending|approved|rejected>, and ?patient=<uuid>. Returns the same shape the detail endpoint serves, paginated by the project default.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_forms_mapping_proposals_retrieve

GET /api/v1/practice/<uid>/forms/mapping-proposals/<id>/

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
proposal_id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "submission": "1b93aee1-8240-405b-a875-ba2e84126725",
  • "submission_template": "0e3de4ce-1a0e-4d8c-a5c3-c059c0cf2f70",
  • "field_response": "0909d828-03ff-42b0-9055-4ddb448a6b02",
  • "field_label": "string",
  • "field_type": "string",
  • "target_patient_field": "string",
  • "proposed_value": "string",
  • "current_patient_value_snapshot": "string",
  • "status": "pending",
  • "reviewed_by": "92ab4dbc-1b27-40ce-b24b-7dde8f4709be",
  • "reviewed_by_email": "user@example.com",
  • "reviewed_at": "2019-08-24T14:15:22Z",
  • "review_notes": "string",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_forms_mapping_proposals_approve_create

POST /api/v1/practice/<uid>/forms/mapping-proposals/<id>/approve/

Body: {"notes": "optional"}.

Idempotent — re-approving an already-approved proposal is a no-op that returns 200 with the existing row. Approving a previously rejected proposal is rejected with 409 (Conflict): the staff member should file a new submission / sendout cycle if they want to revisit.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
proposal_id
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_forms_mapping_proposals_reject_create

POST /api/v1/practice/<uid>/forms/mapping-proposals/<id>/reject/

Body: {"notes": "required"}.

A non-blank notes is required so the audit trail explains why the proposed change did not land. Re-rejecting an already-rejected proposal is idempotent. Rejecting a previously approved proposal is a 409 — once the patient record changed, it's the staff member's job to walk it back via the appropriate patient-edit endpoint.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
proposal_id
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_forms_mapping_proposals_bulk_approve_create

POST /api/v1/practice/<uid>/forms/mapping-proposals/bulk-approve/

Body: {"ids": [<uuid>, ...], "notes": "optional"}.

All-or-nothing: a single validation failure (unknown target field, bad date format, etc.) rolls back the entire batch. Already-approved proposals are no-ops inside the batch; already-rejected proposals abort the batch with 409 — matching the single-row endpoint's semantics.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_forms_sendouts_list

List or create sendouts.

Creating a sendout mints a fresh signed link the staff can hand to the patient; reads return the list filtered by ?status= and ?patient=.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_forms_sendouts_create

List or create sendouts.

Creating a sendout mints a fresh signed link the staff can hand to the patient; reads return the list filtered by ?status= and ?patient=.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
patient
required
string <uuid>
bundle
string or null <uuid>
template
string or null <uuid>

Set when sending exactly one template without a bundle.

channel
string
Enum: "email" "sms" "kiosk"

Delivery channel for the patient-facing link (api#748). Email and SMS dispatch a Celery notification at create + resend; kiosk is a no-op (staff loads the sendout from the kiosk control panel).

  • email - Email
  • sms - SMS
  • kiosk - In-office kiosk
expires_at
string <date-time>

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "bundle": "6350974e-b7e0-4bb6-8ec3-333ab03ecfbf",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "channel": "email",
  • "expires_at": "2019-08-24T14:15:22Z"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "bundle": "6350974e-b7e0-4bb6-8ec3-333ab03ecfbf",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "channel": "email",
  • "token": "string",
  • "status": "pending",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "public_url": "string",
  • "created": "2019-08-24T14:15:22Z"
}

practice_forms_sendouts_retrieve

GET /api/v1/practice/<uid>/forms/sendouts/<id>/ (api#654).

Practice-scoped retrieve. Closes the gap that forced the web detail page (web#532 / web#535) to walk the paginated list endpoint to render a single row. Cross-tenant access returns 404 -- the sendout's existence is not leaked to a foreign practice.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
sendout_id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "patient_name": "string",
  • "bundle": "6350974e-b7e0-4bb6-8ec3-333ab03ecfbf",
  • "bundle_name": "string",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "template_name": "string",
  • "channel": "email",
  • "token": "string",
  • "status": "pending",
  • "expires_at": "2019-08-24T14:15:22Z",
  • "opened_at": "2019-08-24T14:15:22Z",
  • "submitted_at": "2019-08-24T14:15:22Z",
  • "last_resent_at": "2019-08-24T14:15:22Z",
  • "created": "2019-08-24T14:15:22Z"
}

practice_forms_sendouts_cancel_create

POST /api/v1/practice/<uid>/forms/sendouts/<id>/cancel/ (api#654).

Flip status to :attr:SendOutStatus.ARCHIVED so the sendout no longer blocks template archive and the patient-side endpoint stops accepting submissions against the token.

Status semantics

* ``pending`` / ``in_progress`` -> ``archived`` + audit event.
* ``archived`` / ``expired`` -> 200 idempotent re-cancel; audit
  event still fires so the trail captures the intent regardless
  of state (mirrors the template-archive contract).
* ``submitted`` -> 409.  A completed sendout is history; the
  patient already filled the form and the chart already carries
  the submission.  Cancelling here would lie to the audit trail
  about what really happened.

The transition is a single-column UPDATE so a racing transition
on the same row (e.g. the patient submitting between our
``select_for_update`` and the write) can't trample the
``modified`` timestamp on either side; we re-check the row
inside the same transaction to keep the contract honest.
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
sendout_id
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_forms_sendouts_resend_create

POST /api/v1/practice/<uid>/forms/sendouts/<id>/resend/ (api#655).

Re-broadcast the patient-facing notification for sendout_id using the SAME token (no new credential is minted -- staff explicitly asked for "send the same link again"). Throttled to at most one delivery per :data:RESEND_THROTTLE window per sendout so a button-mash does not spam the patient.

Lifecycle gating

* ``pending`` / ``in_progress`` -- allowed.
* ``submitted`` / ``expired`` / ``archived`` -- rejected with 409.
  A submitted form has nothing to remind about; an expired or
  cancelled token would land the patient on a 410 the moment they
  tap the link.

Throttle contract

Returns 429 with {"detail": "...", "next_resend_at": "<iso>"} when the previous resend landed inside the window. The web client uses next_resend_at to gray out the button until the deadline elapses without polling.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
sendout_id
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_forms_sendouts_submissions_list

GET /api/v1/practice/<uid>/forms/sendouts/<id>/submissions/ (api#656).

List :class:FormSubmission rows attached to sendout_id, newest first. Single-template sendouts return a 0-or-1 row list; bundle sendouts return one row per template the patient completed.

Scoping

The parent sendout is resolved against the practice queryset before
we list, so a foreign practice's submissions are unreachable even
when the staff user guesses the bundle's child IDs.  Returns the
same paginated envelope as every other list endpoint.
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
sendout_id
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_forms_sendouts_submissions_latest_retrieve

GET /api/v1/practice/<uid>/forms/sendouts/<id>/submissions/latest/ (api#656).

Convenience endpoint that returns the single most-recent :class:FormSubmission for sendout_id -- the row a staff member is most likely to want when clicking "View submission" on the detail page. Returns 404 when the sendout has no submissions yet (patient hasn't filled the form), so the web client can treat the absence as a non-error "nothing to show" state without parsing a list envelope.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
sendout_id
required
string <uuid>

Responses

practice_forms_submissions_pdf_retrieve

GET /api/v1/practice//forms/submissions//pdf/

Render a completed :class:FormSubmission as a human-readable PDF and stream it to the caller with Content-Type: application/pdf.

The same renderer powers the Celery task that auto-attaches the PDF to the patient's chart on submit (api#620 / escape#156); this endpoint exists so staff can re-download the snapshot on demand without having to dig through the doccenter.

Scoping

Practice-scoped — the submission must belong to a sendout owned by the URL-supplied practice. Cross-tenant access produces a 404 rather than a 403 so the existence of a foreign submission isn't leaked.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
submission_id
required
string <uuid>

Responses

practice_forms_templates_list

List or create form templates for a practice.

GET /v1/practice//forms/templates/?active=true|false|all POST /v1/practice//forms/templates/

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_forms_templates_create

List or create form templates for a practice.

GET /v1/practice//forms/templates/?active=true|false|all POST /v1/practice//forms/templates/

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 200 ] characters
description
string
Array of objects (FormFieldRequest)
prefill_map
any

Map of FormField.label (or template field name) -> dotted attribute path on the Patient row that should pre-populate that field on the kiosk / portal renderer (api#772). Shape: {field_name: 'patient.attribute_dotted_path'}. Example: {'First name': 'first_name', 'Insurance member ID': 'insurance_enrollments.first.subscriber_id'}. Resolution is best-effort and read-only -- absent attributes / null values are omitted from the response so the renderer treats them as 'user must fill in'. See :func:apps.forms.prefill.resolve_prefill for traversal rules.

Responses

Request samples

Content type
{
  • "name": "string",
  • "description": "string",
  • "fields": [
    ],
  • "prefill_map": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "version_group": "270269c2-f759-4e54-adee-ae78012a3e32",
  • "version": 1,
  • "name": "string",
  • "description": "string",
  • "is_active": true,
  • "fields": [
    ],
  • "prefill_map": null,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_forms_templates_retrieve

Retrieve or update a form template.

GET /v1/practice//forms/templates// PATCH /v1/practice//forms/templates//

PATCH semantics: * Editing a template that has zero submissions updates in place. * Editing a template that has any submissions archives the row (is_active=False) and returns a fresh version=N+1 row with the edits applied. Past submissions stay pinned to the archived row.

PUT is intentionally unsupported — full-replace edits over a versioned document are confusing semantically.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "version_group": "270269c2-f759-4e54-adee-ae78012a3e32",
  • "version": 1,
  • "name": "string",
  • "description": "string",
  • "is_active": true,
  • "fields": [
    ],
  • "prefill_map": null,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_forms_templates_partial_update

Retrieve or update a form template.

GET /v1/practice//forms/templates// PATCH /v1/practice//forms/templates//

PATCH semantics: * Editing a template that has zero submissions updates in place. * Editing a template that has any submissions archives the row (is_active=False) and returns a fresh version=N+1 row with the edits applied. Past submissions stay pinned to the archived row.

PUT is intentionally unsupported — full-replace edits over a versioned document are confusing semantically.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_id
required
string <uuid>
Request Body schema:
name
string [ 1 .. 200 ] characters
description
string
Array of objects (FormFieldRequest)
prefill_map
any

Map of FormField.label (or template field name) -> dotted attribute path on the Patient row that should pre-populate that field on the kiosk / portal renderer (api#772). Shape: {field_name: 'patient.attribute_dotted_path'}. Example: {'First name': 'first_name', 'Insurance member ID': 'insurance_enrollments.first.subscriber_id'}. Resolution is best-effort and read-only -- absent attributes / null values are omitted from the response so the renderer treats them as 'user must fill in'. See :func:apps.forms.prefill.resolve_prefill for traversal rules.

Responses

Request samples

Content type
{
  • "name": "string",
  • "description": "string",
  • "fields": [
    ],
  • "prefill_map": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "version_group": "270269c2-f759-4e54-adee-ae78012a3e32",
  • "version": 1,
  • "name": "string",
  • "description": "string",
  • "is_active": true,
  • "fields": [
    ],
  • "prefill_map": null,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_forms_templates_archive_create

POST /api/v1/practice/<uid>/forms/templates/<id>/archive/

Flip is_active=False on the template so it disappears from the active-templates list staff hand out. Historical sendouts and submissions remain pinned to the archived row — versioning is immutable — so existing chart entries stay defensible.

Idempotent: re-archiving an already-archived template is a 200 with the current serialized row. Both archive and re-archive emit the form_template.archived audit event so the trail captures the intent regardless of state.

Conflict

Returns ``409 Conflict`` with ``open_sendout_ids`` when at least one
:class:`FormSendOut` referencing this template is still in a non-
resolved status (``pending`` or ``in_progress``).  The web client
surfaces this as "close N outstanding sendouts first" so staff don't
accidentally orphan an in-flight patient packet.
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_id
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_forms_templates_unarchive_create

POST /api/v1/practice/<uid>/forms/templates/<id>/unarchive/

Flip is_active=True on the template so it reappears in the active-templates list. Idempotent: re-unarchiving an already-active template is a 200 with the current serialized row.

Note that the versioning invariant says only one row per version_group can be active at a time, but the model does NOT currently enforce that with a partial unique index. Unarchive does not auto-archive a competing active version — staff are expected to use the archive endpoint first if they want to swap which version is live, and the API surfaces both endpoints as independent verbs. A future hardening pass can add a deferred-unique constraint if the competing-versions case becomes a real footgun.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_id
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_forms_prefill_retrieve

GET /api/v1/practice/<uid>/patient/<patient_id>/forms/<template_id>/prefill/

Resolve a form template's :attr:FormTemplate.prefill_map against a specific patient and return the values the kiosk / portal should pre-populate (api#772).

Auth

Two acceptable callers:

* **Staff session** -- gated to manager-or-above through
  :class:`IsManagerOrAbove`.  Same convention as the bundle
  endpoints: pre-fill data is PHI (patient demographics + insurance
  identifiers) so front-desk-only roles don't get it.
* **Paired tablet bearer** -- a tablet whose
  :attr:`apps.tablets.models.Tablet.practice` matches the URL
  practice may hit the endpoint.  This is the kiosk path: the
  tablet renderer asks for pre-fill values before showing the
  patient the form.

A request authenticated as a tablet paired with a DIFFERENT
practice is rejected with 403 -- the URL practice is the source
of truth and a paired-elsewhere tablet must not see another
office's patient data even with a valid bearer.

Response shape

.. code:: json

{
  "template_id": "...",
  "values": {
    "First name": "Jane",
    "Date of birth": "1985-05-22"
  }
}

Empty prefill_map, missing patient attributes, and null values all surface as an empty / shorter values dict -- the renderer treats absent keys as "user must fill in" so the resolver is permissively quiet.

Errors

* 404 when the template or patient doesn't exist in this practice.
* 403 when a tablet bearer is paired with a different practice or
  a staff caller is below manager rank.
* 401 when no authentication credentials are supplied at all.
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
template_id
required
string <uuid>

Responses

OAuth

Mint a single-use launch JWT for a 3rd-party app

Mint a short-lived launch JWT bound to (user, application, practice).

The returned JWT carries aud=<client_id>, sub=user:<uid>, practice=<uid>, exp (now + 60 s), and a fresh jti. The jti is recorded in :class:LaunchTokenJTI before the response is returned so the exchange endpoint can detect replays.

Permission stack:

  1. IsAuthenticated -- session or bearer; practically staff sessions from the web nine-dots.
  2. IsStaffUser -- patient users cannot launch 3rd-party apps.
  3. Explicit check that the authenticated user has practice access.
  4. Explicit check that the user's active :class:OAuthPracticeGrant authorizes this app for this practice.
  5. Rate limit (see :class:LaunchTokenCreateThrottle).
Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
required
application
required
string non-empty

OAuth2 Application.client_id of the 3rd-party app to launch.

practice
required
string <uuid>

UUID of the practice the launch will be scoped to.

Responses

Request samples

Content type
{
  • "application": "string",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2"
}

Response samples

Content type
application/json
{
  • "launch_token": "string",
  • "expires_in": 0
}

List the 3rd-party apps with delegated access to your account

Returns every OAuth application for which the caller holds at least one active act_on_behalf-scoped access token, enriched with first_granted_at from the backing grant and last_used_at from the usage-metric rollup. Powers the Connected Apps settings page. No practice filter -- delegated apps are scoped to the user, not to any single practice membership.

Authorizations:
jwtAuthbearerAuthoauth2

Responses

Response samples

Content type
application/json
{
  • "count": 0,
  • "results": [
    ]
}

Revoke a 3rd-party app's delegated access to your account

Invalidates every act_on_behalf-scoped grant and token held by the signing-in user for the target app. The app's practice-level authorization is not affected -- that is governed separately by the practice owner via the Security Nexus.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
app_id
required
string

Responses

Response samples

Content type
application/json
{
  • "grants_revoked": 0,
  • "tokens_revoked": 0
}

Tablets

oauth_tablet_pair_create

Public pair-completion endpoint.

No authentication is required -- the unguessable pair_token IS the auth. The endpoint:

  1. Verifies the JWT signature + expiry.
  2. Confirms the named practice exists (404 cross-tenant guess protection -- a JWT for a since-deleted practice resolves to a clean 404 instead of a 500).
  3. Atomically: a. Inserts :class:PairTokenRedemption (Postgres unique constraint races a second redemption into 410). b. Creates the :class:Tablet row from the JWT claims + posted public key. c. Mints a DOT AccessToken + RefreshToken bound to the escape-kiosk-tablet Application and the new Tablet.
  4. Returns the access + refresh token values, the tablet id, the tablet name, and the practice id so the device can begin making authenticated calls immediately.
Authorizations:
bearerAuthoauth2None
Request Body schema:
required
pair_token
required
string [ 1 .. 4096 ] characters

Pair-token JWT issued by the staff-side pair-token endpoint.

public_key
required
string [ 1 .. 4096 ] characters

Base64-encoded ECDSA P-256 public key (DER SubjectPublicKeyInfo) the tablet just generated.

Responses

Request samples

Content type
{
  • "pair_token": "string",
  • "public_key": "string"
}

practice_kiosk_check_in_create

POST /api/v1/practice//kiosk/check-in/.

Tablet-authenticated. The DRF default auth chain includes :class:apps.tablets.authentication.TabletOAuth2Authentication, which attaches request.tablet when the bearer is a paired tablet's access token. Anything else (staff session, third-party OAuth app, no token at all) is rejected with 401 -- the kiosk check-in surface is exclusively for the in-office tablet, not a general write surface.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
last_name
required
string [ 1 .. 100 ] characters
dob
required
string <date>

Patient date of birth, ISO-8601 (YYYY-MM-DD).

Responses

Request samples

Content type
{
  • "last_name": "string",
  • "dob": "2019-08-24"
}

Response samples

Content type
application/json
{
  • "appointment_uid": "8f39db43-9e43-49ac-b3d9-d5d6ba2d63d8",
  • "scheduled_at": "2019-08-24T14:15:22Z",
  • "checked_in_at": "2019-08-24T14:15:22Z"
}

practice_tablets_list

Return every Tablet (revoked included) at the calling practice.

Why include revoked rows? Revoked tablets show up in the audit trail and the staff settings page wants to render them in a "Recently retired" section so an operator who revokes the wrong device can immediately see the mistake. The serializer's is_revoked derived field carries the distinction.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

practice_tablets_clear_create

POST a 'reset to home screen' message to a paired tablet (api#760).

Endpoint::

POST /api/v1/practice/<practice_uid>/tablets/<tablet_id>/clear/

Mirrors :class:TabletRevokeView's permission + scoping pattern (manager+ on the practice) and reuses the channel-layer dispatch pattern :class:TabletSendView already wires up. Body is empty.

Why a separate endpoint instead of letting staff POST send/ with {"action": "clear_screen"}?

The "Clear Tablet" Settings control should not require the web app to know about the action vocabulary -- the action verb is an implementation detail of the kiosk handshake. A dedicated endpoint keeps the staff-side contract simple ("clear this tablet") and lets the api evolve the underlying WS verb without breaking the UI. It also gives the audit log a distinct event type (tablet.cleared vs. tablet.message_sent) so operators can count clear actions independently of generic send activity.

HIPAA contract

The WS message carries no PHI -- just the verb. The audit event metadata carries the tablet id and the actor user only.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
tablet_id
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_tablets_form_session_submit_create

POST /api/v1/practice//tablets//form-session/submit/.

Tablet-authenticated. See module docstring for the full contract.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
tablet_id
required
string <uuid>
Request Body schema:
required
session_id
required
string <uuid>

form_session correlation UUID returned by the staff-side send/ endpoint at session creation (api#771). Must match the action the tablet is currently riding.

template_id
required
string <uuid>

The :class:FormTemplate this submission answers.

values
any

Field-label -> value map the tablet captured. Persisted verbatim onto FormSubmission.values; tablet writebacks do NOT spawn per-field FormFieldResponse rows.

signature_b64
string
Default: ""

Optional base64-encoded signature image captured at submit time. Decoded server-side and persisted as a Signature row attached to the submission's GFK so the legal evidence row survives the submission's lifecycle. Accepts a bare base64 payload OR a full data:image/png;base64,... URL.

Responses

Request samples

Content type
{
  • "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
  • "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  • "values": null,
  • "signature_b64": ""
}

Response samples

Content type
application/json
{
  • "submission_id": "945dfedc-ad7f-4af7-b20c-06082ffa3cb3",
  • "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
  • "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  • "patient_id": "3854866a-5476-48be-8313-77029ccdd7a7",
  • "new_patient_draft_id": "274f35f0-b5bd-440d-9e9e-d06ad4a01c18",
  • "draft_status": "string",
  • "bundle_completed": true
}

practice_tablets_rename_create

Rename an existing tablet without re-pairing.

Staff manager+ surface. The new name must be unique across active tablets at the practice -- same rule the model's conditional unique constraint enforces, but checked at write time so the API returns a clean 400 instead of an opaque 500.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
tablet_id
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 64 ] characters

New staff-assigned label.

Responses

Request samples

Content type
{
  • "name": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "paired_at": "2019-08-24T14:15:22Z",
  • "last_seen_at": "2019-08-24T14:15:22Z",
  • "revoked_at": "2019-08-24T14:15:22Z",
  • "is_stale": true,
  • "is_revoked": true,
  • "paired_by_email": "string",
  • "revoked_by_email": "string"
}

practice_tablets_revoke_create

Soft-delete a tablet and revoke its OAuth tokens.

POST-only -- the action is a state transition (active -> revoked), not a DELETE of the row. Idempotent: re-revoking an already- revoked tablet returns the same 200 payload but does not double- stamp the timestamp.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
tablet_id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "paired_at": "2019-08-24T14:15:22Z",
  • "last_seen_at": "2019-08-24T14:15:22Z",
  • "revoked_at": "2019-08-24T14:15:22Z",
  • "is_stale": true,
  • "is_revoked": true,
  • "paired_by_email": "string",
  • "revoked_by_email": "string"
}

practice_tablets_send_create

POST a staff-initiated push action to a paired tablet (api#684 / api#771).

Endpoint::

POST /api/v1/practice/<practice_uid>/tablets/<tablet_id>/send/
{ "action": "open_patient_intake",
  "payload": {"patient_id": "<uuid>", "patient_name": "Jane Doe"} }

api#771 adds the form_session action, which uses a sibling form_session field instead of payload::

{ "action": "form_session",
  "form_session": {
    "bundle_id": 42,
    "patient_id": "<uuid>",        // optional
    "appointment_id": "<uuid>"     // optional
  } }

For form_session, the view resolves the bundle's ordered template IDs at send time (so a later edit of the bundle does NOT mutate an in-flight session), mints a fresh session_id (UUID4) so the staff web can correlate ack/submission later, and persists the resolved frame onto :class:PendingTabletAction for delivery via the same persist-then-publish path the other verbs use.

The view validates the action against :data:apps.tablets.actions.TABLET_ACTIONS -- unknown verbs are a 400 and never reach the wire, so a misconfigured client can't trick the kiosk into reacting to a verb it doesn't know.

Why 202 instead of 200?

The Channels group send only enqueues to the channel layer; the api has no way to confirm the tablet's socket actually received the message (it might be offline, mid-reconnect, or the message might be dropped on layer eviction). 202 ACCEPTED is the honest answer: "the api accepted the request; delivery is best-effort". Clients that need a hard confirmation should subscribe to an ack event on the practice-events socket (future work).

Why 404 for revoked/stale tablets instead of 410?

The four "not a valid target" cases -- doesn't exist, wrong practice, revoked, stale -- collapse to a single 404. The response shape and status are uniform across all four so a caller probing for valid ids can't distinguish "doesn't exist" from "exists at another practice", which would leak cross-tenant membership. 410 is a tempting alternative for the revoked case but the same leakage argument applies: a caller learning that a specific tablet id IS revoked at this practice already had to know it exists, which is not staff-facing information for tablets they cannot administer.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
tablet_id
required
string <uuid>
Request Body schema:
required
action
required
string [ 1 .. 64 ] characters

Action verb the tablet should react to (e.g. open_patient_intake).

object

Per-action payload; shape validated in the view.

object

Form-session spec -- REQUIRED when action == 'form_session', ignored otherwise. See api#771.

Responses

Request samples

Content type
{
  • "action": "string",
  • "payload": {
    },
  • "form_session": {
    }
}

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_tablets_pair_token_create

Mint a short-lived single-use pair token for a new tablet.

Staff-authenticated; manager+ role (writes against practice settings). The response carries:

  • pair_token -- the raw JWT (only useful to a tablet capable of decoding it; included for non-QR flows like a future print-and-hand-off workflow).
  • qr_payload -- the absolute URL the tablet scans. Web renders this as a QR code.
  • expires_at -- ISO-8601 UTC timestamp of the pair token's expiry (5 minutes after mint). Used for the staff-facing countdown.
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 64 ] characters

Staff-assigned label for the tablet (e.g. 'Front Desk 1').

Responses

Request samples

Content type
{
  • "name": "string"
}

Response samples

Content type
application/json
{
  • "pair_token": "string",
  • "qr_payload": "http://example.com",
  • "expires_at": "2019-08-24T14:15:22Z"
}

patient-feedback

List patient-feedback submissions (internal staff only).

Filters: ?status= (new / triaged / resolved), ?user= (submitter UUID), ?patient= (patient UUID), ?practice= (practice UUID), ?client= (client UUID). Ordered by -created (newest first). Returns the compact list shape; open the detail view for the full row.

Authorizations:
jwtAuthbearerAuthoauth2
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

Submit patient-portal feedback (patient users only).

Accepts a feedback submission from the patient portal. Body is application/json with {title, details, page_url}; viewport and user_agent are optional. The submitting user is set server-side from request.user -- a client-supplied user value is ignored. The matched per-practice Patient record is resolved automatically by case-insensitive email match. The row is treated as PHI on the read side. Throttled to 5 submissions per hour per portal user.

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
required
title
required
string [ 1 .. 80 ] characters

One-line summary the patient typed into the feedback dialog.

details
required
string non-empty

Long-form description of the issue.

page_url
string <= 2000 characters

Page URL the feedback was submitted from.

viewport
any

Browser viewport metadata (width / height / devicePixelRatio).

user_agent
string <= 1024 characters

User-Agent string at submission time.

Responses

Request samples

Content type
{
  • "title": "string",
  • "details": "string",
  • "page_url": "string",
  • "viewport": null,
  • "user_agent": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "user": "76f62a58-5404-486d-9afc-07bded328704",
  • "submitter_email": "user@example.com",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "patient_name": "string",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "title": "string",
  • "details": "string",
  • "page_url": "string",
  • "viewport": null,
  • "user_agent": "string",
  • "status": "new",
  • "triaged_by": "918c35b9-bedc-437d-84b5-ebe932e91c8b",
  • "triaged_by_email": "user@example.com",
  • "triaged_at": "2019-08-24T14:15:22Z",
  • "resolved_by": "d0d57369-b08b-4db8-8952-8cdeedd9aebc",
  • "resolved_by_email": "user@example.com",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolution_note": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

Read a single patient-feedback submission (internal staff only).

Returns the full row. Every read fires a patient_feedback.viewed audit event because the row may carry incidentally captured PHI.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_feedback_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "user": "76f62a58-5404-486d-9afc-07bded328704",
  • "submitter_email": "user@example.com",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "patient_name": "string",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "title": "string",
  • "details": "string",
  • "page_url": "string",
  • "viewport": null,
  • "user_agent": "string",
  • "status": "new",
  • "triaged_by": "918c35b9-bedc-437d-84b5-ebe932e91c8b",
  • "triaged_by_email": "user@example.com",
  • "triaged_at": "2019-08-24T14:15:22Z",
  • "resolved_by": "d0d57369-b08b-4db8-8952-8cdeedd9aebc",
  • "resolved_by_email": "user@example.com",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolution_note": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

Transition a patient-feedback row's status (internal staff only).

Valid target statuses: new / triaged / resolved. Side effects: moving out of new for the first time stamps triaged_by / triaged_at; moving to resolved stamps resolved_by / resolved_at; bouncing back to new or triaged clears the resolved-stamp pair so the field always reflects the current state.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_feedback_uid
required
string <uuid>
Request Body schema:
required
status
required
string (FeedbackStatusEnum)
Enum: "new" "triaged" "resolved"
  • new - New
  • triaged - Triaged
  • resolved - Resolved
resolution_note
string
Default: ""

Responses

Request samples

Content type
{
  • "status": "new",
  • "resolution_note": ""
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "user": "76f62a58-5404-486d-9afc-07bded328704",
  • "submitter_email": "user@example.com",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "patient_name": "string",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "title": "string",
  • "details": "string",
  • "page_url": "string",
  • "viewport": null,
  • "user_agent": "string",
  • "status": "new",
  • "triaged_by": "918c35b9-bedc-437d-84b5-ebe932e91c8b",
  • "triaged_by_email": "user@example.com",
  • "triaged_at": "2019-08-24T14:15:22Z",
  • "resolved_by": "d0d57369-b08b-4db8-8952-8cdeedd9aebc",
  • "resolved_by_email": "user@example.com",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolution_note": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

payment

payment_list

List payment history for the authenticated patient.

Authorizations:
jwtAuthbearerAuthoauth2
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{}

Payments

payment_create_create

Create a Stripe PaymentIntent and return the client secret.

POST /api/v1/payment/create/

The frontend takes client_secret and confirms the card via Stripe.js so raw PAN never touches our servers (SAQ-A scope). The matching PaymentIntent row is created in PENDING state and transitioned to SUCCEEDED / FAILED by the webhook handler when the confirmation lifecycle completes.

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
required
amount_cents
required
integer >= 50

Amount in cents (minimum $0.50).

description
string <= 255 characters
Default: ""
practice
string <uuid>

UUID of the practice the charge belongs to (used for metadata + audit trail).

save_for_future_use
boolean
Default: false

When true, attach the resulting card to the patient's Stripe Customer for reuse.

payment_method
string <= 64 characters
Default: ""

Optional Stripe PaymentMethod id (pm_...) for one-click pay.

Responses

Request samples

Content type
{
  • "amount_cents": 50,
  • "description": "",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "save_for_future_use": false,
  • "payment_method": ""
}

Response samples

Content type
application/json
{
  • "client_secret": "string",
  • "payment_intent_id": "string",
  • "audit_id": "78c04fa6-cfb4-46a0-9aa5-3681ba4f3897"
}

payment_webhook_stripe_create

Handle Stripe webhook events.

POST /api/v1/payment/webhook/stripe/

The Stripe SDK's Webhook.construct_event does signature + timestamp verification, so we delegate to it and treat any ValueError as a 400. Idempotency is enforced via the :class:WebhookDelivery table: the first time we see an event id we record it and run the handler, every subsequent delivery short-circuits to a 200 OK without side effects.

Authorizations:
bearerAuthoauth2

Responses

Response samples

Content type
application/json
{
  • "status": "string"
}

Portal

List the authenticated patient's appointments.

Returns appointments scoped to the authenticated patient -- resolved server-side from the access token's user. No patient_id query parameter is accepted (cross-patient access vector).

Response items carry the patient-portal-safe shape: uid, start_time (ISO 8601 UTC), duration_minutes, provider_name, procedure_description, and status. Clinical notes, treatment plan IDs, dollars_scheduled, and the long-tail status taxonomy are deliberately omitted.

Filters: ?from=YYYY-MM-DD / ?to=YYYY-MM-DD (inclusive both ends, practice timezone), ?status=scheduled,confirmed (comma-separated whitelist). Page size capped at 100 via StandardPageNumberPagination.

Authorizations:
jwtAuthbearerAuthoauth2
query Parameters
from
string <date>

Earliest appointment date to include (YYYY-MM-DD, practice timezone).

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

status
string

Comma-separated whitelist of patient-facing statuses: scheduled, confirmed, arrived, completed, cancelled, no_show.

to
string <date>

Latest appointment date to include (YYYY-MM-DD, practice timezone, inclusive).

Responses

Response samples

Content type
application/json
{}

Batched badge counts for the patient-portal dashboard.

Returns a single envelope of integer counts the patient-portal home screen needs to render its card badges, replacing N full-list GETs the dashboard previously performed just to derive .length.

Counts are scoped to the authenticated patient -- resolved server-side from the access token's user via case-insensitive email match against the active Patient rows. No patient_id query parameter is honoured.

The response carries no PHI -- only integers -- so the endpoint is safe to cache for short windows in upstream caches. We set Cache-Control: private, max-age=15 to blunt thundering-herd from a tab the patient has left open; the SPA pairs this with TanStack Query's staleTime: 30_000 for defence-in-depth.

Future counts (unread messages, outstanding forms, uploaded-document approvals) will land here as new integer fields once the matching patient-facing surfaces exist server-side. Adding a field is backwards-compatible for the SPA.

Authorizations:
jwtAuthbearerAuthoauth2

Responses

Response samples

Content type
application/json
Example

Single-shot reply used to populate every count badge on the patient-portal home screen. The integer is a true COUNT(*) over the same filter the dashboard previously applied client-side after fetching the full list -- so the badge value is identical across the swap, just one network round-trip cheaper.

{
  • "upcoming_appointments": 2
}

List installed OAuth apps for the current user

Returns OAuth applications the current user has consented to that have declared the requested slot. The slot query parameter is required and must come from the canonical allowlist; unknown slots return 400.

Authorizations:
jwtAuthbearerAuthoauth2
query Parameters
slot
required
string

Slot name to filter on. Allowed values: patient.detail.actions, patient.detail.tab, practice.bar.nine-dots, schedule.appointment.actions.

Responses

Response samples

Content type
application/json
[
  • {
    }
]

List the calling patient's conversations.

Returns the conversations the authenticated patient is an explicit participant of, newest activity first. Each row carries unread_count -- the count of messages created after the patient's last_read_at bookmark -- so the SPA dashboard's usePatientUnreadMessageCount can sum across rows for the badge without a second round-trip.

Cross-patient isolation: the queryset is filtered by ConversationParticipant.user = request.user. A patient with no participant rows sees an empty page; nobody can see another patient's threads. Same 401 / 403 / 404 contract as the sibling /portal/dashboard-counts/ and /portal/appointments/ endpoints.

Authorizations:
jwtAuthbearerAuthoauth2

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Start a new conversation with the calling patient's practice.

Creates a new direct Conversation rooted at the patient's resolved Practice, attaches the calling patient as a ConversationParticipant, attaches the practice's staff messaging recipients (active ADMIN / OFFICE_MANAGER memberships) as additional participants, and persists the first message in a single transaction. Returns 201 with the conversation envelope (same shape as the detail GET).

Staff routing: if the practice has named messaging_inbox_owners configured (GH-695), only those active users are CC'd. Otherwise the fan-out is every active admin / office-manager membership on the practice -- the simplest correct default for practices that haven't set an owner yet. A small admin pool can always triage and reassign; a single named owner that happens to be on vacation cannot, so the fallback also kicks in when every named owner has been deactivated.

Rate limited per portal user at portal_messaging_start_conversation (default 1 / 5 minutes) -- see apps.portal.throttles.

Audit: messaging.conversation_started_by_patient and messaging.message_sent_by_patient are both emitted with subject_user=request.user. Body and subject text are NEVER stored on the audit document -- only their lengths.

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
required
body
required
string [ 1 .. 5000 ] characters

First message in the new conversation. Non-empty after trim.

subject
string <= 255 characters
Default: ""

Optional thread title. Defaults to the first 80 characters of body when omitted or blank -- so the staff inbox always has a usable label.

Responses

Request samples

Content type
{
  • "body": "string",
  • "subject": ""
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "title": "string",
  • "conversation_type": "direct",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "participants": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

Retrieve one of the calling patient's conversations.

Returns the conversation with the given id only if the authenticated patient is a participant. Returns 404 otherwise -- existence-leak ("this conversation exists, you just can't see it") is itself a PHI signal so we never distinguish 403 from 404 here.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
conversation_id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "title": "string",
  • "conversation_type": "direct",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "participants": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

List messages in one of the calling patient's conversations.

Returns messages in the named conversation, chronological order (oldest first), paginated. Cross-patient isolation: the conversation must have the calling patient as an explicit participant or the endpoint returns 404 before issuing the message query.

Emits a single messaging.viewed_by_patient audit event per request (subject_user=request.user, resource_id=conversation_id). Message bodies are NOT included in audit metadata -- only the conversation id and the count of messages returned -- because the bodies are PHI and the audit document index isn't the right place for them.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
conversation_id
required
string <uuid>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Send a message in one of the calling patient's conversations.

Persists a new Message in the named conversation with sender=request.user. Returns 201 with the created message envelope (same shape the message-list endpoint returns) on success.

Cross-patient isolation: the conversation must have the calling patient as an explicit participant or the endpoint returns 404 (not 403). Same existence-leak rationale as the rest of the patient-portal messaging surface.

WebSocket broadcast: persistence triggers the existing message.new post-save signal in apps.messaging.signals so any staff window watching the conversation sees the new message in real time. No additional broadcast is needed in the view path.

Rate limited per portal user at portal_messaging_send (default 30/hour) -- see apps.portal.throttles.

Audit: messaging.message_sent_by_patient with subject_user=request.user. Body length is reported in metadata but the body itself is NEVER stored on the audit document -- the body is PHI.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
conversation_id
required
string <uuid>
Request Body schema:
required
body
required
string [ 1 .. 5000 ] characters

Message body. Must be non-empty after whitespace trim.

Responses

Request samples

Content type
{
  • "body": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "sender_id": "3194e023-c19f-4a42-9172-9e18d68e3a3a",
  • "sender_name": "string",
  • "body": "string",
  • "is_system": true,
  • "created": "2019-08-24T14:15:22Z"
}

Mark a conversation read for the calling patient.

Bumps ConversationParticipant.last_read_at for the calling patient on the named conversation to now(). Subsequent calls to the list endpoint will report unread_count: 0 for this row until a new message arrives.

Returns 404 if the calling patient is not an explicit participant -- the staff side's MarkConversationReadView auto-creates a participant row for operatory conversations, but the patient side never does: operatory threads are not patient-visible, so a missing participant row on the patient side always means the patient has no business in this thread.

Emits messaging.conversation_read_by_patient with subject_user=request.user.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
conversation_id
required
string <uuid>

Responses

Total unread message count for the calling patient.

Returns {"unread": N} -- the sum across the patient's conversations of messages created after each thread's last_read_at bookmark. Sibling helper to the /portal/dashboard-counts/ envelope (api#682); the patients-side dashboard hook today derives the badge by summing unread_count across the conversation list, but this single-integer endpoint exists so future callers (e.g. a header badge that doesn't need the full list) can ask for just the number.

The response carries no PHI -- a single integer -- so it is safe to cache briefly. Returns Cache-Control: private, max-age=15 matching /portal/dashboard-counts/.

Authorizations:
jwtAuthbearerAuthoauth2

Responses

List practices the current user can access

Returns active practices the authenticated user has access to via direct or client-level membership. Accepts first-party JWT/session auth, or OAuth2 bearer tokens carrying reports:read. Unpaginated; the per-user practice list is always small.

Authorizations:
jwtAuthbearerAuthoauth2

Responses

Response samples

Content type
application/json
[
  • {
    }
]

practice_portal_appointment_book_create

Book an appointment as an authenticated patient.

POST /api/v1/practice//portal/appointment/book/

Only patient users (is_patient=True) may access this endpoint. The patient is automatically resolved from the authenticated user's email. Provider and operatory are validated against the practice. Conflicts are checked before creating the appointment.

Returns 201 with the created appointment on success, or 409 with conflict details if the requested time slot is unavailable.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
provider
required
string <uuid>

Provider UUID

operatory
required
string <uuid>

Operatory UUID

start_time
required
string <date-time>

Appointment start (ISO 8601 with timezone)

duration_minutes
required
integer [ 5 .. 480 ]

Duration in minutes

procedures
Array of strings[ items [ 1 .. 20 ] characters ]

List of CDT procedure codes (e.g. ['D0120', 'D1110'])

notes
string <= 2000 characters
Default: ""

Responses

Request samples

Content type

Minimum payload to book an appointment from the patient portal. start_time MUST include a timezone offset -- naive datetimes are rejected with a 400. procedures is optional; if provided, CDT codes are matched against the practice's procedure table.

{
  • "provider": "22222222-2222-4222-8222-222222222222",
  • "operatory": "44444444-4444-4444-8444-444444444444",
  • "start_time": "2026-05-20T10:00:00-07:00",
  • "duration_minutes": 60,
  • "procedures": [
    ],
  • "notes": "First availability in the morning, please."
}

Response samples

Content type
application/json

Returned after the portal successfully books an appointment on the patient's behalf.

{
  • "id": "55555555-5555-4555-8555-555555555555",
  • "provider": "22222222-2222-4222-8222-222222222222",
  • "operatory": "44444444-4444-4444-8444-444444444444",
  • "date_time": "2026-05-20T10:00:00-07:00",
  • "duration_minutes": 60,
  • "status": "scheduled",
  • "note": "First availability in the morning, please.",
  • "provider_name": "Doe, Dr. John"
}

practice_portal_appointment_validate_create

Pre-flight conflict check for a proposed patient appointment.

POST /api/v1/practice//portal/appointment/validate/

Same payload as the booking endpoint but only checks for conflicts without creating anything. Returns 200 with {"available": true} or 409 with conflict details.

Only patient users (is_patient=True) may access this endpoint.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
provider
required
string <uuid>

Provider UUID

operatory
required
string <uuid>

Operatory UUID

start_time
required
string <date-time>

Appointment start (ISO 8601 with timezone)

duration_minutes
required
integer [ 5 .. 480 ]

Duration in minutes

procedures
Array of strings[ items [ 1 .. 20 ] characters ]

List of CDT procedure codes (e.g. ['D0120', 'D1110'])

notes
string <= 2000 characters
Default: ""

Responses

Request samples

Content type

Minimum payload to book an appointment from the patient portal. start_time MUST include a timezone offset -- naive datetimes are rejected with a 400. procedures is optional; if provided, CDT codes are matched against the practice's procedure table.

{
  • "provider": "22222222-2222-4222-8222-222222222222",
  • "operatory": "44444444-4444-4444-8444-444444444444",
  • "start_time": "2026-05-20T10:00:00-07:00",
  • "duration_minutes": 60,
  • "procedures": [
    ],
  • "notes": "First availability in the morning, please."
}

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_portal_appointments_cancel_create

Cancel an appointment as an authenticated patient.

POST /api/v1/practice//portal/appointments//cancel/

Only patient users (is_patient=True) may access this endpoint. The patient record is resolved from the authenticated user's email and must match the appointment's patient. Only appointments in a cancellable state (currently "scheduled") may be cancelled.

An audit-trail AppointmentStatusLog entry is created and an audit event is emitted for HIPAA compliance.

Returns 200 with the updated appointment on success.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
appointment_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
reason
string <= 2000 characters
Default: ""

Patient-supplied reason for cancellation.

reschedule_request
boolean
Default: false

If true, the front desk is notified to reschedule.

Responses

Request samples

Content type

Both fields are optional. reschedule_request=true notifies the front desk to follow up with the patient so the slot can be re-filled and the patient re-booked.

{
  • "reason": "Out of town for work that week.",
  • "reschedule_request": true
}

Response samples

Content type
application/json

Returns the updated appointment with status=cancelled. An AppointmentStatusLog entry is created server-side for the HIPAA audit trail.

{
  • "id": "55555555-5555-4555-8555-555555555555",
  • "provider": "22222222-2222-4222-8222-222222222222",
  • "operatory": "44444444-4444-4444-8444-444444444444",
  • "date_time": "2026-05-20T10:00:00-07:00",
  • "duration_minutes": 60,
  • "status": "cancelled",
  • "cancellation_reason": "Out of town for work that week.",
  • "reschedule_requested": true,
  • "provider_name": "Doe, Dr. John"
}

practice_portal_available_slots_retrieve

Single-day slot finder for the patient portal.

GET /api/v1/practice//portal/available-slots/

Returns slots on a single date, restricted to operatories flagged is_web_sched=True. The response omits operatory identifiers; the patient picks a time, and the booking endpoint chooses a concrete chair server-side.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
date
required
string <date>

Target date (YYYY-MM-DD).

duration_minutes
required
integer

Required appointment length in minutes.

provider
integer

Optional provider ID filter.

Responses

practice_portal_balance_retrieve

Compact balance summary for the patient portal landing page.

GET /api/v1/practice//portal/balance/

Returns:

  • total_balance -- net amount currently owed (positive) or held as credit (negative). Computed from the full ledger.
  • current_charges -- portion of the balance from charges dated within the last _PORTAL_OVERDUE_DAYS days.
  • overdue_charges -- portion of the balance from charges dated more than _PORTAL_OVERDUE_DAYS days ago. Capped at max(0, total_balance).
  • last_payment_date / last_payment_amount -- most recent patient-paid (non-insurance) payment, or null if none.
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json

total_balance is the net amount owed (positive) or held as credit (negative). The balance is split into current_charges (within the last 30 days) and overdue_charges (older than 30 days, never above total_balance). last_payment_* tracks only patient-paid payments -- insurance write-backs are excluded.

{
  • "total_balance": "1035.00",
  • "current_charges": "1035.00",
  • "overdue_charges": "0.00",
  • "last_payment_date": "2026-05-14",
  • "last_payment_amount": "150.00"
}

practice_portal_find_spot_retrieve

Multi-day slot finder for the patient portal.

GET /api/v1/practice//portal/find-spot/

Scans a date range and returns the first matching slots across all web-scheduling-eligible operatories. Search window is capped at 90 days and result count at 20 — both tighter than the staff endpoint.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
duration_minutes
required
integer

Required appointment length in minutes.

end_date
string <date>

Last date to search (default: start_date + 30 days). end_date - start_date must be <= 90 days.

max_results
integer

Maximum slots to return (default 20, max 20).

provider
integer

Optional provider ID filter.

start_date
string <date>

First date to search (default: today).

Responses

practice_portal_ledger_retrieve

Patient's ledger showing charges, payments, adjustments, and running balance.

GET /api/v1/practice//portal/ledger/

Returns a paginated, date-descending list of ledger entries. The running balance is computed across the full ledger (oldest-first) before paginating so each page's balance_after is correct regardless of which page is requested.

Only the authenticated patient's own data is returned.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

1-based page number (default 1).

page_size
integer

Rows per page (default 20, max 100).

Responses

Response samples

Content type
application/json

Ledger entries are sorted oldest-first so running_balance reads like a check register. balance at the envelope level is the net amount the patient currently owes (positive means the practice is owed money; negative means the patient has a credit).

{
  • "entries": [
    ],
  • "balance": "1035.00"
}

practice_portal_message_list

List or send messages for the authenticated patient.

Only patient users (is_patient=True) may access this endpoint. Messages are scoped to the practice in the URL and the authenticated user.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json

Typical response for a patient checking their inbox. Results are ordered newest-first by created and wrapped in the project-wide paginator envelope (count, next, previous, results).

{
  • "count": 123,
  • "results": [
    ]
}

practice_portal_message_create

List or send messages for the authenticated patient.

Only patient users (is_patient=True) may access this endpoint. Messages are scoped to the practice in the URL and the authenticated user.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
subject
required
string [ 1 .. 255 ] characters
body
required
string non-empty
is_read
boolean
custom_data
any

Responses

Request samples

Content type

Only subject and body are writable -- patient, practice and is_from_patient are server-set from the authenticated user and URL scope.

{
  • "subject": "Question about my upcoming cleaning",
  • "body": "Hi! Is it OK to drink coffee the morning of my cleaning appointment?"
}

Response samples

Content type
application/json

Full message record with server-assigned id, patient, practice, and timestamp.

{
  • "id": "cccccccc-cccc-4ccc-8ccc-cccccccccccc",
  • "patient": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
  • "practice": "99999999-9999-4999-8999-999999999999",
  • "subject": "Question about my upcoming cleaning",
  • "body": "Hi! Is it OK to drink coffee the morning of my cleaning appointment?",
  • "is_from_patient": true,
  • "is_read": false,
  • "created": "2026-05-10T14:22:08Z",
  • "custom_data": { }
}

practice_portal_message_retrieve

Retrieve a single portal message.

Practice-scoped and patient-scoped.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
message_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json

Same shape as the list entries. Fetching a message marks it viewed for audit purposes.

{
  • "id": "dddddddd-dddd-4ddd-8ddd-dddddddddddd",
  • "patient": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
  • "practice": "99999999-9999-4999-8999-999999999999",
  • "subject": "Re: Question about my upcoming cleaning",
  • "body": "Coffee is fine! Please just avoid eating within 30 minutes of your appointment.",
  • "is_from_patient": false,
  • "is_read": true,
  • "created": "2026-05-10T16:03:41Z",
  • "custom_data": { }
}

practice_portal_payment_methods_retrieve

List the patient's saved Stripe payment methods.

GET /api/v1/practice//portal/payment-methods/

Returns a sanitized shape — only brand / last4 / expiry are exposed to the frontend. When the patient has no Stripe Customer yet (never saved a card) we return an empty list rather than 404 so the UI can render its "no saved cards" empty state without special-casing.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "results": [
    ]
}

practice_portal_payment_methods_destroy

Detach a single saved payment method.

DELETE /api/v1/practice//portal/payment-methods//

Verifies the payment method belongs to the authenticated patient's Stripe Customer before detaching — without this check, a malicious portal user could detach another patient's card by guessing pm_xxx ids.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
pm_id
required
string
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_portal_payments_list

List patient-paid payment history for the authenticated patient.

Insurance-source payments (pay_type classified as insurance) are filtered out — patient-portal callers want their own out-of-pocket payments, not EOB write-backs. The ledger endpoint surfaces insurance payments separately.

Paginated via :class:StandardPageNumberPagination so a long history doesn't ship in a single response.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json

The patient sees only their own payments in this practice. pay_type is stable (online_patient_portal for portal-posted payments); Stripe processing is stubbed today and will land once the BAA is finalised.

[
  • [
    ]
]

practice_portal_payments_create

Record a patient payment from the portal — charge-then-persist.

The flow is:

  1. Validate the payload.
  2. If a Stripe payment_method token was supplied, create a confirmed off-session PaymentIntent server-side so the card is charged before we persist anything. A failure here returns 402 PAYMENT_REQUIRED with the sanitized Stripe error — no PaymentRecord is written.
  3. Only after a successful charge (or a non-Stripe payload — for e.g. the initial post-deploy window when STRIPE_SECRET_KEY is unset) do we persist the PaymentRecord.

503 SERVICE_UNAVAILABLE is returned when a payment_method is supplied but Stripe creds are missing — the frontend treats this as "payments not yet enabled in this environment" rather than a bug.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
amount
required
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Payment amount in dollars (e.g. 150.00).

payment_method
string <= 255 characters
Default: ""

Stripe payment method token (not processed yet).

notes
string <= 500 characters
Default: ""

Optional note for the payment (e.g. 'Co-pay for cleaning').

Responses

Request samples

Content type

amount is required and must be positive. payment_method is accepted today (Stripe PM token) but deferred until the BAA is finalised -- no card is charged yet, the PaymentRecord is written directly.

{
  • "amount": "150.00",
  • "payment_method": "pm_synthetic_placeholder",
  • "notes": "Co-pay for cleaning"
}

Response samples

Content type
application/json

Returns the freshly created PaymentRecord in the same shape used by the list endpoint.

{
  • "id": "cdcdcdcd-cdcd-4dcd-8dcd-cdcdcdcdcdcd",
  • "pay_date": "2026-05-14",
  • "pay_amount": "150.00",
  • "pay_type": "online_patient_portal",
  • "pay_note": "Co-pay for cleaning",
  • "created": "2026-05-14T18:02:19Z"
}

practice_portal_setup_intents_create

Create a Stripe SetupIntent so the patient can save a card.

POST /api/v1/practice//portal/setup-intents/

Returns client_secret for the frontend to call stripe.confirmSetup with. The Stripe Customer is created on demand so the row only exists once the patient actually saves a card.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "client_secret": "string",
  • "setup_intent_id": "string",
  • "customer_id": "string"
}

Patient Submissions (Public)

portal_submission_create

Submit patient intake data via a one-time invite token.

POST /api/v1/portal/submission//

No authentication required. The token must be valid, not expired, and not already used. Stores the submitted data and marks the submission as submitted.

Authorizations:
bearerAuthoauth2
path Parameters
token
required
string
Request Body schema:
required
submitted_data
required
any

Patient intake data (demographics, etc.).

Responses

Request samples

Content type

Public endpoint -- no authentication. The invite token in the URL authorises the write. submitted_data is an open JSON envelope; the practice's intake form decides its shape.

{
  • "submitted_data": {
    }
}

Response samples

Content type
application/json

The token is now marked used; replaying it returns 410 Gone.

{
  • "detail": "Submission received."
}

practice

practice_list

List practices (admin-only).

Authorizations:
jwtAuthbearerAuthoauth2
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_clinical_note_template_retrieve

Retrieve, update, or delete a clinical note template.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
note_template_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "category": "exam",
  • "content": "string",
  • "is_active": true,
  • "sort_order": 2147483647,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_clinical_note_template_update

Retrieve, update, or delete a clinical note template.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
note_template_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 255 ] characters
CategoryEnum (string) or BlankEnum (any)
content
required
string non-empty

Template body. Supports placeholder tokens like {{tooth}}, {{provider}}.

is_active
boolean
sort_order
integer [ 0 .. 2147483647 ]
custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "category": "exam",
  • "content": "string",
  • "is_active": true,
  • "sort_order": 2147483647,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "category": "exam",
  • "content": "string",
  • "is_active": true,
  • "sort_order": 2147483647,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_clinical_note_template_partial_update

Retrieve, update, or delete a clinical note template.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
note_template_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
name
string [ 1 .. 255 ] characters
CategoryEnum (string) or BlankEnum (any)
content
string non-empty

Template body. Supports placeholder tokens like {{tooth}}, {{provider}}.

is_active
boolean
sort_order
integer [ 0 .. 2147483647 ]
custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "category": "exam",
  • "content": "string",
  • "is_active": true,
  • "sort_order": 2147483647,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "category": "exam",
  • "content": "string",
  • "is_active": true,
  • "sort_order": 2147483647,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_clinical_note_template_destroy

Retrieve, update, or delete a clinical note template.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
note_template_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_clinical_procedure_partial_update

Handle PATCH on the list endpoint for bulk updates.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
custom_data
any

Responses

Request samples

Content type
{
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "procedure_code": {
    },
  • "proc_code": "string",
  • "description": "string",
  • "proc_date": "2019-08-24",
  • "date_complete": "2019-08-24",
  • "proc_fee": "string",
  • "status": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "discount": "string",
  • "unit_qty": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_clinical_procedure_code_retrieve

Retrieve or update a procedure code.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
procedure_code_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "code": "string",
  • "description": "string",
  • "abbreviation": "string",
  • "service_type": "diagnostic",
  • "default_fee": "string",
  • "default_duration_minutes": 2147483647,
  • "generate_recall": true,
  • "is_active": true,
  • "ada_code": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_clinical_procedure_code_update

Retrieve or update a procedure code.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
procedure_code_uid
required
string <uuid>
Request Body schema:
required
code
required
string [ 1 .. 20 ] characters
description
string <= 255 characters
abbreviation
string <= 100 characters
ServiceTypeEnum (string) or BlankEnum (any)
default_fee
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Practice UCR fee

default_duration_minutes
integer [ 0 .. 2147483647 ]

Default appointment block size

generate_recall
boolean

Triggers recall scheduling when completed

is_active
boolean
ada_code
string <= 20 characters

ADA/CDT code reference (insurance module)

custom_data
any

Responses

Request samples

Content type
{
  • "code": "string",
  • "description": "string",
  • "abbreviation": "string",
  • "service_type": "diagnostic",
  • "default_fee": "string",
  • "default_duration_minutes": 2147483647,
  • "generate_recall": true,
  • "is_active": true,
  • "ada_code": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "code": "string",
  • "description": "string",
  • "abbreviation": "string",
  • "service_type": "diagnostic",
  • "default_fee": "string",
  • "default_duration_minutes": 2147483647,
  • "generate_recall": true,
  • "is_active": true,
  • "ada_code": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_clinical_procedure_code_partial_update

Retrieve or update a procedure code.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
procedure_code_uid
required
string <uuid>
Request Body schema:
code
string [ 1 .. 20 ] characters
description
string <= 255 characters
abbreviation
string <= 100 characters
ServiceTypeEnum (string) or BlankEnum (any)
default_fee
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Practice UCR fee

default_duration_minutes
integer [ 0 .. 2147483647 ]

Default appointment block size

generate_recall
boolean

Triggers recall scheduling when completed

is_active
boolean
ada_code
string <= 20 characters

ADA/CDT code reference (insurance module)

custom_data
any

Responses

Request samples

Content type
{
  • "code": "string",
  • "description": "string",
  • "abbreviation": "string",
  • "service_type": "diagnostic",
  • "default_fee": "string",
  • "default_duration_minutes": 2147483647,
  • "generate_recall": true,
  • "is_active": true,
  • "ada_code": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "code": "string",
  • "description": "string",
  • "abbreviation": "string",
  • "service_type": "diagnostic",
  • "default_fee": "string",
  • "default_duration_minutes": 2147483647,
  • "generate_recall": true,
  • "is_active": true,
  • "ada_code": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_comms_commlog_partial_update

Handle PATCH on the list endpoint for bulk updates.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
patient
string or null <uuid>
date_time
string or null <date-time>
mode
string (ModeEnum)
Enum: "phone" "email" "text" "fax" "mail" "in_person" "web" "other"
  • phone - Phone
  • email - Email
  • text - Text
  • fax - Fax
  • mail - Mail
  • in_person - In Person
  • web - Web
  • other - Other
direction
string (Direction80cEnum)
Enum: "sent" "received" "neither"
  • sent - Sent
  • received - Received
  • neither - Neither
outcome
string
Enum: "success" "no_answer" "voicemail" "bounced" "bad_number" "other"

What happened on the contact attempt. Only success rows count toward the recall-list last_reached_at annotation.

  • success - Success
  • no_answer - No Answer
  • voicemail - Voicemail
  • bounced - Bounced
  • bad_number - Bad Number
  • other - Other
subject
string <= 255 characters

Short label, e.g. 'Recall reminder', 'Treatment plan follow-up'.

note
string
staff_user
string or null <uuid>

Staff member who logged the contact. Null for system-generated entries.

recall
string or null <uuid>

Optional link to the specific recall this contact addresses.

is_imported
boolean

True if this row was imported from a legacy PMS (escape-opendental, escape-eaglesoft, ...) rather than created natively in Escape. Imported rows may carry PHI in the note body that pre-dates the Escape BAA / no-PHI-in-comms policy (GH-575); clients must NOT expose 'resend' or 'use as template' affordances on imported rows, and any future send endpoint that takes a replicate_of_commlog_id MUST refuse imported sources.

custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "date_time": "2019-08-24T14:15:22Z",
  • "mode": "phone",
  • "direction": "sent",
  • "outcome": "success",
  • "subject": "string",
  • "note": "string",
  • "staff_user": "17986289-b0ef-402a-92d5-49bc6fa3367e",
  • "recall": "e7ef6ec4-8466-4387-af6a-2ed34de604a8",
  • "is_imported": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "date_time": "2019-08-24T14:15:22Z",
  • "mode": "phone",
  • "direction": "sent",
  • "outcome": "success",
  • "subject": "string",
  • "note": "string",
  • "staff_user": "17986289-b0ef-402a-92d5-49bc6fa3367e",
  • "recall": "e7ef6ec4-8466-4387-af6a-2ed34de604a8",
  • "is_imported": true,
  • "custom_data": null
}

practice_doccenter_category_list

List system + practice categories; POST creates a practice-custom category.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{}

practice_doccenter_category_create

List system + practice categories; POST creates a practice-custom category.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
slug
required
string [ 1 .. 50 ] characters ^[-a-zA-Z0-9_]+$
label
required
string [ 1 .. 100 ] characters
icon
string <= 50 characters

Lucide icon name

sort_order
integer [ 0 .. 32767 ]
custom_data
any

Responses

Request samples

Content type
{
  • "slug": "string",
  • "label": "string",
  • "icon": "string",
  • "sort_order": 32767,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "slug": "string",
  • "label": "string",
  • "icon": "string",
  • "sort_order": 32767,
  • "custom_data": null
}

practice_doccenter_category_retrieve

Update/delete practice-custom categories only.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
category_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "slug": "string",
  • "label": "string",
  • "icon": "string",
  • "sort_order": 32767,
  • "custom_data": null
}

practice_doccenter_category_update

Update/delete practice-custom categories only.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
category_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
slug
required
string [ 1 .. 50 ] characters ^[-a-zA-Z0-9_]+$
label
required
string [ 1 .. 100 ] characters
icon
string <= 50 characters

Lucide icon name

sort_order
integer [ 0 .. 32767 ]
custom_data
any

Responses

Request samples

Content type
{
  • "slug": "string",
  • "label": "string",
  • "icon": "string",
  • "sort_order": 32767,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "slug": "string",
  • "label": "string",
  • "icon": "string",
  • "sort_order": 32767,
  • "custom_data": null
}

practice_doccenter_category_partial_update

Update/delete practice-custom categories only.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
category_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
slug
string [ 1 .. 50 ] characters ^[-a-zA-Z0-9_]+$
label
string [ 1 .. 100 ] characters
icon
string <= 50 characters

Lucide icon name

sort_order
integer [ 0 .. 32767 ]
custom_data
any

Responses

Request samples

Content type
{
  • "slug": "string",
  • "label": "string",
  • "icon": "string",
  • "sort_order": 32767,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "slug": "string",
  • "label": "string",
  • "icon": "string",
  • "sort_order": 32767,
  • "custom_data": null
}

practice_doccenter_category_destroy

Update/delete practice-custom categories only.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
category_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_doccenter_document_retrieve

Retrieve or update document metadata.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
doc_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "category": "86d23d13-9dbb-46f3-82d0-25253c7750c3",
  • "title": "string",
  • "description": "string",
  • "original_filename": "string",
  • "mime_type": "string",
  • "file_size": 0,
  • "page_count": 0,
  • "uploaded_by": "e134ce2c-a199-4e99-9c11-627b70a7ff28",
  • "source_application": 0,
  • "is_deleted": true,
  • "deleted_at": "2019-08-24T14:15:22Z",
  • "deleted_by": "d7d7cfa2-327b-4733-8887-d09252b40b06",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolved_by": "d0d57369-b08b-4db8-8952-8cdeedd9aebc",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "download_url": "string",
  • "patient_name": "string",
  • "category_label": "string",
  • "uploaded_by_name": "string",
  • "caller_id": "string",
  • "processing_state": "pending",
  • "processing_error": "string",
  • "processing_updated_at": "2019-08-24T14:15:22Z",
  • "transcript": "string",
  • "transcript_confidence": "string",
  • "custom_data": null
}

practice_doccenter_document_update

Retrieve or update document metadata.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
doc_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
patient
string or null <uuid>
category
string or null <uuid>
title
required
string [ 1 .. 255 ] characters
description
string
caller_id
string <= 32 characters ^\+\d{1,15}$

E.164 caller-ID for voicemail recordings (e.g. +14155551234). Used by the patient-link suggestion engine downstream of the voicemail-to-text pipeline.

custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "category": "86d23d13-9dbb-46f3-82d0-25253c7750c3",
  • "title": "string",
  • "description": "string",
  • "caller_id": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "category": "86d23d13-9dbb-46f3-82d0-25253c7750c3",
  • "title": "string",
  • "description": "string",
  • "original_filename": "string",
  • "mime_type": "string",
  • "file_size": 0,
  • "page_count": 0,
  • "uploaded_by": "e134ce2c-a199-4e99-9c11-627b70a7ff28",
  • "source_application": 0,
  • "is_deleted": true,
  • "deleted_at": "2019-08-24T14:15:22Z",
  • "deleted_by": "d7d7cfa2-327b-4733-8887-d09252b40b06",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolved_by": "d0d57369-b08b-4db8-8952-8cdeedd9aebc",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "download_url": "string",
  • "patient_name": "string",
  • "category_label": "string",
  • "uploaded_by_name": "string",
  • "caller_id": "string",
  • "processing_state": "pending",
  • "processing_error": "string",
  • "processing_updated_at": "2019-08-24T14:15:22Z",
  • "transcript": "string",
  • "transcript_confidence": "string",
  • "custom_data": null
}

practice_doccenter_document_partial_update

Retrieve or update document metadata.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
doc_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
patient
string or null <uuid>
category
string or null <uuid>
title
string [ 1 .. 255 ] characters
description
string
caller_id
string <= 32 characters ^\+\d{1,15}$

E.164 caller-ID for voicemail recordings (e.g. +14155551234). Used by the patient-link suggestion engine downstream of the voicemail-to-text pipeline.

custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "category": "86d23d13-9dbb-46f3-82d0-25253c7750c3",
  • "title": "string",
  • "description": "string",
  • "caller_id": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "category": "86d23d13-9dbb-46f3-82d0-25253c7750c3",
  • "title": "string",
  • "description": "string",
  • "original_filename": "string",
  • "mime_type": "string",
  • "file_size": 0,
  • "page_count": 0,
  • "uploaded_by": "e134ce2c-a199-4e99-9c11-627b70a7ff28",
  • "source_application": 0,
  • "is_deleted": true,
  • "deleted_at": "2019-08-24T14:15:22Z",
  • "deleted_by": "d7d7cfa2-327b-4733-8887-d09252b40b06",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolved_by": "d0d57369-b08b-4db8-8952-8cdeedd9aebc",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "download_url": "string",
  • "patient_name": "string",
  • "category_label": "string",
  • "uploaded_by_name": "string",
  • "caller_id": "string",
  • "processing_state": "pending",
  • "processing_error": "string",
  • "processing_updated_at": "2019-08-24T14:15:22Z",
  • "transcript": "string",
  • "transcript_confidence": "string",
  • "custom_data": null
}

practice_doccenter_inbox_list

List inbox items for this practice.

Practice Inbox (escape#151) renders three tabs — Documents (emailed in), Voicemails, and Faxes — each backed by a single-source list query. The ?source= filter lets the web client pull just the rows it needs per tab without round-tripping every pending item and filtering client-side.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_doccenter_inbox_retrieve

View or update inbox item (title, notes).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
inbox_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "original_filename": "string",
  • "mime_type": "string",
  • "file_size": 0,
  • "title": "string",
  • "notes": "string",
  • "source": "web",
  • "inbound_email": "e4185790-fbc9-4897-be5d-ea0372f36408",
  • "uploaded_by": "e134ce2c-a199-4e99-9c11-627b70a7ff28",
  • "source_application": 0,
  • "expires_at": "2019-08-24T14:15:22Z",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "download_url": "string",
  • "uploaded_by_name": "string",
  • "source_application_name": "string",
  • "custom_data": null
}

practice_doccenter_inbox_update

View or update inbox item (title, notes).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
inbox_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
title
string <= 255 characters
notes
string

Staff notes during triage

custom_data
any

Responses

Request samples

Content type
{
  • "title": "string",
  • "notes": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "original_filename": "string",
  • "mime_type": "string",
  • "file_size": 0,
  • "title": "string",
  • "notes": "string",
  • "source": "web",
  • "inbound_email": "e4185790-fbc9-4897-be5d-ea0372f36408",
  • "uploaded_by": "e134ce2c-a199-4e99-9c11-627b70a7ff28",
  • "source_application": 0,
  • "expires_at": "2019-08-24T14:15:22Z",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "download_url": "string",
  • "uploaded_by_name": "string",
  • "source_application_name": "string",
  • "custom_data": null
}

practice_doccenter_inbox_partial_update

View or update inbox item (title, notes).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
inbox_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
title
string <= 255 characters
notes
string

Staff notes during triage

custom_data
any

Responses

Request samples

Content type
{
  • "title": "string",
  • "notes": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "original_filename": "string",
  • "mime_type": "string",
  • "file_size": 0,
  • "title": "string",
  • "notes": "string",
  • "source": "web",
  • "inbound_email": "e4185790-fbc9-4897-be5d-ea0372f36408",
  • "uploaded_by": "e134ce2c-a199-4e99-9c11-627b70a7ff28",
  • "source_application": 0,
  • "expires_at": "2019-08-24T14:15:22Z",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "download_url": "string",
  • "uploaded_by_name": "string",
  • "source_application_name": "string",
  • "custom_data": null
}

practice_faxes_retrieve

Retrieve a single fax row, including a signed download URL.

Read-only — there's no legitimate reason to PATCH a fax row in place. Status changes flow through the webhook handler, not the user-facing API.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
fax_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "direction": "inbound",
  • "from_number": "string",
  • "to_number": "string",
  • "page_count": 0,
  • "status": "queued",
  • "sinch_fax_id": "string",
  • "document_url": "string",
  • "error_message": "string",
  • "completed_at": "2019-08-24T14:15:22Z",
  • "sent_by": "40cc1a1c-5bda-4c73-bb08-df4a7613e4ee",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "practice_link": true,
  • "filed_at": "2019-08-24T14:15:22Z",
  • "filed_by": "011b59c1-1189-4a11-87df-fa9753db2861",
  • "discarded_at": "2019-08-24T14:15:22Z",
  • "discarded_by": "69474e1d-c497-4e9d-9f07-e93914ef0818",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_imaging_mount_list

List mounts in a practice and create new mounts from a template.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_imaging_mount_create

List mounts in a practice and create new mounts from a template.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
patient
required
string <uuid>
exam
string or null <uuid>

Optional exam the mount was initialised from.

template
required
string <uuid>
name
string <= 255 characters

Optional user-supplied label.

notes
string
custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "exam": "76d06126-4ce7-4fb4-98c2-d484d7e9ee38",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "name": "string",
  • "notes": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "exam": "76d06126-4ce7-4fb4-98c2-d484d7e9ee38",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "template_code": "string",
  • "template_name": "string",
  • "name": "string",
  • "notes": "string",
  • "slots": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_imaging_mount_template_list

List canonical mount templates (FMX-18, BW-4, Pano, etc.).

Templates are not practice-scoped (they're industry standards) but the endpoint is mounted under the practice URL so access control still runs through PracticeScopedMixin.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{}

practice_imaging_mount_retrieve

Retrieve, update metadata on, or delete a mount.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
mount_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "exam": "76d06126-4ce7-4fb4-98c2-d484d7e9ee38",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "template_code": "string",
  • "template_name": "string",
  • "name": "string",
  • "notes": "string",
  • "slots": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_imaging_mount_update

Retrieve, update metadata on, or delete a mount.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
mount_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
patient
required
string <uuid>
exam
string or null <uuid>

Optional exam the mount was initialised from.

template
required
string <uuid>
name
string <= 255 characters

Optional user-supplied label.

notes
string
custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "exam": "76d06126-4ce7-4fb4-98c2-d484d7e9ee38",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "name": "string",
  • "notes": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "exam": "76d06126-4ce7-4fb4-98c2-d484d7e9ee38",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "template_code": "string",
  • "template_name": "string",
  • "name": "string",
  • "notes": "string",
  • "slots": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_imaging_mount_partial_update

Retrieve, update metadata on, or delete a mount.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
mount_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
patient
string <uuid>
exam
string or null <uuid>

Optional exam the mount was initialised from.

template
string <uuid>
name
string <= 255 characters

Optional user-supplied label.

notes
string
custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "exam": "76d06126-4ce7-4fb4-98c2-d484d7e9ee38",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "name": "string",
  • "notes": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "exam": "76d06126-4ce7-4fb4-98c2-d484d7e9ee38",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "template_code": "string",
  • "template_name": "string",
  • "name": "string",
  • "notes": "string",
  • "slots": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_imaging_mount_destroy

Retrieve, update metadata on, or delete a mount.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
mount_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_imaging_mount_slot_update

Update a single slot on a mount (assign/unassign image, rotate, flip).

Looked up by (mount_uid, slot_index). PATCH is the primary verb; PUT is supported for completeness but requires all updatable fields.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
mount_uid
required
string <uuid>
practice_uid
required
string <uuid>
slot_index
required
integer
Request Body schema:
image
string or null <uuid>
rotation
integer [ 0 .. 2147483647 ]

Display rotation in degrees: 0, 90, 180 or 270.

flipped
boolean

Horizontal flip.

label
string <= 255 characters
custom_data
any

Responses

Request samples

Content type
{
  • "image": "89f204d4-24d2-439a-b6e8-e97405cb1f8e",
  • "rotation": 2147483647,
  • "flipped": true,
  • "label": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "slot_index": 0,
  • "image": "89f204d4-24d2-439a-b6e8-e97405cb1f8e",
  • "rotation": 2147483647,
  • "flipped": true,
  • "label": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_imaging_mount_slot_partial_update

Update a single slot on a mount (assign/unassign image, rotate, flip).

Looked up by (mount_uid, slot_index). PATCH is the primary verb; PUT is supported for completeness but requires all updatable fields.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
mount_uid
required
string <uuid>
practice_uid
required
string <uuid>
slot_index
required
integer
Request Body schema:
image
string or null <uuid>
rotation
integer [ 0 .. 2147483647 ]

Display rotation in degrees: 0, 90, 180 or 270.

flipped
boolean

Horizontal flip.

label
string <= 255 characters
custom_data
any

Responses

Request samples

Content type
{
  • "image": "89f204d4-24d2-439a-b6e8-e97405cb1f8e",
  • "rotation": 2147483647,
  • "flipped": true,
  • "label": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "slot_index": 0,
  • "image": "89f204d4-24d2-439a-b6e8-e97405cb1f8e",
  • "rotation": 2147483647,
  • "flipped": true,
  • "label": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_imaging_source_list

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{}

practice_imaging_source_create

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 255 ] characters
source_type
required
string (SourceTypeEnum)
Enum: "webcam" "sensor" "file_upload"
  • webcam - Webcam / Intraoral Camera
  • sensor - X-Ray Sensor
  • file_upload - File Upload
is_active
boolean
notes
string
custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "source_type": "webcam",
  • "is_active": true,
  • "notes": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "source_type": "webcam",
  • "is_active": true,
  • "notes": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_imaging_source_retrieve

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
source_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "source_type": "webcam",
  • "is_active": true,
  • "notes": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_imaging_source_update

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
source_uid
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 255 ] characters
source_type
required
string (SourceTypeEnum)
Enum: "webcam" "sensor" "file_upload"
  • webcam - Webcam / Intraoral Camera
  • sensor - X-Ray Sensor
  • file_upload - File Upload
is_active
boolean
notes
string
custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "source_type": "webcam",
  • "is_active": true,
  • "notes": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "source_type": "webcam",
  • "is_active": true,
  • "notes": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_imaging_source_partial_update

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
source_uid
required
string <uuid>
Request Body schema:
name
string [ 1 .. 255 ] characters
source_type
string (SourceTypeEnum)
Enum: "webcam" "sensor" "file_upload"
  • webcam - Webcam / Intraoral Camera
  • sensor - X-Ray Sensor
  • file_upload - File Upload
is_active
boolean
notes
string
custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "source_type": "webcam",
  • "is_active": true,
  • "notes": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "source_type": "webcam",
  • "is_active": true,
  • "notes": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_imaging_source_destroy

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
source_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_imaging_template_list

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_imaging_template_create

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 255 ] characters
description
string
grid_rows
integer [ 0 .. 2147483647 ]

Number of rows in the exam grid layout

grid_cols
integer [ 0 .. 2147483647 ]

Number of columns in the exam grid layout

source
string or null <uuid>

Capture source for this template

is_active
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "description": "string",
  • "grid_rows": 2147483647,
  • "grid_cols": 2147483647,
  • "source": "07b8e003-7027-443f-88b0-24a5eb1cc68b",
  • "is_active": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "description": "string",
  • "grid_rows": 2147483647,
  • "grid_cols": 2147483647,
  • "source": "07b8e003-7027-443f-88b0-24a5eb1cc68b",
  • "source_type": "string",
  • "is_active": true,
  • "slots": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_imaging_template_slot_list

Manage slots within an exam template.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_id
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{}

practice_imaging_template_slot_create

Manage slots within an exam template.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_id
required
string <uuid>
Request Body schema:
row
integer [ 0 .. 2147483647 ]

Row position in the grid (0-indexed)

col
integer [ 0 .. 2147483647 ]

Column position in the grid (0-indexed)

label
string <= 255 characters

e.g., 'UR PA', 'BW Right', 'Photo 1'

custom_data
any

Responses

Request samples

Content type
{
  • "row": 2147483647,
  • "col": 2147483647,
  • "label": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "row": 2147483647,
  • "col": 2147483647,
  • "label": "string",
  • "custom_data": null
}

practice_imaging_template_slot_destroy

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
slot_uid
required
string <uuid>
template_id
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_imaging_template_retrieve

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "description": "string",
  • "grid_rows": 2147483647,
  • "grid_cols": 2147483647,
  • "source": "07b8e003-7027-443f-88b0-24a5eb1cc68b",
  • "source_type": "string",
  • "is_active": true,
  • "slots": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_imaging_template_update

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_uid
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 255 ] characters
description
string
grid_rows
integer [ 0 .. 2147483647 ]

Number of rows in the exam grid layout

grid_cols
integer [ 0 .. 2147483647 ]

Number of columns in the exam grid layout

source
string or null <uuid>

Capture source for this template

is_active
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "description": "string",
  • "grid_rows": 2147483647,
  • "grid_cols": 2147483647,
  • "source": "07b8e003-7027-443f-88b0-24a5eb1cc68b",
  • "is_active": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "description": "string",
  • "grid_rows": 2147483647,
  • "grid_cols": 2147483647,
  • "source": "07b8e003-7027-443f-88b0-24a5eb1cc68b",
  • "source_type": "string",
  • "is_active": true,
  • "slots": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_imaging_template_partial_update

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_uid
required
string <uuid>
Request Body schema:
name
string [ 1 .. 255 ] characters
description
string
grid_rows
integer [ 0 .. 2147483647 ]

Number of rows in the exam grid layout

grid_cols
integer [ 0 .. 2147483647 ]

Number of columns in the exam grid layout

source
string or null <uuid>

Capture source for this template

is_active
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "description": "string",
  • "grid_rows": 2147483647,
  • "grid_cols": 2147483647,
  • "source": "07b8e003-7027-443f-88b0-24a5eb1cc68b",
  • "is_active": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "description": "string",
  • "grid_rows": 2147483647,
  • "grid_cols": 2147483647,
  • "source": "07b8e003-7027-443f-88b0-24a5eb1cc68b",
  • "source_type": "string",
  • "is_active": true,
  • "slots": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_imaging_template_destroy

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_insurance_carrier_retrieve

Retrieve, update, or deactivate an insurance carrier.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
carrier_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "phone": "string",
  • "website": "http://example.com",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "payer_id": "string",
  • "claim_office_id": "string",
  • "hpid": "string",
  • "payment_source": "string",
  • "notes": "string",
  • "is_active": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_insurance_carrier_update

Retrieve, update, or deactivate an insurance carrier.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
carrier_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 255 ] characters
phone
string <= 20 characters
website
string <uri> <= 200 characters
address_line1
string <= 255 characters
address_line2
string <= 255 characters
city
string <= 100 characters
state
string <= 2 characters
zip_code
string <= 10 characters
payer_id
string <= 50 characters

EDI payer ID for clearinghouse submission

claim_office_id
string <= 50 characters

Separate claim submission office ID

hpid
string <= 50 characters

Health Plan Identifier

payment_source
string <= 50 characters

check, eft, virtual_card

notes
string
is_active
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "phone": "string",
  • "website": "http://example.com",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "payer_id": "string",
  • "claim_office_id": "string",
  • "hpid": "string",
  • "payment_source": "string",
  • "notes": "string",
  • "is_active": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "phone": "string",
  • "website": "http://example.com",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "payer_id": "string",
  • "claim_office_id": "string",
  • "hpid": "string",
  • "payment_source": "string",
  • "notes": "string",
  • "is_active": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_insurance_carrier_partial_update

Retrieve, update, or deactivate an insurance carrier.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
carrier_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
name
string [ 1 .. 255 ] characters
phone
string <= 20 characters
website
string <uri> <= 200 characters
address_line1
string <= 255 characters
address_line2
string <= 255 characters
city
string <= 100 characters
state
string <= 2 characters
zip_code
string <= 10 characters
payer_id
string <= 50 characters

EDI payer ID for clearinghouse submission

claim_office_id
string <= 50 characters

Separate claim submission office ID

hpid
string <= 50 characters

Health Plan Identifier

payment_source
string <= 50 characters

check, eft, virtual_card

notes
string
is_active
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "phone": "string",
  • "website": "http://example.com",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "payer_id": "string",
  • "claim_office_id": "string",
  • "hpid": "string",
  • "payment_source": "string",
  • "notes": "string",
  • "is_active": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "phone": "string",
  • "website": "http://example.com",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "payer_id": "string",
  • "claim_office_id": "string",
  • "hpid": "string",
  • "payment_source": "string",
  • "notes": "string",
  • "is_active": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_insurance_carrier_destroy

Retrieve, update, or deactivate an insurance carrier.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
carrier_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_insurance_fee_schedule_entry_list

List entries for a fee schedule.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
fee_schedule_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{}

practice_insurance_fee_schedule_entry_destroy

Delete a single fee schedule entry.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
entry_uid
required
string <uuid>
fee_schedule_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_insurance_fee_schedule_retrieve

Retrieve, update, or delete a fee schedule.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
fee_schedule_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "carrier_name": "string",
  • "name": "string",
  • "effective_date": "2019-08-24",
  • "expiration_date": "2019-08-24",
  • "notes": "string",
  • "entry_count": 0,
  • "entries": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_insurance_fee_schedule_update

Retrieve, update, or delete a fee schedule.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
fee_schedule_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
carrier
string or null <uuid>
name
required
string [ 1 .. 255 ] characters
effective_date
string or null <date>
expiration_date
string or null <date>
notes
string
custom_data
any

Responses

Request samples

Content type
{
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "name": "string",
  • "effective_date": "2019-08-24",
  • "expiration_date": "2019-08-24",
  • "notes": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "carrier_name": "string",
  • "name": "string",
  • "effective_date": "2019-08-24",
  • "expiration_date": "2019-08-24",
  • "notes": "string",
  • "entry_count": 0,
  • "entries": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_insurance_fee_schedule_partial_update

Retrieve, update, or delete a fee schedule.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
fee_schedule_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
carrier
string or null <uuid>
name
string [ 1 .. 255 ] characters
effective_date
string or null <date>
expiration_date
string or null <date>
notes
string
custom_data
any

Responses

Request samples

Content type
{
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "name": "string",
  • "effective_date": "2019-08-24",
  • "expiration_date": "2019-08-24",
  • "notes": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "carrier_name": "string",
  • "name": "string",
  • "effective_date": "2019-08-24",
  • "expiration_date": "2019-08-24",
  • "notes": "string",
  • "entry_count": 0,
  • "entries": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_insurance_fee_schedule_destroy

Retrieve, update, or delete a fee schedule.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
fee_schedule_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_insurance_patient_insurance_partial_update

Handle PATCH on the list endpoint for bulk updates.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
patient
string <uuid>
insurance_plan
string or null <uuid>
carrier_name
string [ 1 .. 255 ] characters
carrier
string or null <uuid>
fee_schedule
string or null <uuid>

Fee schedule used for benefit estimation under this plan

group_number
string <= 100 characters
subscriber_id
string <= 100 characters
subscriber_name
string <= 255 characters

Policy holder name if different from patient

ordinal
integer [ 0 .. 32767 ]

1=primary, 2=secondary

RelationshipToSubscriberEnum (string) or BlankEnum (any)
effective_date
string or null <date>
termination_date
string or null <date>
custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "carrier_name": "string",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "group_number": "string",
  • "subscriber_id": "string",
  • "subscriber_name": "string",
  • "ordinal": 32767,
  • "relationship_to_subscriber": "self",
  • "effective_date": "2019-08-24",
  • "termination_date": "2019-08-24",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "carrier_name": "string",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "group_number": "string",
  • "subscriber_id": "string",
  • "subscriber_name": "string",
  • "ordinal": 32767,
  • "relationship_to_subscriber": "self",
  • "effective_date": "2019-08-24",
  • "termination_date": "2019-08-24",
  • "custom_data": null
}

practice_insurance_plan_benefit_retrieve

Update or delete a plan-level benefit.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
benefit_uid
required
string <uuid>
plan_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "custom_data": null,
  • "procedure_code": {
    },
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "benefit_type": "percentage",
  • "coverage_category": "diagnostic",
  • "percent": "string",
  • "monetary_amt": "string",
  • "time_period": "calendar_year",
  • "proc_code": "string",
  • "min_age": 32767,
  • "max_age": 32767,
  • "waiting_period_months": 32767,
  • "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
  • "modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "patient_insurance": "e396a8de-c249-4467-871f-c8b5f28219f1"
}

practice_insurance_plan_benefit_update

Update or delete a plan-level benefit.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
benefit_uid
required
string <uuid>
plan_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
insurance_plan
string or null <uuid>
BenefitTypeEnum (string) or BlankEnum (any)
CoverageCategoryEnum (string) or BlankEnum (any)
percent
string <decimal> ^-?\d{0,3}(?:\.\d{0,2})?$
monetary_amt
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
TimePeriodEnum (string) or BlankEnum (any)
proc_code
string <= 20 characters

Benefit tied to a specific procedure code

procedure_code
string or null <uuid>
min_age
integer or null [ 0 .. 32767 ]

Minimum patient age (inclusive) for this benefit to apply

max_age
integer or null [ 0 .. 32767 ]

Maximum patient age (inclusive) for this benefit to apply

waiting_period_months
integer or null [ 0 .. 32767 ]

Months from effective date before this benefit is available

custom_data
any

Responses

Request samples

Content type
{
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "benefit_type": "percentage",
  • "coverage_category": "diagnostic",
  • "percent": "string",
  • "monetary_amt": "string",
  • "time_period": "calendar_year",
  • "proc_code": "string",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "min_age": 32767,
  • "max_age": 32767,
  • "waiting_period_months": 32767,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "benefit_type": "percentage",
  • "coverage_category": "diagnostic",
  • "percent": "string",
  • "monetary_amt": "string",
  • "time_period": "calendar_year",
  • "proc_code": "string",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "min_age": 32767,
  • "max_age": 32767,
  • "waiting_period_months": 32767,
  • "custom_data": null
}

practice_insurance_plan_benefit_partial_update

Update or delete a plan-level benefit.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
benefit_uid
required
string <uuid>
plan_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
insurance_plan
string or null <uuid>
BenefitTypeEnum (string) or BlankEnum (any)
CoverageCategoryEnum (string) or BlankEnum (any)
percent
string <decimal> ^-?\d{0,3}(?:\.\d{0,2})?$
monetary_amt
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
TimePeriodEnum (string) or BlankEnum (any)
proc_code
string <= 20 characters

Benefit tied to a specific procedure code

procedure_code
string or null <uuid>
min_age
integer or null [ 0 .. 32767 ]

Minimum patient age (inclusive) for this benefit to apply

max_age
integer or null [ 0 .. 32767 ]

Maximum patient age (inclusive) for this benefit to apply

waiting_period_months
integer or null [ 0 .. 32767 ]

Months from effective date before this benefit is available

custom_data
any

Responses

Request samples

Content type
{
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "benefit_type": "percentage",
  • "coverage_category": "diagnostic",
  • "percent": "string",
  • "monetary_amt": "string",
  • "time_period": "calendar_year",
  • "proc_code": "string",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "min_age": 32767,
  • "max_age": 32767,
  • "waiting_period_months": 32767,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "benefit_type": "percentage",
  • "coverage_category": "diagnostic",
  • "percent": "string",
  • "monetary_amt": "string",
  • "time_period": "calendar_year",
  • "proc_code": "string",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "min_age": 32767,
  • "max_age": 32767,
  • "waiting_period_months": 32767,
  • "custom_data": null
}

practice_insurance_plan_benefit_destroy

Update or delete a plan-level benefit.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
benefit_uid
required
string <uuid>
plan_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_insurance_plan_retrieve

Retrieve, update, or delete an insurance plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "carrier_name": "string",
  • "plan_name": "string",
  • "group_name": "string",
  • "group_number": "string",
  • "employer_name": "string",
  • "plan_type": "ppo",
  • "annual_maximum": "string",
  • "individual_deductible": "string",
  • "family_deductible": "string",
  • "plan_year_begin_month": 32767,
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "notes": "string",
  • "is_active": true,
  • "benefits": [
    ],
  • "enrollment_count": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_insurance_plan_update

Retrieve, update, or delete an insurance plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
carrier
string or null <uuid>
plan_name
string <= 255 characters
group_name
string <= 255 characters
group_number
string <= 100 characters
employer_name
string <= 255 characters
PlanTypeEnum (string) or BlankEnum (any)
annual_maximum
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
individual_deductible
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
family_deductible
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
plan_year_begin_month
integer or null [ 0 .. 32767 ]

Month (1-12) when the plan year resets

fee_schedule
string or null <uuid>

Carrier-specific fee schedule (allowed amounts) for this plan

notes
string
is_active
boolean
Array of objects (InsuranceBenefitWriteRequest)
custom_data
any

Responses

Request samples

Content type
{
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "plan_name": "string",
  • "group_name": "string",
  • "group_number": "string",
  • "employer_name": "string",
  • "plan_type": "ppo",
  • "annual_maximum": "string",
  • "individual_deductible": "string",
  • "family_deductible": "string",
  • "plan_year_begin_month": 32767,
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "notes": "string",
  • "is_active": true,
  • "benefits": [
    ],
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "carrier_name": "string",
  • "plan_name": "string",
  • "group_name": "string",
  • "group_number": "string",
  • "employer_name": "string",
  • "plan_type": "ppo",
  • "annual_maximum": "string",
  • "individual_deductible": "string",
  • "family_deductible": "string",
  • "plan_year_begin_month": 32767,
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "notes": "string",
  • "is_active": true,
  • "benefits": [
    ],
  • "enrollment_count": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_insurance_plan_partial_update

Retrieve, update, or delete an insurance plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
carrier
string or null <uuid>
plan_name
string <= 255 characters
group_name
string <= 255 characters
group_number
string <= 100 characters
employer_name
string <= 255 characters
PlanTypeEnum (string) or BlankEnum (any)
annual_maximum
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
individual_deductible
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
family_deductible
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
plan_year_begin_month
integer or null [ 0 .. 32767 ]

Month (1-12) when the plan year resets

fee_schedule
string or null <uuid>

Carrier-specific fee schedule (allowed amounts) for this plan

notes
string
is_active
boolean
Array of objects (InsuranceBenefitWriteRequest)
custom_data
any

Responses

Request samples

Content type
{
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "plan_name": "string",
  • "group_name": "string",
  • "group_number": "string",
  • "employer_name": "string",
  • "plan_type": "ppo",
  • "annual_maximum": "string",
  • "individual_deductible": "string",
  • "family_deductible": "string",
  • "plan_year_begin_month": 32767,
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "notes": "string",
  • "is_active": true,
  • "benefits": [
    ],
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "carrier_name": "string",
  • "plan_name": "string",
  • "group_name": "string",
  • "group_number": "string",
  • "employer_name": "string",
  • "plan_type": "ppo",
  • "annual_maximum": "string",
  • "individual_deductible": "string",
  • "family_deductible": "string",
  • "plan_year_begin_month": 32767,
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "notes": "string",
  • "is_active": true,
  • "benefits": [
    ],
  • "enrollment_count": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_insurance_plan_destroy

Retrieve, update, or delete an insurance plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_insurance_verification_retrieve

Retrieve a single insurance verification.

Verifications are immutable snapshots -- this view only supports GET. Emits insurance.verification_viewed on each read.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
verification_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "verified_by": "8c493be0-efe2-4a3e-bdbd-7af0eab50aa2",
  • "verified_at": "2019-08-24T14:15:22Z",
  • "source": "phone",
  • "raw_response": null,
  • "annual_max": "string",
  • "deductible_total": "string",
  • "deductible_met": "string",
  • "waiting_period_notes": "string",
  • "frequency_limits": null,
  • "plan": {
    },
  • "patient_summary": {
    },
  • "verified_by_summary": {
    },
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_intake_lookup_retrieve

Search for an existing patient by last name and date of birth.

Both last_name and date_of_birth are required query parameters to prevent patient list enumeration from a kiosk.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

practice_intake_patient_create

Create a new patient from kiosk intake data.

Creates a Patient with status="prospective" plus related medical history and insurance records in a single atomic transaction.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_intake_patient_confirm_update

Existing patient confirms or updates their data at the kiosk.

Only provided fields are updated. Sets last_medical_review to today.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_billing_balance_retrieve

GET patient balance. Returns 404 if no balance record exists.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "custom_data": null,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "balance_total": "string",
  • "insurance_estimate": "string",
  • "patient_portion": "string",
  • "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
  • "modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb"
}

practice_patient_billing_payment_plan_retrieve

Retrieve or update a payment plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "custom_data": null,
  • "charges": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "plan_date": "2019-08-24",
  • "apr": "string",
  • "completed_amt": "string",
  • "is_closed": true,
  • "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
  • "modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "guarantor": "2dc581b4-936d-4ab3-8a7d-1fc8f857bc6f"
}

practice_patient_billing_payment_plan_update

Retrieve or update a payment plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
guarantor
string or null <uuid>
plan_date
string or null <date>
apr
string <decimal> ^-?\d{0,3}(?:\.\d{0,2})?$
completed_amt
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
is_closed
boolean
Array of objects (PaymentPlanChargeWriteRequest)
custom_data
any

Responses

Request samples

Content type
{
  • "guarantor": "2dc581b4-936d-4ab3-8a7d-1fc8f857bc6f",
  • "plan_date": "2019-08-24",
  • "apr": "string",
  • "completed_amt": "string",
  • "is_closed": true,
  • "charges": [
    ],
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "guarantor": "2dc581b4-936d-4ab3-8a7d-1fc8f857bc6f",
  • "plan_date": "2019-08-24",
  • "apr": "string",
  • "completed_amt": "string",
  • "is_closed": true,
  • "charges": [
    ],
  • "custom_data": null
}

practice_patient_billing_payment_plan_partial_update

Retrieve or update a payment plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
guarantor
string or null <uuid>
plan_date
string or null <date>
apr
string <decimal> ^-?\d{0,3}(?:\.\d{0,2})?$
completed_amt
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
is_closed
boolean
Array of objects (PaymentPlanChargeWriteRequest)
custom_data
any

Responses

Request samples

Content type
{
  • "guarantor": "2dc581b4-936d-4ab3-8a7d-1fc8f857bc6f",
  • "plan_date": "2019-08-24",
  • "apr": "string",
  • "completed_amt": "string",
  • "is_closed": true,
  • "charges": [
    ],
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "guarantor": "2dc581b4-936d-4ab3-8a7d-1fc8f857bc6f",
  • "plan_date": "2019-08-24",
  • "apr": "string",
  • "completed_amt": "string",
  • "is_closed": true,
  • "charges": [
    ],
  • "custom_data": null
}

practice_patient_billing_payment_retrieve

Retrieve or update a payment record.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
payment_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "custom_data": null,
  • "splits": [
    ],
  • "patient_name": "string",
  • "patient_first_name": "string",
  • "patient_last_name": "string",
  • "provider_name": "string",
  • "pay_method": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "pay_date": "2019-08-24",
  • "pay_amount": "string",
  • "pay_type": "string",
  • "pay_note": "string",
  • "stripe_payment_intent_id": "string",
  • "stripe_status": "PENDING",
  • "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
  • "modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9"
}

practice_patient_billing_payment_update

Retrieve or update a payment record.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
payment_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
pay_date
string or null <date>
pay_amount
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
pay_type
string <= 100 characters
pay_note
string
provider
string or null <uuid>
custom_data
any
Array of objects (PaymentSplitWriteRequest)

Responses

Request samples

Content type
{
  • "pay_date": "2019-08-24",
  • "pay_amount": "string",
  • "pay_type": "string",
  • "pay_note": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "custom_data": null,
  • "splits": [
    ]
}

Response samples

Content type
application/json
{
  • "pay_date": "2019-08-24",
  • "pay_amount": "string",
  • "pay_type": "string",
  • "pay_note": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "custom_data": null,
  • "splits": [
    ]
}

practice_patient_billing_payment_partial_update

Retrieve or update a payment record.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
payment_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
pay_date
string or null <date>
pay_amount
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
pay_type
string <= 100 characters
pay_note
string
provider
string or null <uuid>
custom_data
any
Array of objects (PaymentSplitWriteRequest)

Responses

Request samples

Content type
{
  • "pay_date": "2019-08-24",
  • "pay_amount": "string",
  • "pay_type": "string",
  • "pay_note": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "custom_data": null,
  • "splits": [
    ]
}

Response samples

Content type
application/json
{
  • "pay_date": "2019-08-24",
  • "pay_amount": "string",
  • "pay_type": "string",
  • "pay_note": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "custom_data": null,
  • "splits": [
    ]
}

practice_patient_clinical_allergy_list

List and create allergies for a patient.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_clinical_allergy_create

List and create allergies for a patient.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
allergy_name
required
string [ 1 .. 255 ] characters
reaction
string <= 255 characters
is_active
boolean
date_reaction
string or null <date>
custom_data
any

Responses

Request samples

Content type
{
  • "allergy_name": "string",
  • "reaction": "string",
  • "is_active": true,
  • "date_reaction": "2019-08-24",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "allergy_name": "string",
  • "reaction": "string",
  • "is_active": true,
  • "date_reaction": "2019-08-24",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_allergy_retrieve

Retrieve, update, or delete a patient allergy.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
allergy_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "allergy_name": "string",
  • "reaction": "string",
  • "is_active": true,
  • "date_reaction": "2019-08-24",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_allergy_update

Retrieve, update, or delete a patient allergy.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
allergy_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
allergy_name
required
string [ 1 .. 255 ] characters
reaction
string <= 255 characters
is_active
boolean
date_reaction
string or null <date>
custom_data
any

Responses

Request samples

Content type
{
  • "allergy_name": "string",
  • "reaction": "string",
  • "is_active": true,
  • "date_reaction": "2019-08-24",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "allergy_name": "string",
  • "reaction": "string",
  • "is_active": true,
  • "date_reaction": "2019-08-24",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_allergy_partial_update

Retrieve, update, or delete a patient allergy.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
allergy_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
allergy_name
string [ 1 .. 255 ] characters
reaction
string <= 255 characters
is_active
boolean
date_reaction
string or null <date>
custom_data
any

Responses

Request samples

Content type
{
  • "allergy_name": "string",
  • "reaction": "string",
  • "is_active": true,
  • "date_reaction": "2019-08-24",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "allergy_name": "string",
  • "reaction": "string",
  • "is_active": true,
  • "date_reaction": "2019-08-24",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_allergy_destroy

Retrieve, update, or delete a patient allergy.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
allergy_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_clinical_anesthesia_retrieve

Retrieve or update an anesthesia record.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
anesthesia_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "agent": "lidocaine_epi",
  • "agent_display": "string",
  • "agent_other": "string",
  • "route": "infiltration",
  • "route_display": "string",
  • "site": "string",
  • "carpules": "string",
  • "lot_number": "string",
  • "expiration_date": "2019-08-24",
  • "administered_at": "2019-08-24T14:15:22Z",
  • "note": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_anesthesia_update

Retrieve or update an anesthesia record.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
anesthesia_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
appointment
string or null <uuid>
provider
string or null <uuid>
agent
required
string (AgentEnum)
Enum: "lidocaine_epi" "lidocaine" "articaine_epi" "articaine_epi_200" "mepivacaine_epi" "mepivacaine" "bupivacaine_epi" "prilocaine_epi" "prilocaine" "topical_benzocaine" "topical_lidocaine" "nitrous" "other"
  • lidocaine_epi - Lidocaine 2% with Epinephrine 1:100,000
  • lidocaine - Lidocaine 2% (plain)
  • articaine_epi - Articaine 4% with Epinephrine 1:100,000
  • articaine_epi_200 - Articaine 4% with Epinephrine 1:200,000
  • mepivacaine_epi - Mepivacaine 2% with Levonordefrin 1:20,000
  • mepivacaine - Mepivacaine 3% (plain)
  • bupivacaine_epi - Bupivacaine 0.5% with Epinephrine 1:200,000
  • prilocaine_epi - Prilocaine 4% with Epinephrine 1:200,000
  • prilocaine - Prilocaine 4% (plain)
  • topical_benzocaine - Topical Benzocaine 20%
  • topical_lidocaine - Topical Lidocaine 5%
  • nitrous - Nitrous Oxide / Oxygen
  • other - Other
agent_other
string <= 100 characters

If agent=other, specify here

route
string (RouteEnum)
Enum: "infiltration" "block" "topical" "inhalation"
  • infiltration - Infiltration
  • block - Block
  • topical - Topical
  • inhalation - Inhalation
site
string <= 100 characters

e.g. #14 buccal infiltration, right IAN block

carpules
string <decimal> ^-?\d{0,2}(?:\.\d{0,1})?$

Number of carpules administered

lot_number
string <= 50 characters
expiration_date
string or null <date>
administered_at
required
string <date-time>

When the anesthesia was administered

note
string

Complications, reactions, or additional notes

custom_data
any

Responses

Request samples

Content type
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "agent": "lidocaine_epi",
  • "agent_other": "string",
  • "route": "infiltration",
  • "site": "string",
  • "carpules": "string",
  • "lot_number": "string",
  • "expiration_date": "2019-08-24",
  • "administered_at": "2019-08-24T14:15:22Z",
  • "note": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "agent": "lidocaine_epi",
  • "agent_other": "string",
  • "route": "infiltration",
  • "site": "string",
  • "carpules": "string",
  • "lot_number": "string",
  • "expiration_date": "2019-08-24",
  • "administered_at": "2019-08-24T14:15:22Z",
  • "note": "string",
  • "custom_data": null
}

practice_patient_clinical_anesthesia_partial_update

Retrieve or update an anesthesia record.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
anesthesia_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
appointment
string or null <uuid>
provider
string or null <uuid>
agent
string (AgentEnum)
Enum: "lidocaine_epi" "lidocaine" "articaine_epi" "articaine_epi_200" "mepivacaine_epi" "mepivacaine" "bupivacaine_epi" "prilocaine_epi" "prilocaine" "topical_benzocaine" "topical_lidocaine" "nitrous" "other"
  • lidocaine_epi - Lidocaine 2% with Epinephrine 1:100,000
  • lidocaine - Lidocaine 2% (plain)
  • articaine_epi - Articaine 4% with Epinephrine 1:100,000
  • articaine_epi_200 - Articaine 4% with Epinephrine 1:200,000
  • mepivacaine_epi - Mepivacaine 2% with Levonordefrin 1:20,000
  • mepivacaine - Mepivacaine 3% (plain)
  • bupivacaine_epi - Bupivacaine 0.5% with Epinephrine 1:200,000
  • prilocaine_epi - Prilocaine 4% with Epinephrine 1:200,000
  • prilocaine - Prilocaine 4% (plain)
  • topical_benzocaine - Topical Benzocaine 20%
  • topical_lidocaine - Topical Lidocaine 5%
  • nitrous - Nitrous Oxide / Oxygen
  • other - Other
agent_other
string <= 100 characters

If agent=other, specify here

route
string (RouteEnum)
Enum: "infiltration" "block" "topical" "inhalation"
  • infiltration - Infiltration
  • block - Block
  • topical - Topical
  • inhalation - Inhalation
site
string <= 100 characters

e.g. #14 buccal infiltration, right IAN block

carpules
string <decimal> ^-?\d{0,2}(?:\.\d{0,1})?$

Number of carpules administered

lot_number
string <= 50 characters
expiration_date
string or null <date>
administered_at
string <date-time>

When the anesthesia was administered

note
string

Complications, reactions, or additional notes

custom_data
any

Responses

Request samples

Content type
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "agent": "lidocaine_epi",
  • "agent_other": "string",
  • "route": "infiltration",
  • "site": "string",
  • "carpules": "string",
  • "lot_number": "string",
  • "expiration_date": "2019-08-24",
  • "administered_at": "2019-08-24T14:15:22Z",
  • "note": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "agent": "lidocaine_epi",
  • "agent_other": "string",
  • "route": "infiltration",
  • "site": "string",
  • "carpules": "string",
  • "lot_number": "string",
  • "expiration_date": "2019-08-24",
  • "administered_at": "2019-08-24T14:15:22Z",
  • "note": "string",
  • "custom_data": null
}

practice_patient_clinical_condition_list

List and create medical conditions for a patient.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_clinical_condition_create

List and create medical conditions for a patient.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
condition_name
required
string [ 1 .. 255 ] characters
date_start
string or null <date>
date_stop
string or null <date>
note
string
custom_data
any

Responses

Request samples

Content type
{
  • "condition_name": "string",
  • "date_start": "2019-08-24",
  • "date_stop": "2019-08-24",
  • "note": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "condition_name": "string",
  • "date_start": "2019-08-24",
  • "date_stop": "2019-08-24",
  • "note": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_condition_retrieve

Retrieve, update, or delete a patient medical condition.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
condition_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "condition_name": "string",
  • "date_start": "2019-08-24",
  • "date_stop": "2019-08-24",
  • "note": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_condition_update

Retrieve, update, or delete a patient medical condition.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
condition_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
condition_name
required
string [ 1 .. 255 ] characters
date_start
string or null <date>
date_stop
string or null <date>
note
string
custom_data
any

Responses

Request samples

Content type
{
  • "condition_name": "string",
  • "date_start": "2019-08-24",
  • "date_stop": "2019-08-24",
  • "note": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "condition_name": "string",
  • "date_start": "2019-08-24",
  • "date_stop": "2019-08-24",
  • "note": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_condition_partial_update

Retrieve, update, or delete a patient medical condition.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
condition_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
condition_name
string [ 1 .. 255 ] characters
date_start
string or null <date>
date_stop
string or null <date>
note
string
custom_data
any

Responses

Request samples

Content type
{
  • "condition_name": "string",
  • "date_start": "2019-08-24",
  • "date_stop": "2019-08-24",
  • "note": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "condition_name": "string",
  • "date_start": "2019-08-24",
  • "date_stop": "2019-08-24",
  • "note": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_condition_destroy

Retrieve, update, or delete a patient medical condition.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
condition_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_clinical_education_retrieve

Retrieve, update, or delete a patient education record.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
education_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "topic": "oral_hygiene",
  • "topic_display": "string",
  • "detail": "string",
  • "products_recommended": "string",
  • "education_date": "2019-08-24",
  • "compliance_note": "string",
  • "send_to_portal": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_education_update

Retrieve, update, or delete a patient education record.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
education_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
appointment
string or null <uuid>
provider
string or null <uuid>
topic
required
string (TopicEnum)
Enum: "oral_hygiene" "brushing" "flossing" "interproximal" "electric_toothbrush" "fluoride" "diet_counseling" "tobacco_cessation" "perio_disease" "caries_risk" "dry_mouth" "bruxism" "sensitivity" "whitening" "ortho_care" "implant_care" "post_op" "pre_med" "other"
  • oral_hygiene - Oral Hygiene Instructions
  • brushing - Brushing Technique
  • flossing - Flossing Technique
  • interproximal - Interproximal Cleaning
  • electric_toothbrush - Electric Toothbrush
  • fluoride - Fluoride Use
  • diet_counseling - Diet Counseling
  • tobacco_cessation - Tobacco Cessation
  • perio_disease - Periodontal Disease
  • caries_risk - Caries Risk
  • dry_mouth - Dry Mouth / Xerostomia
  • bruxism - Bruxism / Night Guard
  • sensitivity - Sensitivity
  • whitening - Whitening Options
  • ortho_care - Orthodontic Care
  • implant_care - Implant Care
  • post_op - Post-Operative Instructions
  • pre_med - Premedication Reminder
  • other - Other
detail
string

Specific instructions or notes about what was discussed

products_recommended
string <= 255 characters

e.g. Sonicare, Waterpik, MI Paste

education_date
required
string <date>
compliance_note
string

Patient response, compliance observations

send_to_portal
boolean

Make available in patient portal

custom_data
any

Responses

Request samples

Content type
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "topic": "oral_hygiene",
  • "detail": "string",
  • "products_recommended": "string",
  • "education_date": "2019-08-24",
  • "compliance_note": "string",
  • "send_to_portal": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "topic": "oral_hygiene",
  • "detail": "string",
  • "products_recommended": "string",
  • "education_date": "2019-08-24",
  • "compliance_note": "string",
  • "send_to_portal": true,
  • "custom_data": null
}

practice_patient_clinical_education_partial_update

Retrieve, update, or delete a patient education record.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
education_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
appointment
string or null <uuid>
provider
string or null <uuid>
topic
string (TopicEnum)
Enum: "oral_hygiene" "brushing" "flossing" "interproximal" "electric_toothbrush" "fluoride" "diet_counseling" "tobacco_cessation" "perio_disease" "caries_risk" "dry_mouth" "bruxism" "sensitivity" "whitening" "ortho_care" "implant_care" "post_op" "pre_med" "other"
  • oral_hygiene - Oral Hygiene Instructions
  • brushing - Brushing Technique
  • flossing - Flossing Technique
  • interproximal - Interproximal Cleaning
  • electric_toothbrush - Electric Toothbrush
  • fluoride - Fluoride Use
  • diet_counseling - Diet Counseling
  • tobacco_cessation - Tobacco Cessation
  • perio_disease - Periodontal Disease
  • caries_risk - Caries Risk
  • dry_mouth - Dry Mouth / Xerostomia
  • bruxism - Bruxism / Night Guard
  • sensitivity - Sensitivity
  • whitening - Whitening Options
  • ortho_care - Orthodontic Care
  • implant_care - Implant Care
  • post_op - Post-Operative Instructions
  • pre_med - Premedication Reminder
  • other - Other
detail
string

Specific instructions or notes about what was discussed

products_recommended
string <= 255 characters

e.g. Sonicare, Waterpik, MI Paste

education_date
string <date>
compliance_note
string

Patient response, compliance observations

send_to_portal
boolean

Make available in patient portal

custom_data
any

Responses

Request samples

Content type
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "topic": "oral_hygiene",
  • "detail": "string",
  • "products_recommended": "string",
  • "education_date": "2019-08-24",
  • "compliance_note": "string",
  • "send_to_portal": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "topic": "oral_hygiene",
  • "detail": "string",
  • "products_recommended": "string",
  • "education_date": "2019-08-24",
  • "compliance_note": "string",
  • "send_to_portal": true,
  • "custom_data": null
}

practice_patient_clinical_education_destroy

Retrieve, update, or delete a patient education record.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
education_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_clinical_medication_list

List and create medications for a patient.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_clinical_medication_create

List and create medications for a patient.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
medication_name
required
string [ 1 .. 255 ] characters
date_start
string or null <date>
date_stop
string or null <date>
note
string
rx_cui
string <= 20 characters

RxNorm concept unique identifier

custom_data
any

Responses

Request samples

Content type
{
  • "medication_name": "string",
  • "date_start": "2019-08-24",
  • "date_stop": "2019-08-24",
  • "note": "string",
  • "rx_cui": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "medication_name": "string",
  • "date_start": "2019-08-24",
  • "date_stop": "2019-08-24",
  • "note": "string",
  • "rx_cui": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_medication_retrieve

Retrieve, update, or delete a patient medication.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
medication_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "medication_name": "string",
  • "date_start": "2019-08-24",
  • "date_stop": "2019-08-24",
  • "note": "string",
  • "rx_cui": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_medication_update

Retrieve, update, or delete a patient medication.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
medication_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
medication_name
required
string [ 1 .. 255 ] characters
date_start
string or null <date>
date_stop
string or null <date>
note
string
rx_cui
string <= 20 characters

RxNorm concept unique identifier

custom_data
any

Responses

Request samples

Content type
{
  • "medication_name": "string",
  • "date_start": "2019-08-24",
  • "date_stop": "2019-08-24",
  • "note": "string",
  • "rx_cui": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "medication_name": "string",
  • "date_start": "2019-08-24",
  • "date_stop": "2019-08-24",
  • "note": "string",
  • "rx_cui": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_medication_partial_update

Retrieve, update, or delete a patient medication.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
medication_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
medication_name
string [ 1 .. 255 ] characters
date_start
string or null <date>
date_stop
string or null <date>
note
string
rx_cui
string <= 20 characters

RxNorm concept unique identifier

custom_data
any

Responses

Request samples

Content type
{
  • "medication_name": "string",
  • "date_start": "2019-08-24",
  • "date_stop": "2019-08-24",
  • "note": "string",
  • "rx_cui": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "medication_name": "string",
  • "date_start": "2019-08-24",
  • "date_stop": "2019-08-24",
  • "note": "string",
  • "rx_cui": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_medication_destroy

Retrieve, update, or delete a patient medication.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
medication_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_clinical_note_retrieve

Retrieve or update a clinical note. PATCH is blocked if the note is signed.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
note_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "template_name": "string",
  • "note_type": "clinical",
  • "subject": "string",
  • "content": "string",
  • "note_date": "2019-08-24",
  • "is_signed": true,
  • "signed_by": "66eaecaf-2581-4b22-b9af-2f669ed2f9ba",
  • "signed_at": "2019-08-24T14:15:22Z",
  • "is_addendum": true,
  • "parent_note": "47e0a283-e822-462a-a025-efa34db2b778",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
  • "custom_data": null
}

practice_patient_clinical_note_update

Retrieve or update a clinical note. PATCH is blocked if the note is signed.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
note_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
appointment
string or null <uuid>
provider
string or null <uuid>
template
string or null <uuid>

Template used to create this note (reference only, content is copied)

note_type
string (NoteTypeEnum)
Enum: "clinical" "exam" "hygiene" "consult" "phone" "lab" "other"
  • clinical - Clinical Note
  • exam - Exam Note
  • hygiene - Hygiene Note
  • consult - Consult Note
  • phone - Phone Note
  • lab - Lab Note
  • other - Other
subject
string <= 200 characters
content
string

Plain text or structured note content

note_date
string or null <date>
is_addendum
boolean

Addendum to a previous note

parent_note
string or null <uuid>

If is_addendum=True, the original note this amends

custom_data
any

Responses

Request samples

Content type
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "note_type": "clinical",
  • "subject": "string",
  • "content": "string",
  • "note_date": "2019-08-24",
  • "is_addendum": true,
  • "parent_note": "47e0a283-e822-462a-a025-efa34db2b778",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "note_type": "clinical",
  • "subject": "string",
  • "content": "string",
  • "note_date": "2019-08-24",
  • "is_addendum": true,
  • "parent_note": "47e0a283-e822-462a-a025-efa34db2b778",
  • "custom_data": null
}

practice_patient_clinical_note_partial_update

Retrieve or update a clinical note. PATCH is blocked if the note is signed.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
note_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
appointment
string or null <uuid>
provider
string or null <uuid>
template
string or null <uuid>

Template used to create this note (reference only, content is copied)

note_type
string (NoteTypeEnum)
Enum: "clinical" "exam" "hygiene" "consult" "phone" "lab" "other"
  • clinical - Clinical Note
  • exam - Exam Note
  • hygiene - Hygiene Note
  • consult - Consult Note
  • phone - Phone Note
  • lab - Lab Note
  • other - Other
subject
string <= 200 characters
content
string

Plain text or structured note content

note_date
string or null <date>
is_addendum
boolean

Addendum to a previous note

parent_note
string or null <uuid>

If is_addendum=True, the original note this amends

custom_data
any

Responses

Request samples

Content type
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "note_type": "clinical",
  • "subject": "string",
  • "content": "string",
  • "note_date": "2019-08-24",
  • "is_addendum": true,
  • "parent_note": "47e0a283-e822-462a-a025-efa34db2b778",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "note_type": "clinical",
  • "subject": "string",
  • "content": "string",
  • "note_date": "2019-08-24",
  • "is_addendum": true,
  • "parent_note": "47e0a283-e822-462a-a025-efa34db2b778",
  • "custom_data": null
}

practice_patient_clinical_perio_list

List and create periodontal exams for a patient.

GET returns exams ordered by most recent first, with readings prefetched.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_clinical_perio_create

List and create periodontal exams for a patient.

GET returns exams ordered by most recent first, with readings prefetched.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
provider
string or null <uuid>
appointment
string or null <uuid>
exam_date
required
string <date-time>
is_completed
boolean

Completed exams cannot be deleted

StageEnum (string) or BlankEnum (any)
GradeEnum (string) or BlankEnum (any)
note
string
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "exam_date": "2019-08-24T14:15:22Z",
  • "is_completed": true,
  • "stage": "healthy",
  • "grade": "grade_a",
  • "note": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "exam_date": "2019-08-24T14:15:22Z",
  • "is_completed": true,
  • "stage": "healthy",
  • "grade": "grade_a",
  • "note": "string",
  • "custom_data": null
}

practice_patient_clinical_perio_retrieve

Retrieve, update, or delete a periodontal exam.

Completed exams cannot be deleted (returns 422).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
perio_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "exam_date": "2019-08-24T14:15:22Z",
  • "is_completed": true,
  • "stage": "healthy",
  • "grade": "grade_a",
  • "note": "string",
  • "readings": [
    ],
  • "reading_count": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_perio_update

Retrieve, update, or delete a periodontal exam.

Completed exams cannot be deleted (returns 422).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
perio_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
provider
string or null <uuid>
appointment
string or null <uuid>
exam_date
required
string <date-time>
is_completed
boolean

Completed exams cannot be deleted

StageEnum (string) or BlankEnum (any)
GradeEnum (string) or BlankEnum (any)
note
string
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "exam_date": "2019-08-24T14:15:22Z",
  • "is_completed": true,
  • "stage": "healthy",
  • "grade": "grade_a",
  • "note": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "exam_date": "2019-08-24T14:15:22Z",
  • "is_completed": true,
  • "stage": "healthy",
  • "grade": "grade_a",
  • "note": "string",
  • "custom_data": null
}

practice_patient_clinical_perio_partial_update

Retrieve, update, or delete a periodontal exam.

Completed exams cannot be deleted (returns 422).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
perio_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
provider
string or null <uuid>
appointment
string or null <uuid>
exam_date
string <date-time>
is_completed
boolean

Completed exams cannot be deleted

StageEnum (string) or BlankEnum (any)
GradeEnum (string) or BlankEnum (any)
note
string
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "exam_date": "2019-08-24T14:15:22Z",
  • "is_completed": true,
  • "stage": "healthy",
  • "grade": "grade_a",
  • "note": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "exam_date": "2019-08-24T14:15:22Z",
  • "is_completed": true,
  • "stage": "healthy",
  • "grade": "grade_a",
  • "note": "string",
  • "custom_data": null
}

practice_patient_clinical_perio_destroy

Retrieve, update, or delete a periodontal exam.

Completed exams cannot be deleted (returns 422).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
perio_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_clinical_procedure_retrieve

Retrieve, update, or delete a procedure.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
procedure_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "procedure_code": {
    },
  • "proc_code": "string",
  • "description": "string",
  • "proc_date": "2019-08-24",
  • "date_complete": "2019-08-24",
  • "proc_fee": "string",
  • "status": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "discount": "string",
  • "unit_qty": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_procedure_update

Retrieve, update, or delete a procedure.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
procedure_uid
required
string <uuid>
Request Body schema:
provider
string or null <uuid>
appointment
string or null <uuid>
procedure_code
string or null <uuid>
proc_code
string <= 20 characters
description
string <= 255 characters
proc_date
string or null <date>
proc_fee
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
status
string <= 30 characters

complete, existing_current, existing_other

tooth_num
string <= 10 characters
surface
string <= 20 characters
discount
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
unit_qty
integer [ 0 .. 2147483647 ]
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "proc_code": "string",
  • "description": "string",
  • "proc_date": "2019-08-24",
  • "proc_fee": "string",
  • "status": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "discount": "string",
  • "unit_qty": 2147483647,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "proc_code": "string",
  • "description": "string",
  • "proc_date": "2019-08-24",
  • "proc_fee": "string",
  • "status": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "discount": "string",
  • "unit_qty": 2147483647,
  • "custom_data": null
}

practice_patient_clinical_procedure_partial_update

Retrieve, update, or delete a procedure.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
procedure_uid
required
string <uuid>
Request Body schema:
provider
string or null <uuid>
appointment
string or null <uuid>
procedure_code
string or null <uuid>
proc_code
string <= 20 characters
description
string <= 255 characters
proc_date
string or null <date>
proc_fee
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
status
string <= 30 characters

complete, existing_current, existing_other

tooth_num
string <= 10 characters
surface
string <= 20 characters
discount
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
unit_qty
integer [ 0 .. 2147483647 ]
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "proc_code": "string",
  • "description": "string",
  • "proc_date": "2019-08-24",
  • "proc_fee": "string",
  • "status": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "discount": "string",
  • "unit_qty": 2147483647,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "proc_code": "string",
  • "description": "string",
  • "proc_date": "2019-08-24",
  • "proc_fee": "string",
  • "status": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "discount": "string",
  • "unit_qty": 2147483647,
  • "custom_data": null
}

practice_patient_clinical_procedure_destroy

Retrieve, update, or delete a procedure.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
procedure_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_clinical_tooth_retrieve

Retrieve, update, or delete a tooth condition.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
tooth_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "tooth_num": "strin",
  • "condition": "missing",
  • "dentition": "permanent",
  • "surfaces": "string",
  • "material": "string",
  • "note": "string",
  • "date_identified": "2019-08-24",
  • "is_current": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_tooth_update

Retrieve, update, or delete a tooth condition.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
tooth_uid
required
string <uuid>
Request Body schema:
required
tooth_num
required
string [ 1 .. 5 ] characters

Universal numbering: 1-32 (permanent), A-T (primary)

condition
required
string (ConditionEnum)
Enum: "missing" "implant" "crown" "bridge_abutment" "bridge_pontic" "veneer" "root_canal" "extraction_planned" "impacted" "unerupted" "supernumerary" "deciduous" "denture" "partial_denture" "caries" "filling" "sealant" "fracture" "watch"
  • missing - Missing
  • implant - Implant
  • crown - Crown
  • bridge_abutment - Bridge Abutment
  • bridge_pontic - Bridge Pontic
  • veneer - Veneer
  • root_canal - Root Canal
  • extraction_planned - Extraction Planned
  • impacted - Impacted
  • unerupted - Unerupted
  • supernumerary - Supernumerary
  • deciduous - Deciduous / Primary
  • denture - Denture
  • partial_denture - Partial Denture
  • caries - Caries
  • filling - Filling
  • sealant - Sealant
  • fracture - Fracture
  • watch - Watch
dentition
string (DentitionEnum)
Enum: "permanent" "primary"
  • permanent - Permanent
  • primary - Primary
surfaces
string <= 10 characters

Affected surfaces: M, O, D, B/F, L, I (e.g. 'MOD')

material
string <= 50 characters

e.g. PFM, zirconia, amalgam, composite

note
string
date_identified
string or null <date>
is_current
boolean

False = historical condition superseded by a newer one

custom_data
any

Responses

Request samples

Content type
{
  • "tooth_num": "strin",
  • "condition": "missing",
  • "dentition": "permanent",
  • "surfaces": "string",
  • "material": "string",
  • "note": "string",
  • "date_identified": "2019-08-24",
  • "is_current": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "tooth_num": "strin",
  • "condition": "missing",
  • "dentition": "permanent",
  • "surfaces": "string",
  • "material": "string",
  • "note": "string",
  • "date_identified": "2019-08-24",
  • "is_current": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_tooth_partial_update

Retrieve, update, or delete a tooth condition.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
tooth_uid
required
string <uuid>
Request Body schema:
tooth_num
string [ 1 .. 5 ] characters

Universal numbering: 1-32 (permanent), A-T (primary)

condition
string (ConditionEnum)
Enum: "missing" "implant" "crown" "bridge_abutment" "bridge_pontic" "veneer" "root_canal" "extraction_planned" "impacted" "unerupted" "supernumerary" "deciduous" "denture" "partial_denture" "caries" "filling" "sealant" "fracture" "watch"
  • missing - Missing
  • implant - Implant
  • crown - Crown
  • bridge_abutment - Bridge Abutment
  • bridge_pontic - Bridge Pontic
  • veneer - Veneer
  • root_canal - Root Canal
  • extraction_planned - Extraction Planned
  • impacted - Impacted
  • unerupted - Unerupted
  • supernumerary - Supernumerary
  • deciduous - Deciduous / Primary
  • denture - Denture
  • partial_denture - Partial Denture
  • caries - Caries
  • filling - Filling
  • sealant - Sealant
  • fracture - Fracture
  • watch - Watch
dentition
string (DentitionEnum)
Enum: "permanent" "primary"
  • permanent - Permanent
  • primary - Primary
surfaces
string <= 10 characters

Affected surfaces: M, O, D, B/F, L, I (e.g. 'MOD')

material
string <= 50 characters

e.g. PFM, zirconia, amalgam, composite

note
string
date_identified
string or null <date>
is_current
boolean

False = historical condition superseded by a newer one

custom_data
any

Responses

Request samples

Content type
{
  • "tooth_num": "strin",
  • "condition": "missing",
  • "dentition": "permanent",
  • "surfaces": "string",
  • "material": "string",
  • "note": "string",
  • "date_identified": "2019-08-24",
  • "is_current": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "tooth_num": "strin",
  • "condition": "missing",
  • "dentition": "permanent",
  • "surfaces": "string",
  • "material": "string",
  • "note": "string",
  • "date_identified": "2019-08-24",
  • "is_current": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_tooth_destroy

Retrieve, update, or delete a tooth condition.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
tooth_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_clinical_treatment_plan_retrieve

Retrieve, update, or delete a treatment plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "name": "string",
  • "status": "active",
  • "date_created": "2019-08-24",
  • "date_accepted": "2019-08-24",
  • "note": "string",
  • "items": [
    ],
  • "item_count": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_treatment_plan_update

Retrieve, update, or delete a treatment plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
provider
string or null <uuid>
name
required
string [ 1 .. 200 ] characters
note
string
status
string (TreatmentPlanStatusEnum)
Enum: "active" "accepted" "declined" "completed" "archived"
  • active - Active
  • accepted - Accepted
  • declined - Declined
  • completed - Completed
  • archived - Archived
date_accepted
string or null <date>
custom_data
any
Array of objects (TreatmentPlanItemWriteRequest)

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "name": "string",
  • "note": "string",
  • "status": "active",
  • "date_accepted": "2019-08-24",
  • "custom_data": null,
  • "items": [
    ]
}

Response samples

Content type
application/json
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "name": "string",
  • "note": "string",
  • "status": "active",
  • "date_accepted": "2019-08-24",
  • "custom_data": null,
  • "items": [
    ]
}

practice_patient_clinical_treatment_plan_partial_update

Retrieve, update, or delete a treatment plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
provider
string or null <uuid>
name
string [ 1 .. 200 ] characters
note
string
status
string (TreatmentPlanStatusEnum)
Enum: "active" "accepted" "declined" "completed" "archived"
  • active - Active
  • accepted - Accepted
  • declined - Declined
  • completed - Completed
  • archived - Archived
date_accepted
string or null <date>
custom_data
any
Array of objects (TreatmentPlanItemWriteRequest)

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "name": "string",
  • "note": "string",
  • "status": "active",
  • "date_accepted": "2019-08-24",
  • "custom_data": null,
  • "items": [
    ]
}

Response samples

Content type
application/json
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "name": "string",
  • "note": "string",
  • "status": "active",
  • "date_accepted": "2019-08-24",
  • "custom_data": null,
  • "items": [
    ]
}

practice_patient_clinical_treatment_plan_destroy

Retrieve, update, or delete a treatment plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_clinical_treatment_plan_item_list

List and create items within a treatment plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_clinical_treatment_plan_item_create

List and create items within a treatment plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
provider
string or null <uuid>
procedure_code
string or null <uuid>
proc_code
string <= 20 characters
description
string <= 255 characters
tooth_num
string <= 10 characters
surface
string <= 20 characters
planned_fee
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
date_planned
string or null <date>
status
string <= 30 characters

planned, completed

plan_name
string <= 255 characters
priority
integer [ 0 .. 2147483647 ]
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "proc_code": "string",
  • "description": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "planned_fee": "string",
  • "date_planned": "2019-08-24",
  • "status": "string",
  • "plan_name": "string",
  • "priority": 2147483647,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "treatment_plan": "c4c01122-8b32-4bce-bbce-bb1bda9a1a32",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "proc_code": "string",
  • "procedure_code_fee": "string",
  • "description": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "planned_fee": "string",
  • "date_planned": "2019-08-24",
  • "status": "string",
  • "est_primary_ins": "string",
  • "est_secondary_ins": "string",
  • "plan_name": "string",
  • "priority": 2147483647,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_treatment_plan_item_retrieve

Retrieve, update, or delete a treatment plan item.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
item_uid
required
string <uuid>
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "treatment_plan": "c4c01122-8b32-4bce-bbce-bb1bda9a1a32",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "proc_code": "string",
  • "procedure_code_fee": "string",
  • "description": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "planned_fee": "string",
  • "date_planned": "2019-08-24",
  • "status": "string",
  • "est_primary_ins": "string",
  • "est_secondary_ins": "string",
  • "plan_name": "string",
  • "priority": 2147483647,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_treatment_plan_item_update

Retrieve, update, or delete a treatment plan item.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
item_uid
required
string <uuid>
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
provider
string or null <uuid>
procedure_code
string or null <uuid>
proc_code
string <= 20 characters
description
string <= 255 characters
tooth_num
string <= 10 characters
surface
string <= 20 characters
planned_fee
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
date_planned
string or null <date>
status
string <= 30 characters

planned, completed

plan_name
string <= 255 characters
priority
integer [ 0 .. 2147483647 ]
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "proc_code": "string",
  • "description": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "planned_fee": "string",
  • "date_planned": "2019-08-24",
  • "status": "string",
  • "plan_name": "string",
  • "priority": 2147483647,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "treatment_plan": "c4c01122-8b32-4bce-bbce-bb1bda9a1a32",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "proc_code": "string",
  • "procedure_code_fee": "string",
  • "description": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "planned_fee": "string",
  • "date_planned": "2019-08-24",
  • "status": "string",
  • "est_primary_ins": "string",
  • "est_secondary_ins": "string",
  • "plan_name": "string",
  • "priority": 2147483647,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_treatment_plan_item_partial_update

Retrieve, update, or delete a treatment plan item.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
item_uid
required
string <uuid>
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
provider
string or null <uuid>
procedure_code
string or null <uuid>
proc_code
string <= 20 characters
description
string <= 255 characters
tooth_num
string <= 10 characters
surface
string <= 20 characters
planned_fee
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
date_planned
string or null <date>
status
string <= 30 characters

planned, completed

plan_name
string <= 255 characters
priority
integer [ 0 .. 2147483647 ]
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "proc_code": "string",
  • "description": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "planned_fee": "string",
  • "date_planned": "2019-08-24",
  • "status": "string",
  • "plan_name": "string",
  • "priority": 2147483647,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "treatment_plan": "c4c01122-8b32-4bce-bbce-bb1bda9a1a32",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "proc_code": "string",
  • "procedure_code_fee": "string",
  • "description": "string",
  • "tooth_num": "string",
  • "surface": "string",
  • "planned_fee": "string",
  • "date_planned": "2019-08-24",
  • "status": "string",
  • "est_primary_ins": "string",
  • "est_secondary_ins": "string",
  • "plan_name": "string",
  • "priority": 2147483647,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_treatment_plan_item_destroy

Retrieve, update, or delete a treatment plan item.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
item_uid
required
string <uuid>
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_clinical_vital_sign_retrieve

Retrieve or update a vital sign reading.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
vital_sign_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "reading_date": "2019-08-24T14:15:22Z",
  • "bp_systolic": 0,
  • "bp_diastolic": 0,
  • "pulse": 0,
  • "respiration": 0,
  • "o2_saturation": 0,
  • "temperature": "string",
  • "note": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_clinical_vital_sign_update

Retrieve or update a vital sign reading.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
vital_sign_uid
required
string <uuid>
Request Body schema:
required
appointment
string or null <uuid>
provider
string or null <uuid>
reading_date
required
string <date-time>

When the vitals were taken

bp_systolic
integer or null [ 0 .. 32767 ]

Systolic blood pressure (mmHg)

bp_diastolic
integer or null [ 0 .. 32767 ]

Diastolic blood pressure (mmHg)

pulse
integer or null [ 0 .. 32767 ]

Pulse rate (bpm)

respiration
integer or null [ 0 .. 32767 ]

Respiration rate (breaths/min)

o2_saturation
integer or null [ 0 .. 32767 ]

Oxygen saturation (%)

temperature
string or null <decimal> ^-?\d{0,3}(?:\.\d{0,1})?$

Temperature (F)

note
string
custom_data
any

Responses

Request samples

Content type
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "reading_date": "2019-08-24T14:15:22Z",
  • "bp_systolic": 32767,
  • "bp_diastolic": 32767,
  • "pulse": 32767,
  • "respiration": 32767,
  • "o2_saturation": 32767,
  • "temperature": "string",
  • "note": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "reading_date": "2019-08-24T14:15:22Z",
  • "bp_systolic": 32767,
  • "bp_diastolic": 32767,
  • "pulse": 32767,
  • "respiration": 32767,
  • "o2_saturation": 32767,
  • "temperature": "string",
  • "note": "string",
  • "custom_data": null
}

practice_patient_clinical_vital_sign_partial_update

Retrieve or update a vital sign reading.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
vital_sign_uid
required
string <uuid>
Request Body schema:
appointment
string or null <uuid>
provider
string or null <uuid>
reading_date
string <date-time>

When the vitals were taken

bp_systolic
integer or null [ 0 .. 32767 ]

Systolic blood pressure (mmHg)

bp_diastolic
integer or null [ 0 .. 32767 ]

Diastolic blood pressure (mmHg)

pulse
integer or null [ 0 .. 32767 ]

Pulse rate (bpm)

respiration
integer or null [ 0 .. 32767 ]

Respiration rate (breaths/min)

o2_saturation
integer or null [ 0 .. 32767 ]

Oxygen saturation (%)

temperature
string or null <decimal> ^-?\d{0,3}(?:\.\d{0,1})?$

Temperature (F)

note
string
custom_data
any

Responses

Request samples

Content type
{
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "reading_date": "2019-08-24T14:15:22Z",
  • "bp_systolic": 32767,
  • "bp_diastolic": 32767,
  • "pulse": 32767,
  • "respiration": 32767,
  • "o2_saturation": 32767,
  • "temperature": "string",
  • "note": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "reading_date": "2019-08-24T14:15:22Z",
  • "bp_systolic": 32767,
  • "bp_diastolic": 32767,
  • "pulse": 32767,
  • "respiration": 32767,
  • "o2_saturation": 32767,
  • "temperature": "string",
  • "note": "string",
  • "custom_data": null
}

practice_patient_comms_commlog_retrieve

Retrieve, update, or delete a communication log entry.

GH-575: every detail GET emits one comms.commlog_viewed audit event carrying is_imported so HIPAA review can filter reads of PHI-bearing historical imports specifically.

TODO(GH-575): when a replicate_of_commlog_id send endpoint is added (e.g. "resend this email" / "use as template"), it MUST 400 when the source row is is_imported=True and emit comms.commlog_resend_blocked to the audit trail. Follow-up issue tracked in escapedental/web (suppress the affordance UI-side) and in api (when the send endpoint actually lands).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
commlog_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "date_time": "2019-08-24T14:15:22Z",
  • "mode": "phone",
  • "direction": "sent",
  • "outcome": "success",
  • "subject": "string",
  • "note": "string",
  • "phi_redacted_note": "string",
  • "staff_user": "17986289-b0ef-402a-92d5-49bc6fa3367e",
  • "recall": "e7ef6ec4-8466-4387-af6a-2ed34de604a8",
  • "is_imported": true,
  • "custom_data": null,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_patient_comms_commlog_update

Retrieve, update, or delete a communication log entry.

GH-575: every detail GET emits one comms.commlog_viewed audit event carrying is_imported so HIPAA review can filter reads of PHI-bearing historical imports specifically.

TODO(GH-575): when a replicate_of_commlog_id send endpoint is added (e.g. "resend this email" / "use as template"), it MUST 400 when the source row is is_imported=True and emit comms.commlog_resend_blocked to the audit trail. Follow-up issue tracked in escapedental/web (suppress the affordance UI-side) and in api (when the send endpoint actually lands).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
commlog_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
date_time
string or null <date-time>
mode
string (ModeEnum)
Enum: "phone" "email" "text" "fax" "mail" "in_person" "web" "other"
  • phone - Phone
  • email - Email
  • text - Text
  • fax - Fax
  • mail - Mail
  • in_person - In Person
  • web - Web
  • other - Other
direction
string (Direction80cEnum)
Enum: "sent" "received" "neither"
  • sent - Sent
  • received - Received
  • neither - Neither
outcome
string
Enum: "success" "no_answer" "voicemail" "bounced" "bad_number" "other"

What happened on the contact attempt. Only success rows count toward the recall-list last_reached_at annotation.

  • success - Success
  • no_answer - No Answer
  • voicemail - Voicemail
  • bounced - Bounced
  • bad_number - Bad Number
  • other - Other
subject
string <= 255 characters

Short label, e.g. 'Recall reminder', 'Treatment plan follow-up'.

note
string
staff_user
string or null <uuid>

Staff member who logged the contact. Null for system-generated entries.

recall
string or null <uuid>

Optional link to the specific recall this contact addresses.

custom_data
any

Responses

Request samples

Content type
{
  • "date_time": "2019-08-24T14:15:22Z",
  • "mode": "phone",
  • "direction": "sent",
  • "outcome": "success",
  • "subject": "string",
  • "note": "string",
  • "staff_user": "17986289-b0ef-402a-92d5-49bc6fa3367e",
  • "recall": "e7ef6ec4-8466-4387-af6a-2ed34de604a8",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "date_time": "2019-08-24T14:15:22Z",
  • "mode": "phone",
  • "direction": "sent",
  • "outcome": "success",
  • "subject": "string",
  • "note": "string",
  • "staff_user": "17986289-b0ef-402a-92d5-49bc6fa3367e",
  • "recall": "e7ef6ec4-8466-4387-af6a-2ed34de604a8",
  • "custom_data": null
}

practice_patient_comms_commlog_partial_update

Retrieve, update, or delete a communication log entry.

GH-575: every detail GET emits one comms.commlog_viewed audit event carrying is_imported so HIPAA review can filter reads of PHI-bearing historical imports specifically.

TODO(GH-575): when a replicate_of_commlog_id send endpoint is added (e.g. "resend this email" / "use as template"), it MUST 400 when the source row is is_imported=True and emit comms.commlog_resend_blocked to the audit trail. Follow-up issue tracked in escapedental/web (suppress the affordance UI-side) and in api (when the send endpoint actually lands).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
commlog_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
date_time
string or null <date-time>
mode
string (ModeEnum)
Enum: "phone" "email" "text" "fax" "mail" "in_person" "web" "other"
  • phone - Phone
  • email - Email
  • text - Text
  • fax - Fax
  • mail - Mail
  • in_person - In Person
  • web - Web
  • other - Other
direction
string (Direction80cEnum)
Enum: "sent" "received" "neither"
  • sent - Sent
  • received - Received
  • neither - Neither
outcome
string
Enum: "success" "no_answer" "voicemail" "bounced" "bad_number" "other"

What happened on the contact attempt. Only success rows count toward the recall-list last_reached_at annotation.

  • success - Success
  • no_answer - No Answer
  • voicemail - Voicemail
  • bounced - Bounced
  • bad_number - Bad Number
  • other - Other
subject
string <= 255 characters

Short label, e.g. 'Recall reminder', 'Treatment plan follow-up'.

note
string
staff_user
string or null <uuid>

Staff member who logged the contact. Null for system-generated entries.

recall
string or null <uuid>

Optional link to the specific recall this contact addresses.

custom_data
any

Responses

Request samples

Content type
{
  • "date_time": "2019-08-24T14:15:22Z",
  • "mode": "phone",
  • "direction": "sent",
  • "outcome": "success",
  • "subject": "string",
  • "note": "string",
  • "staff_user": "17986289-b0ef-402a-92d5-49bc6fa3367e",
  • "recall": "e7ef6ec4-8466-4387-af6a-2ed34de604a8",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "date_time": "2019-08-24T14:15:22Z",
  • "mode": "phone",
  • "direction": "sent",
  • "outcome": "success",
  • "subject": "string",
  • "note": "string",
  • "staff_user": "17986289-b0ef-402a-92d5-49bc6fa3367e",
  • "recall": "e7ef6ec4-8466-4387-af6a-2ed34de604a8",
  • "custom_data": null
}

practice_patient_comms_commlog_destroy

Retrieve, update, or delete a communication log entry.

GH-575: every detail GET emits one comms.commlog_viewed audit event carrying is_imported so HIPAA review can filter reads of PHI-bearing historical imports specifically.

TODO(GH-575): when a replicate_of_commlog_id send endpoint is added (e.g. "resend this email" / "use as template"), it MUST 400 when the source row is is_imported=True and emit comms.commlog_resend_blocked to the audit trail. Follow-up issue tracked in escapedental/web (suppress the affordance UI-side) and in api (when the send endpoint actually lands).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
commlog_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_doccenter_retrieve

Retrieve or update document metadata.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
doc_id
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "category": "86d23d13-9dbb-46f3-82d0-25253c7750c3",
  • "title": "string",
  • "description": "string",
  • "original_filename": "string",
  • "mime_type": "string",
  • "file_size": 0,
  • "page_count": 0,
  • "uploaded_by": "e134ce2c-a199-4e99-9c11-627b70a7ff28",
  • "source_application": 0,
  • "is_deleted": true,
  • "deleted_at": "2019-08-24T14:15:22Z",
  • "deleted_by": "d7d7cfa2-327b-4733-8887-d09252b40b06",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolved_by": "d0d57369-b08b-4db8-8952-8cdeedd9aebc",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "download_url": "string",
  • "patient_name": "string",
  • "category_label": "string",
  • "uploaded_by_name": "string",
  • "caller_id": "string",
  • "processing_state": "pending",
  • "processing_error": "string",
  • "processing_updated_at": "2019-08-24T14:15:22Z",
  • "transcript": "string",
  • "transcript_confidence": "string",
  • "custom_data": null
}

practice_patient_doccenter_update

Retrieve or update document metadata.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
doc_id
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
patient
string or null <uuid>
category
string or null <uuid>
title
required
string [ 1 .. 255 ] characters
description
string
caller_id
string <= 32 characters ^\+\d{1,15}$

E.164 caller-ID for voicemail recordings (e.g. +14155551234). Used by the patient-link suggestion engine downstream of the voicemail-to-text pipeline.

custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "category": "86d23d13-9dbb-46f3-82d0-25253c7750c3",
  • "title": "string",
  • "description": "string",
  • "caller_id": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "category": "86d23d13-9dbb-46f3-82d0-25253c7750c3",
  • "title": "string",
  • "description": "string",
  • "original_filename": "string",
  • "mime_type": "string",
  • "file_size": 0,
  • "page_count": 0,
  • "uploaded_by": "e134ce2c-a199-4e99-9c11-627b70a7ff28",
  • "source_application": 0,
  • "is_deleted": true,
  • "deleted_at": "2019-08-24T14:15:22Z",
  • "deleted_by": "d7d7cfa2-327b-4733-8887-d09252b40b06",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolved_by": "d0d57369-b08b-4db8-8952-8cdeedd9aebc",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "download_url": "string",
  • "patient_name": "string",
  • "category_label": "string",
  • "uploaded_by_name": "string",
  • "caller_id": "string",
  • "processing_state": "pending",
  • "processing_error": "string",
  • "processing_updated_at": "2019-08-24T14:15:22Z",
  • "transcript": "string",
  • "transcript_confidence": "string",
  • "custom_data": null
}

practice_patient_doccenter_partial_update

Retrieve or update document metadata.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
doc_id
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
patient
string or null <uuid>
category
string or null <uuid>
title
string [ 1 .. 255 ] characters
description
string
caller_id
string <= 32 characters ^\+\d{1,15}$

E.164 caller-ID for voicemail recordings (e.g. +14155551234). Used by the patient-link suggestion engine downstream of the voicemail-to-text pipeline.

custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "category": "86d23d13-9dbb-46f3-82d0-25253c7750c3",
  • "title": "string",
  • "description": "string",
  • "caller_id": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "category": "86d23d13-9dbb-46f3-82d0-25253c7750c3",
  • "title": "string",
  • "description": "string",
  • "original_filename": "string",
  • "mime_type": "string",
  • "file_size": 0,
  • "page_count": 0,
  • "uploaded_by": "e134ce2c-a199-4e99-9c11-627b70a7ff28",
  • "source_application": 0,
  • "is_deleted": true,
  • "deleted_at": "2019-08-24T14:15:22Z",
  • "deleted_by": "d7d7cfa2-327b-4733-8887-d09252b40b06",
  • "resolved_at": "2019-08-24T14:15:22Z",
  • "resolved_by": "d0d57369-b08b-4db8-8952-8cdeedd9aebc",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "download_url": "string",
  • "patient_name": "string",
  • "category_label": "string",
  • "uploaded_by_name": "string",
  • "caller_id": "string",
  • "processing_state": "pending",
  • "processing_error": "string",
  • "processing_updated_at": "2019-08-24T14:15:22Z",
  • "transcript": "string",
  • "transcript_confidence": "string",
  • "custom_data": null
}

practice_patient_imaging_exam_list

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_imaging_exam_create

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
template
string or null <uuid>
name
string <= 255 characters

Optional exam name/label

exam_date
required
string <date>
provider
string or null <uuid>
notes
string
is_complete
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "name": "string",
  • "exam_date": "2019-08-24",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "notes": "string",
  • "is_complete": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "template_name": "string",
  • "name": "string",
  • "exam_date": "2019-08-24",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "notes": "string",
  • "is_complete": true,
  • "image_count": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_imaging_exam_retrieve

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
exam_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "template_name": "string",
  • "name": "string",
  • "exam_date": "2019-08-24",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "notes": "string",
  • "is_complete": true,
  • "image_count": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null,
  • "images": [
    ]
}

practice_patient_imaging_exam_update

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
exam_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
template
string or null <uuid>
name
string <= 255 characters

Optional exam name/label

exam_date
required
string <date>
provider
string or null <uuid>
notes
string
is_complete
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "name": "string",
  • "exam_date": "2019-08-24",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "notes": "string",
  • "is_complete": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "template_name": "string",
  • "name": "string",
  • "exam_date": "2019-08-24",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "notes": "string",
  • "is_complete": true,
  • "image_count": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_imaging_exam_partial_update

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
exam_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
template
string or null <uuid>
name
string <= 255 characters

Optional exam name/label

exam_date
string <date>
provider
string or null <uuid>
notes
string
is_complete
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "name": "string",
  • "exam_date": "2019-08-24",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "notes": "string",
  • "is_complete": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "template_name": "string",
  • "name": "string",
  • "exam_date": "2019-08-24",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "notes": "string",
  • "is_complete": true,
  • "image_count": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_imaging_exam_destroy

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
exam_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_imaging_image_list

List images for a patient with filtering and ordering.

Query params: image_type — filter by type (PA, BW, PANO, CEPH, etc.) source — filter by source ID exam — filter by exam ID date_from — capture_date >= (YYYY-MM-DD) date_to — capture_date <= (YYYY-MM-DD) ordering — comma-separated fields: capture_date, created, image_type (prefix with - for descending, default: -capture_date,-created)

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_imaging_image_retrieve

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
image_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "exam": "76d06126-4ce7-4fb4-98c2-d484d7e9ee38",
  • "source": "07b8e003-7027-443f-88b0-24a5eb1cc68b",
  • "source_name": "string",
  • "template_slot": "a8f6b7f7-6b3b-48c7-a4e4-e20bd837e2e6",
  • "original_filename": "string",
  • "mime_type": "string",
  • "file_size": 0,
  • "width": 0,
  • "height": 0,
  • "image_type": "pa",
  • "capture_date": "2019-08-24",
  • "capture_device": "string",
  • "tooth_numbers": null,
  • "description": "string",
  • "degrees_rotated": -2147483648,
  • "is_flipped": true,
  • "display_settings": null,
  • "annotations": null,
  • "notes": "string",
  • "is_deleted": true,
  • "download_url": "string",
  • "thumbnail_url": "string",
  • "uploaded_by": "e134ce2c-a199-4e99-9c11-627b70a7ff28",
  • "deleted_by": "d7d7cfa2-327b-4733-8887-d09252b40b06",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_imaging_image_update

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
image_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
exam
required
string <uuid>
source
string or null <uuid>
template_slot
string or null <uuid>

Which slot in the exam template grid this image fills

original_filename
string <= 255 characters
mime_type
string [ 1 .. 50 ] characters
ImageTypeEnum (string) or BlankEnum (any)
capture_date
required
string <date>
capture_device
string <= 255 characters

Device name from browser getUserMedia

tooth_numbers
any

Universal numbering: 1-32 permanent, A-T primary

description
string <= 255 characters

Short description/label for the image

degrees_rotated
integer [ -2147483648 .. 2147483647 ]

Rotation state: 0, 90, 180, or 270 degrees

is_flipped
boolean

Horizontal flip state

display_settings
any

Viewer display settings: brightness, contrast, inverted, etc.

annotations
any

Array of annotation objects from the viewer

notes
string
custom_data
any

Responses

Request samples

Content type
{
  • "exam": "76d06126-4ce7-4fb4-98c2-d484d7e9ee38",
  • "source": "07b8e003-7027-443f-88b0-24a5eb1cc68b",
  • "template_slot": "a8f6b7f7-6b3b-48c7-a4e4-e20bd837e2e6",
  • "original_filename": "string",
  • "mime_type": "string",
  • "image_type": "pa",
  • "capture_date": "2019-08-24",
  • "capture_device": "string",
  • "tooth_numbers": null,
  • "description": "string",
  • "degrees_rotated": -2147483648,
  • "is_flipped": true,
  • "display_settings": null,
  • "annotations": null,
  • "notes": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "exam": "76d06126-4ce7-4fb4-98c2-d484d7e9ee38",
  • "source": "07b8e003-7027-443f-88b0-24a5eb1cc68b",
  • "source_name": "string",
  • "template_slot": "a8f6b7f7-6b3b-48c7-a4e4-e20bd837e2e6",
  • "original_filename": "string",
  • "mime_type": "string",
  • "file_size": 0,
  • "width": 0,
  • "height": 0,
  • "image_type": "pa",
  • "capture_date": "2019-08-24",
  • "capture_device": "string",
  • "tooth_numbers": null,
  • "description": "string",
  • "degrees_rotated": -2147483648,
  • "is_flipped": true,
  • "display_settings": null,
  • "annotations": null,
  • "notes": "string",
  • "is_deleted": true,
  • "download_url": "string",
  • "thumbnail_url": "string",
  • "uploaded_by": "e134ce2c-a199-4e99-9c11-627b70a7ff28",
  • "deleted_by": "d7d7cfa2-327b-4733-8887-d09252b40b06",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_imaging_image_partial_update

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
image_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
exam
string <uuid>
source
string or null <uuid>
template_slot
string or null <uuid>

Which slot in the exam template grid this image fills

original_filename
string <= 255 characters
mime_type
string [ 1 .. 50 ] characters
ImageTypeEnum (string) or BlankEnum (any)
capture_date
string <date>
capture_device
string <= 255 characters

Device name from browser getUserMedia

tooth_numbers
any

Universal numbering: 1-32 permanent, A-T primary

description
string <= 255 characters

Short description/label for the image

degrees_rotated
integer [ -2147483648 .. 2147483647 ]

Rotation state: 0, 90, 180, or 270 degrees

is_flipped
boolean

Horizontal flip state

display_settings
any

Viewer display settings: brightness, contrast, inverted, etc.

annotations
any

Array of annotation objects from the viewer

notes
string
custom_data
any

Responses

Request samples

Content type
{
  • "exam": "76d06126-4ce7-4fb4-98c2-d484d7e9ee38",
  • "source": "07b8e003-7027-443f-88b0-24a5eb1cc68b",
  • "template_slot": "a8f6b7f7-6b3b-48c7-a4e4-e20bd837e2e6",
  • "original_filename": "string",
  • "mime_type": "string",
  • "image_type": "pa",
  • "capture_date": "2019-08-24",
  • "capture_device": "string",
  • "tooth_numbers": null,
  • "description": "string",
  • "degrees_rotated": -2147483648,
  • "is_flipped": true,
  • "display_settings": null,
  • "annotations": null,
  • "notes": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "exam": "76d06126-4ce7-4fb4-98c2-d484d7e9ee38",
  • "source": "07b8e003-7027-443f-88b0-24a5eb1cc68b",
  • "source_name": "string",
  • "template_slot": "a8f6b7f7-6b3b-48c7-a4e4-e20bd837e2e6",
  • "original_filename": "string",
  • "mime_type": "string",
  • "file_size": 0,
  • "width": 0,
  • "height": 0,
  • "image_type": "pa",
  • "capture_date": "2019-08-24",
  • "capture_device": "string",
  • "tooth_numbers": null,
  • "description": "string",
  • "degrees_rotated": -2147483648,
  • "is_flipped": true,
  • "display_settings": null,
  • "annotations": null,
  • "notes": "string",
  • "is_deleted": true,
  • "download_url": "string",
  • "thumbnail_url": "string",
  • "uploaded_by": "e134ce2c-a199-4e99-9c11-627b70a7ff28",
  • "deleted_by": "d7d7cfa2-327b-4733-8887-d09252b40b06",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_patient_imaging_image_destroy

Resolve practice_uid from the URL and enforce client-level access.

Mixed-in views automatically pick up :class:apps.practices.permissions.PracticeIsActive so writes to descendants of an inactive Client / Practice are blocked with a 403 even if the view overrides permission_classes or get_permissions(). See GH-277 for the cascade-disable rationale.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
image_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_imaging_image_upload_create

Upload a dental image via multipart form data.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
exam
required
string <uuid>
source
string or null <uuid>
template_slot
string or null <uuid>

Which slot in the exam template grid this image fills

file
required
string <binary>
ImageTypeEnum (string) or BlankEnum (any)
capture_date
required
string <date>
capture_device
string <= 255 characters

Device name from browser getUserMedia

tooth_numbers
any

Universal numbering: 1-32 permanent, A-T primary

description
string <= 255 characters

Short description/label for the image

notes
string

Responses

Response samples

Content type
application/json
{
  • "exam": "76d06126-4ce7-4fb4-98c2-d484d7e9ee38",
  • "source": "07b8e003-7027-443f-88b0-24a5eb1cc68b",
  • "template_slot": "a8f6b7f7-6b3b-48c7-a4e4-e20bd837e2e6",
  • "image_type": "pa",
  • "capture_date": "2019-08-24",
  • "capture_device": "string",
  • "tooth_numbers": null,
  • "description": "string",
  • "notes": "string"
}

practice_patient_insurance_claim_log_list

List status change log entries for a specific claim.

GET /practice//patient//insurance/claim//log/

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
claim_id
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_insurance_claim_retrieve

Retrieve a single insurance claim with full details.

GET /practice//patient//insurance/claim//

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
claim_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "custom_data": null,
  • "procedures": [
    ],
  • "status_log": [
    ],
  • "patient_name": "string",
  • "patient_first_name": "string",
  • "patient_last_name": "string",
  • "provider_name": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "date_service": "2019-08-24",
  • "date_sent": "2019-08-24",
  • "status": "draft",
  • "claim_status": "string",
  • "claim_fee": "string",
  • "ins_pay_est": "string",
  • "ins_pay_amt": "string",
  • "ded_applied": "string",
  • "write_off": "string",
  • "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
  • "modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "patient_insurance": "e396a8de-c249-4467-871f-c8b5f28219f1"
}

practice_patient_insurance_claim_update_partial_update

Update an insurance claim. Only draft or imported claims may be edited.

PATCH /practice//patient//insurance/claim//

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
claim_uid
required
string <uuid>
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
provider
string or null <uuid>
patient_insurance
string or null <uuid>
date_service
string or null <date>
date_sent
string or null <date>
claim_fee
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
ins_pay_est
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
ins_pay_amt
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
ded_applied
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
write_off
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
Array of objects (ClaimProcedureWriteRequest)
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "patient_insurance": "e396a8de-c249-4467-871f-c8b5f28219f1",
  • "date_service": "2019-08-24",
  • "date_sent": "2019-08-24",
  • "claim_fee": "string",
  • "ins_pay_est": "string",
  • "ins_pay_amt": "string",
  • "ded_applied": "string",
  • "write_off": "string",
  • "procedures": [
    ],
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "patient_insurance": "e396a8de-c249-4467-871f-c8b5f28219f1",
  • "date_service": "2019-08-24",
  • "date_sent": "2019-08-24",
  • "claim_fee": "string",
  • "ins_pay_est": "string",
  • "ins_pay_amt": "string",
  • "ded_applied": "string",
  • "write_off": "string",
  • "procedures": [
    ],
  • "custom_data": null
}

practice_patient_insurance_plan_benefit_retrieve

Update or delete a benefit.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
benefit_uid
required
string <uuid>
patient_id
required
string <uuid>
plan_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "custom_data": null,
  • "procedure_code": {
    },
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "benefit_type": "percentage",
  • "coverage_category": "diagnostic",
  • "percent": "string",
  • "monetary_amt": "string",
  • "time_period": "calendar_year",
  • "proc_code": "string",
  • "min_age": 32767,
  • "max_age": 32767,
  • "waiting_period_months": 32767,
  • "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
  • "modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "patient_insurance": "e396a8de-c249-4467-871f-c8b5f28219f1"
}

practice_patient_insurance_plan_benefit_update

Update or delete a benefit.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
benefit_uid
required
string <uuid>
patient_id
required
string <uuid>
plan_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
insurance_plan
string or null <uuid>
BenefitTypeEnum (string) or BlankEnum (any)
CoverageCategoryEnum (string) or BlankEnum (any)
percent
string <decimal> ^-?\d{0,3}(?:\.\d{0,2})?$
monetary_amt
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
TimePeriodEnum (string) or BlankEnum (any)
proc_code
string <= 20 characters

Benefit tied to a specific procedure code

procedure_code
string or null <uuid>
min_age
integer or null [ 0 .. 32767 ]

Minimum patient age (inclusive) for this benefit to apply

max_age
integer or null [ 0 .. 32767 ]

Maximum patient age (inclusive) for this benefit to apply

waiting_period_months
integer or null [ 0 .. 32767 ]

Months from effective date before this benefit is available

custom_data
any

Responses

Request samples

Content type
{
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "benefit_type": "percentage",
  • "coverage_category": "diagnostic",
  • "percent": "string",
  • "monetary_amt": "string",
  • "time_period": "calendar_year",
  • "proc_code": "string",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "min_age": 32767,
  • "max_age": 32767,
  • "waiting_period_months": 32767,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "benefit_type": "percentage",
  • "coverage_category": "diagnostic",
  • "percent": "string",
  • "monetary_amt": "string",
  • "time_period": "calendar_year",
  • "proc_code": "string",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "min_age": 32767,
  • "max_age": 32767,
  • "waiting_period_months": 32767,
  • "custom_data": null
}

practice_patient_insurance_plan_benefit_partial_update

Update or delete a benefit.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
benefit_uid
required
string <uuid>
patient_id
required
string <uuid>
plan_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
insurance_plan
string or null <uuid>
BenefitTypeEnum (string) or BlankEnum (any)
CoverageCategoryEnum (string) or BlankEnum (any)
percent
string <decimal> ^-?\d{0,3}(?:\.\d{0,2})?$
monetary_amt
string <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$
TimePeriodEnum (string) or BlankEnum (any)
proc_code
string <= 20 characters

Benefit tied to a specific procedure code

procedure_code
string or null <uuid>
min_age
integer or null [ 0 .. 32767 ]

Minimum patient age (inclusive) for this benefit to apply

max_age
integer or null [ 0 .. 32767 ]

Maximum patient age (inclusive) for this benefit to apply

waiting_period_months
integer or null [ 0 .. 32767 ]

Months from effective date before this benefit is available

custom_data
any

Responses

Request samples

Content type
{
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "benefit_type": "percentage",
  • "coverage_category": "diagnostic",
  • "percent": "string",
  • "monetary_amt": "string",
  • "time_period": "calendar_year",
  • "proc_code": "string",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "min_age": 32767,
  • "max_age": 32767,
  • "waiting_period_months": 32767,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "benefit_type": "percentage",
  • "coverage_category": "diagnostic",
  • "percent": "string",
  • "monetary_amt": "string",
  • "time_period": "calendar_year",
  • "proc_code": "string",
  • "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
  • "min_age": 32767,
  • "max_age": 32767,
  • "waiting_period_months": 32767,
  • "custom_data": null
}

practice_patient_insurance_plan_benefit_destroy

Update or delete a benefit.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
benefit_uid
required
string <uuid>
patient_id
required
string <uuid>
plan_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_insurance_plan_retrieve

Retrieve, update, or delete a patient insurance plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "custom_data": null,
  • "benefits": [
    ],
  • "carrier_detail": {
    },
  • "plan_detail": {
    },
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "carrier_name": "string",
  • "group_number": "string",
  • "subscriber_id": "string",
  • "subscriber_name": "string",
  • "ordinal": 1,
  • "relationship_to_subscriber": "self",
  • "effective_date": "2019-08-24",
  • "termination_date": "2019-08-24",
  • "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
  • "modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5"
}

practice_patient_insurance_plan_update

Retrieve, update, or delete a patient insurance plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
insurance_plan
string or null <uuid>
carrier_name
required
string [ 1 .. 255 ] characters
carrier
string or null <uuid>
fee_schedule
string or null <uuid>

Fee schedule used for benefit estimation under this plan

group_number
string <= 100 characters
subscriber_id
string <= 100 characters
subscriber_name
string <= 255 characters

Policy holder name if different from patient

ordinal
integer [ 0 .. 32767 ]

1=primary, 2=secondary

RelationshipToSubscriberEnum (string) or BlankEnum (any)
effective_date
string or null <date>
termination_date
string or null <date>
custom_data
any

Responses

Request samples

Content type
{
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "carrier_name": "string",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "group_number": "string",
  • "subscriber_id": "string",
  • "subscriber_name": "string",
  • "ordinal": 32767,
  • "relationship_to_subscriber": "self",
  • "effective_date": "2019-08-24",
  • "termination_date": "2019-08-24",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "carrier_name": "string",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "group_number": "string",
  • "subscriber_id": "string",
  • "subscriber_name": "string",
  • "ordinal": 32767,
  • "relationship_to_subscriber": "self",
  • "effective_date": "2019-08-24",
  • "termination_date": "2019-08-24",
  • "custom_data": null
}

practice_patient_insurance_plan_partial_update

Retrieve, update, or delete a patient insurance plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
insurance_plan
string or null <uuid>
carrier_name
string [ 1 .. 255 ] characters
carrier
string or null <uuid>
fee_schedule
string or null <uuid>

Fee schedule used for benefit estimation under this plan

group_number
string <= 100 characters
subscriber_id
string <= 100 characters
subscriber_name
string <= 255 characters

Policy holder name if different from patient

ordinal
integer [ 0 .. 32767 ]

1=primary, 2=secondary

RelationshipToSubscriberEnum (string) or BlankEnum (any)
effective_date
string or null <date>
termination_date
string or null <date>
custom_data
any

Responses

Request samples

Content type
{
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "carrier_name": "string",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "group_number": "string",
  • "subscriber_id": "string",
  • "subscriber_name": "string",
  • "ordinal": 32767,
  • "relationship_to_subscriber": "self",
  • "effective_date": "2019-08-24",
  • "termination_date": "2019-08-24",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "insurance_plan": "b384841f-92bf-462b-afca-b6f7c0177002",
  • "carrier_name": "string",
  • "carrier": "faaa07f8-ed24-4408-95d3-1d7233f61a3e",
  • "fee_schedule": "23e675e4-8697-41ef-9cf8-c46fa2b3e8c5",
  • "group_number": "string",
  • "subscriber_id": "string",
  • "subscriber_name": "string",
  • "ordinal": 32767,
  • "relationship_to_subscriber": "self",
  • "effective_date": "2019-08-24",
  • "termination_date": "2019-08-24",
  • "custom_data": null
}

practice_patient_insurance_plan_destroy

Retrieve, update, or delete a patient insurance plan.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
plan_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_scheduling_recall_list

List recalls for a specific patient (patient-scoped, read-only).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_retrieve

Retrieve or update a single patient. Staff-only.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "first_name": "string",
  • "last_name": "string",
  • "preferred_name": "string",
  • "email": "user@example.com",
  • "date_of_birth": "2019-08-24",
  • "gender": "male",
  • "status": "active",
  • "phone_home": "string",
  • "phone_work": "string",
  • "phone_mobile": "string",
  • "address": "string",
  • "address2": "string",
  • "city": "string",
  • "state": "string",
  • "zip_code": "string",
  • "primary_provider": "be2be9e9-c010-46fe-8c1e-a13cbc4f6d37",
  • "secondary_provider": "777f5dc9-f0f1-403f-9363-1023b8767d88",
  • "last_medical_review": "2019-08-24",
  • "last_medical_review_by": "32e17085-58ec-492b-b21e-23eca3985cd7",
  • "last_medical_review_by_name": "string",
  • "balance_current": "string",
  • "last_recall_date": "2019-08-24",
  • "next_recall_date": "2019-08-24",
  • "prefers_email": true,
  • "prefers_sms": true,
  • "hipaa_consent_signed": true,
  • "hipaa_consent_date": "2019-08-24",
  • "hipaa_authorization_signed": true,
  • "hipaa_authorization_date": "2019-08-24",
  • "hipaa_privacy_practices_signed": true,
  • "hipaa_privacy_practices_date": "2019-08-24",
  • "custom_data": null,
  • "referral_source": "string"
}

practice_patient_update

Retrieve or update a single patient. Staff-only.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
first_name
required
string [ 1 .. 100 ] characters
last_name
required
string [ 1 .. 100 ] characters
preferred_name
string <= 100 characters
email
string <email> <= 254 characters
date_of_birth
string or null <date>
gender
string (GenderEnum)
Enum: "male" "female" "other" "unknown"
  • male - Male
  • female - Female
  • other - Other
  • unknown - Unknown
status
string (PatientStatusEnum)
Enum: "active" "inactive" "archived" "deceased" "prospective"
  • active - Active
  • inactive - Inactive
  • archived - Archived
  • deceased - Deceased
  • prospective - Prospective
phone_home
string or null
phone_work
string or null
phone_mobile
string or null
address
string <= 255 characters
address2
string <= 255 characters
city
string <= 100 characters
state
string <= 50 characters
zip_code
string <= 10 characters ^\d{5}(-\d{4})?$
primary_provider
string or null <uuid>
secondary_provider
string or null <uuid>
balance_current
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Current account balance, denormalized from the ledger for fast list rendering.

last_recall_date
string or null <date>

Most recent recall appointment date from the source PMS

next_recall_date
string or null <date>

Next scheduled recall appointment date from the source PMS

prefers_email
boolean

Patient opts in to email communications (per source PMS)

prefers_sms
boolean

Patient opts in to SMS/text communications (per source PMS)

hipaa_consent_signed
boolean

HIPAA treatment consent signed (per source PMS)

hipaa_consent_date
string or null <date>

Date HIPAA treatment consent was signed

hipaa_authorization_signed
boolean

HIPAA authorization (release of info) signed (per source PMS)

hipaa_authorization_date
string or null <date>

Date HIPAA authorization was signed

hipaa_privacy_practices_signed
boolean

HIPAA notice of privacy practices acknowledged (per source PMS)

hipaa_privacy_practices_date
string or null <date>

Date HIPAA notice of privacy practices was acknowledged

custom_data
any

Responses

Request samples

Content type
{
  • "first_name": "string",
  • "last_name": "string",
  • "preferred_name": "string",
  • "email": "user@example.com",
  • "date_of_birth": "2019-08-24",
  • "gender": "male",
  • "status": "active",
  • "phone_home": "string",
  • "phone_work": "string",
  • "phone_mobile": "string",
  • "address": "string",
  • "address2": "string",
  • "city": "string",
  • "state": "string",
  • "zip_code": "string",
  • "primary_provider": "be2be9e9-c010-46fe-8c1e-a13cbc4f6d37",
  • "secondary_provider": "777f5dc9-f0f1-403f-9363-1023b8767d88",
  • "balance_current": "string",
  • "last_recall_date": "2019-08-24",
  • "next_recall_date": "2019-08-24",
  • "prefers_email": true,
  • "prefers_sms": true,
  • "hipaa_consent_signed": true,
  • "hipaa_consent_date": "2019-08-24",
  • "hipaa_authorization_signed": true,
  • "hipaa_authorization_date": "2019-08-24",
  • "hipaa_privacy_practices_signed": true,
  • "hipaa_privacy_practices_date": "2019-08-24",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "first_name": "string",
  • "last_name": "string",
  • "preferred_name": "string",
  • "email": "user@example.com",
  • "date_of_birth": "2019-08-24",
  • "gender": "male",
  • "status": "active",
  • "phone_home": "string",
  • "phone_work": "string",
  • "phone_mobile": "string",
  • "address": "string",
  • "address2": "string",
  • "city": "string",
  • "state": "string",
  • "zip_code": "string",
  • "primary_provider": "be2be9e9-c010-46fe-8c1e-a13cbc4f6d37",
  • "secondary_provider": "777f5dc9-f0f1-403f-9363-1023b8767d88",
  • "last_medical_review": "2019-08-24",
  • "last_medical_review_by": "32e17085-58ec-492b-b21e-23eca3985cd7",
  • "last_medical_review_by_name": "string",
  • "balance_current": "string",
  • "last_recall_date": "2019-08-24",
  • "next_recall_date": "2019-08-24",
  • "prefers_email": true,
  • "prefers_sms": true,
  • "hipaa_consent_signed": true,
  • "hipaa_consent_date": "2019-08-24",
  • "hipaa_authorization_signed": true,
  • "hipaa_authorization_date": "2019-08-24",
  • "hipaa_privacy_practices_signed": true,
  • "hipaa_privacy_practices_date": "2019-08-24",
  • "custom_data": null,
  • "referral_source": "string"
}

practice_patient_partial_update

Retrieve or update a single patient. Staff-only.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
first_name
string [ 1 .. 100 ] characters
last_name
string [ 1 .. 100 ] characters
preferred_name
string <= 100 characters
email
string <email> <= 254 characters
date_of_birth
string or null <date>
gender
string (GenderEnum)
Enum: "male" "female" "other" "unknown"
  • male - Male
  • female - Female
  • other - Other
  • unknown - Unknown
status
string (PatientStatusEnum)
Enum: "active" "inactive" "archived" "deceased" "prospective"
  • active - Active
  • inactive - Inactive
  • archived - Archived
  • deceased - Deceased
  • prospective - Prospective
phone_home
string or null
phone_work
string or null
phone_mobile
string or null
address
string <= 255 characters
address2
string <= 255 characters
city
string <= 100 characters
state
string <= 50 characters
zip_code
string <= 10 characters ^\d{5}(-\d{4})?$
primary_provider
string or null <uuid>
secondary_provider
string or null <uuid>
balance_current
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Current account balance, denormalized from the ledger for fast list rendering.

last_recall_date
string or null <date>

Most recent recall appointment date from the source PMS

next_recall_date
string or null <date>

Next scheduled recall appointment date from the source PMS

prefers_email
boolean

Patient opts in to email communications (per source PMS)

prefers_sms
boolean

Patient opts in to SMS/text communications (per source PMS)

hipaa_consent_signed
boolean

HIPAA treatment consent signed (per source PMS)

hipaa_consent_date
string or null <date>

Date HIPAA treatment consent was signed

hipaa_authorization_signed
boolean

HIPAA authorization (release of info) signed (per source PMS)

hipaa_authorization_date
string or null <date>

Date HIPAA authorization was signed

hipaa_privacy_practices_signed
boolean

HIPAA notice of privacy practices acknowledged (per source PMS)

hipaa_privacy_practices_date
string or null <date>

Date HIPAA notice of privacy practices was acknowledged

custom_data
any

Responses

Request samples

Content type
{
  • "first_name": "string",
  • "last_name": "string",
  • "preferred_name": "string",
  • "email": "user@example.com",
  • "date_of_birth": "2019-08-24",
  • "gender": "male",
  • "status": "active",
  • "phone_home": "string",
  • "phone_work": "string",
  • "phone_mobile": "string",
  • "address": "string",
  • "address2": "string",
  • "city": "string",
  • "state": "string",
  • "zip_code": "string",
  • "primary_provider": "be2be9e9-c010-46fe-8c1e-a13cbc4f6d37",
  • "secondary_provider": "777f5dc9-f0f1-403f-9363-1023b8767d88",
  • "balance_current": "string",
  • "last_recall_date": "2019-08-24",
  • "next_recall_date": "2019-08-24",
  • "prefers_email": true,
  • "prefers_sms": true,
  • "hipaa_consent_signed": true,
  • "hipaa_consent_date": "2019-08-24",
  • "hipaa_authorization_signed": true,
  • "hipaa_authorization_date": "2019-08-24",
  • "hipaa_privacy_practices_signed": true,
  • "hipaa_privacy_practices_date": "2019-08-24",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "first_name": "string",
  • "last_name": "string",
  • "preferred_name": "string",
  • "email": "user@example.com",
  • "date_of_birth": "2019-08-24",
  • "gender": "male",
  • "status": "active",
  • "phone_home": "string",
  • "phone_work": "string",
  • "phone_mobile": "string",
  • "address": "string",
  • "address2": "string",
  • "city": "string",
  • "state": "string",
  • "zip_code": "string",
  • "primary_provider": "be2be9e9-c010-46fe-8c1e-a13cbc4f6d37",
  • "secondary_provider": "777f5dc9-f0f1-403f-9363-1023b8767d88",
  • "last_medical_review": "2019-08-24",
  • "last_medical_review_by": "32e17085-58ec-492b-b21e-23eca3985cd7",
  • "last_medical_review_by_name": "string",
  • "balance_current": "string",
  • "last_recall_date": "2019-08-24",
  • "next_recall_date": "2019-08-24",
  • "prefers_email": true,
  • "prefers_sms": true,
  • "hipaa_consent_signed": true,
  • "hipaa_consent_date": "2019-08-24",
  • "hipaa_authorization_signed": true,
  • "hipaa_authorization_date": "2019-08-24",
  • "hipaa_privacy_practices_signed": true,
  • "hipaa_privacy_practices_date": "2019-08-24",
  • "custom_data": null,
  • "referral_source": "string"
}

practice_patient_referral_source_list

List and create referral sources for a practice.

Bulk create is supported by POSTing an array.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_referral_source_create

List and create referral sources for a practice.

Bulk create is supported by POSTing an array.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
first_name
string <= 100 characters
last_name
string <= 100 characters
specialty
string <= 100 characters
phone
string <= 20 characters
email
string <email> <= 254 characters
npi
string <= 20 characters
is_doctor
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "first_name": "string",
  • "last_name": "string",
  • "specialty": "string",
  • "phone": "string",
  • "email": "user@example.com",
  • "npi": "string",
  • "is_doctor": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "first_name": "string",
  • "last_name": "string",
  • "specialty": "string",
  • "phone": "string",
  • "email": "user@example.com",
  • "npi": "string",
  • "is_doctor": true,
  • "custom_data": null
}

practice_patient_referral_source_retrieve

Retrieve, update, or delete a referral source.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
referral_source_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "first_name": "string",
  • "last_name": "string",
  • "specialty": "string",
  • "phone": "string",
  • "email": "user@example.com",
  • "npi": "string",
  • "is_doctor": true,
  • "custom_data": null,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_patient_referral_source_update

Retrieve, update, or delete a referral source.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
referral_source_uid
required
string <uuid>
Request Body schema:
first_name
string <= 100 characters
last_name
string <= 100 characters
specialty
string <= 100 characters
phone
string <= 20 characters
email
string <email> <= 254 characters
npi
string <= 20 characters
is_doctor
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "first_name": "string",
  • "last_name": "string",
  • "specialty": "string",
  • "phone": "string",
  • "email": "user@example.com",
  • "npi": "string",
  • "is_doctor": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "first_name": "string",
  • "last_name": "string",
  • "specialty": "string",
  • "phone": "string",
  • "email": "user@example.com",
  • "npi": "string",
  • "is_doctor": true,
  • "custom_data": null
}

practice_patient_referral_source_partial_update

Retrieve, update, or delete a referral source.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
referral_source_uid
required
string <uuid>
Request Body schema:
first_name
string <= 100 characters
last_name
string <= 100 characters
specialty
string <= 100 characters
phone
string <= 20 characters
email
string <email> <= 254 characters
npi
string <= 20 characters
is_doctor
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "first_name": "string",
  • "last_name": "string",
  • "specialty": "string",
  • "phone": "string",
  • "email": "user@example.com",
  • "npi": "string",
  • "is_doctor": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "first_name": "string",
  • "last_name": "string",
  • "specialty": "string",
  • "phone": "string",
  • "email": "user@example.com",
  • "npi": "string",
  • "is_doctor": true,
  • "custom_data": null
}

practice_patient_referral_source_destroy

Retrieve, update, or delete a referral source.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
referral_source_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_provider_retrieve

Retrieve or update a single provider.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
provider_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "first_name": "string",
  • "last_name": "string",
  • "abbreviation": "string",
  • "specialty": "string",
  • "provider_type": "dentist",
  • "color": "string",
  • "npi": "string",
  • "dea_number": "string",
  • "is_hidden": true,
  • "is_secondary": true,
  • "is_active": true,
  • "is_web_sched": true,
  • "custom_data": null
}

practice_provider_update

Retrieve or update a single provider.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
provider_uid
required
string <uuid>
Request Body schema:
required
first_name
required
string [ 1 .. 100 ] characters
last_name
required
string [ 1 .. 100 ] characters
abbreviation
string <= 20 characters
specialty
string <= 100 characters
provider_type
string (ProviderTypeEnum)
Enum: "dentist" "hygienist" "assistant" "other"
  • dentist - Dentist
  • hygienist - Hygienist
  • assistant - Assistant
  • other - Other
color
string <= 7 characters

Hex color for calendar rendering, e.g. #3B82F6

npi
string <= 10 characters

National Provider Identifier

dea_number
string <= 9 characters

DEA registration number (2 letters + 7 digits, e.g. AB1234567). Required on paper controlled-substance prescriptions. Not required for non-controlled prescriptions. Added as part of the prescriptions module (escape#136 / api#482).

is_hidden
boolean

Hidden from dropdowns but visible on historical records

is_secondary
boolean

Legacy import field — use provider_type instead

is_active
boolean

Currently employed at this practice

is_web_sched
boolean

Available for patient online scheduling.

custom_data
any

Responses

Request samples

Content type
{
  • "first_name": "string",
  • "last_name": "string",
  • "abbreviation": "string",
  • "specialty": "string",
  • "provider_type": "dentist",
  • "color": "string",
  • "npi": "string",
  • "dea_number": "string",
  • "is_hidden": true,
  • "is_secondary": true,
  • "is_active": true,
  • "is_web_sched": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "first_name": "string",
  • "last_name": "string",
  • "abbreviation": "string",
  • "specialty": "string",
  • "provider_type": "dentist",
  • "color": "string",
  • "npi": "string",
  • "dea_number": "string",
  • "is_hidden": true,
  • "is_secondary": true,
  • "is_active": true,
  • "is_web_sched": true,
  • "custom_data": null
}

practice_provider_partial_update

Retrieve or update a single provider.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
provider_uid
required
string <uuid>
Request Body schema:
first_name
string [ 1 .. 100 ] characters
last_name
string [ 1 .. 100 ] characters
abbreviation
string <= 20 characters
specialty
string <= 100 characters
provider_type
string (ProviderTypeEnum)
Enum: "dentist" "hygienist" "assistant" "other"
  • dentist - Dentist
  • hygienist - Hygienist
  • assistant - Assistant
  • other - Other
color
string <= 7 characters

Hex color for calendar rendering, e.g. #3B82F6

npi
string <= 10 characters

National Provider Identifier

dea_number
string <= 9 characters

DEA registration number (2 letters + 7 digits, e.g. AB1234567). Required on paper controlled-substance prescriptions. Not required for non-controlled prescriptions. Added as part of the prescriptions module (escape#136 / api#482).

is_hidden
boolean

Hidden from dropdowns but visible on historical records

is_secondary
boolean

Legacy import field — use provider_type instead

is_active
boolean

Currently employed at this practice

is_web_sched
boolean

Available for patient online scheduling.

custom_data
any

Responses

Request samples

Content type
{
  • "first_name": "string",
  • "last_name": "string",
  • "abbreviation": "string",
  • "specialty": "string",
  • "provider_type": "dentist",
  • "color": "string",
  • "npi": "string",
  • "dea_number": "string",
  • "is_hidden": true,
  • "is_secondary": true,
  • "is_active": true,
  • "is_web_sched": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "first_name": "string",
  • "last_name": "string",
  • "abbreviation": "string",
  • "specialty": "string",
  • "provider_type": "dentist",
  • "color": "string",
  • "npi": "string",
  • "dea_number": "string",
  • "is_hidden": true,
  • "is_secondary": true,
  • "is_active": true,
  • "is_web_sched": true,
  • "custom_data": null
}

practice_provider_operatory_retrieve

Retrieve, update, or delete a single operatory.

Delete is an admin-rare path — the web app prefers a soft-hide (is_hidden=True + is_bookable=False) so historical appointments keep their operatory context. When an admin does choose to delete, we let the FK's CASCADE clean up dependents (schedule templates, legacy appointment rows, etc.) and emit an operatory.deleted audit event.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
operatory_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "abbreviation": "string",
  • "provider_dentist": "e47c6d02-29ee-4cef-ae75-7c7efebcc8cb",
  • "provider_dentist_name": "string",
  • "provider_hygienist": "cc1b609c-8966-4136-9bf1-9a022231718a",
  • "provider_hygienist_name": "string",
  • "is_hygiene": true,
  • "is_hidden": true,
  • "is_bookable": true,
  • "sort_order": 2147483647,
  • "is_web_sched": true,
  • "custom_data": null
}

practice_provider_operatory_update

Retrieve, update, or delete a single operatory.

Delete is an admin-rare path — the web app prefers a soft-hide (is_hidden=True + is_bookable=False) so historical appointments keep their operatory context. When an admin does choose to delete, we let the FK's CASCADE clean up dependents (schedule templates, legacy appointment rows, etc.) and emit an operatory.deleted audit event.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
operatory_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 100 ] characters
abbreviation
string <= 20 characters
provider_dentist
string or null <uuid>

Default dentist assigned to this chair

provider_hygienist
string or null <uuid>

Default hygienist assigned to this chair

is_hygiene
boolean
is_hidden
boolean
is_bookable
boolean

Operatories where is_bookable=False are skipped by the slot-finder. Used for PMS 'overflow' or 'notes-only' pseudo-chairs that host free-text annotations but aren't real rooms.

sort_order
integer [ 0 .. 2147483647 ]

Display ordering in schedule views

is_web_sched
boolean

Available for patient online scheduling

custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "abbreviation": "string",
  • "provider_dentist": "e47c6d02-29ee-4cef-ae75-7c7efebcc8cb",
  • "provider_hygienist": "cc1b609c-8966-4136-9bf1-9a022231718a",
  • "is_hygiene": true,
  • "is_hidden": true,
  • "is_bookable": true,
  • "sort_order": 2147483647,
  • "is_web_sched": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "abbreviation": "string",
  • "provider_dentist": "e47c6d02-29ee-4cef-ae75-7c7efebcc8cb",
  • "provider_dentist_name": "string",
  • "provider_hygienist": "cc1b609c-8966-4136-9bf1-9a022231718a",
  • "provider_hygienist_name": "string",
  • "is_hygiene": true,
  • "is_hidden": true,
  • "is_bookable": true,
  • "sort_order": 2147483647,
  • "is_web_sched": true,
  • "custom_data": null
}

practice_provider_operatory_partial_update

Retrieve, update, or delete a single operatory.

Delete is an admin-rare path — the web app prefers a soft-hide (is_hidden=True + is_bookable=False) so historical appointments keep their operatory context. When an admin does choose to delete, we let the FK's CASCADE clean up dependents (schedule templates, legacy appointment rows, etc.) and emit an operatory.deleted audit event.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
operatory_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
name
string [ 1 .. 100 ] characters
abbreviation
string <= 20 characters
provider_dentist
string or null <uuid>

Default dentist assigned to this chair

provider_hygienist
string or null <uuid>

Default hygienist assigned to this chair

is_hygiene
boolean
is_hidden
boolean
is_bookable
boolean

Operatories where is_bookable=False are skipped by the slot-finder. Used for PMS 'overflow' or 'notes-only' pseudo-chairs that host free-text annotations but aren't real rooms.

sort_order
integer [ 0 .. 2147483647 ]

Display ordering in schedule views

is_web_sched
boolean

Available for patient online scheduling

custom_data
any

Responses

Request samples

Content type
{
  • "name": "string",
  • "abbreviation": "string",
  • "provider_dentist": "e47c6d02-29ee-4cef-ae75-7c7efebcc8cb",
  • "provider_hygienist": "cc1b609c-8966-4136-9bf1-9a022231718a",
  • "is_hygiene": true,
  • "is_hidden": true,
  • "is_bookable": true,
  • "sort_order": 2147483647,
  • "is_web_sched": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "abbreviation": "string",
  • "provider_dentist": "e47c6d02-29ee-4cef-ae75-7c7efebcc8cb",
  • "provider_dentist_name": "string",
  • "provider_hygienist": "cc1b609c-8966-4136-9bf1-9a022231718a",
  • "provider_hygienist_name": "string",
  • "is_hygiene": true,
  • "is_hidden": true,
  • "is_bookable": true,
  • "sort_order": 2147483647,
  • "is_web_sched": true,
  • "custom_data": null
}

practice_provider_operatory_destroy

Retrieve, update, or delete a single operatory.

Delete is an admin-rare path — the web app prefers a soft-hide (is_hidden=True + is_bookable=False) so historical appointments keep their operatory context. When an admin does choose to delete, we let the FK's CASCADE clean up dependents (schedule templates, legacy appointment rows, etc.) and emit an operatory.deleted audit event.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
operatory_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_scheduling_appointment_retrieve

Retrieve or update a single appointment. Status changes must go through /transition/.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
appointment_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_hygienist": "cc1b609c-8966-4136-9bf1-9a022231718a",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "treatment_plan": "c4c01122-8b32-4bce-bbce-bb1bda9a1a32",
  • "date_time": "2019-08-24T14:15:22Z",
  • "duration_minutes": 2147483647,
  • "status": "scheduled",
  • "confirmed_status": "not_called",
  • "appointment_type": "string",
  • "is_hygiene": true,
  • "is_new_patient": true,
  • "procedure_description": "string",
  • "note": "string",
  • "cancellation_reason": "string",
  • "reschedule_requested": true,
  • "arrived_at": "2019-08-24T14:15:22Z",
  • "seated_at": "2019-08-24T14:15:22Z",
  • "ready_for_doctor_at": "2019-08-24T14:15:22Z",
  • "ready_for_walkout_at": "2019-08-24T14:15:22Z",
  • "dismissed_at": "2019-08-24T14:15:22Z",
  • "dollars_scheduled": "string",
  • "patient_name": "string",
  • "provider_name": "string",
  • "provider_hygienist_name": "string",
  • "cancelled_by": "string",
  • "cancelled_by_name": "string",
  • "scheduled_procedures": [
    ],
  • "custom_data": null
}

practice_scheduling_appointment_update

Retrieve or update a single appointment. Status changes must go through /transition/.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
appointment_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
patient
string or null <uuid>
provider
string or null <uuid>
provider_hygienist
string or null <uuid>
operatory
string or null <uuid>
treatment_plan
string or null <uuid>

Treatment plan this appointment was scheduled from

date_time
string or null <date-time>
duration_minutes
integer [ 0 .. 2147483647 ]
ConfirmedStatusEnum (string) or BlankEnum (any)
appointment_type
string <= 100 characters

e.g. New Patient Exam, Crown Prep

is_hygiene
boolean
is_new_patient
boolean
procedure_description
string
note
string
cancellation_reason
string

Patient-supplied reason for cancellation

reschedule_requested
boolean

Patient asked the front desk to reschedule

arrived_at
string or null <date-time>
seated_at
string or null <date-time>
ready_for_doctor_at
string or null <date-time>

When hygienist signaled ready for doctor exam

ready_for_walkout_at
string or null <date-time>

When patient is ready for walkout (checkout/scheduling)

dismissed_at
string or null <date-time>
dollars_scheduled
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Scheduled procedure total from the source PMS; nullable when unknown

Array of objects (AppointmentProcedureRequest)
custom_data
any
allow_overbooking
boolean
Default: false
skip_validation
boolean
Default: false

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_hygienist": "cc1b609c-8966-4136-9bf1-9a022231718a",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "treatment_plan": "c4c01122-8b32-4bce-bbce-bb1bda9a1a32",
  • "date_time": "2019-08-24T14:15:22Z",
  • "duration_minutes": 2147483647,
  • "confirmed_status": "not_called",
  • "appointment_type": "string",
  • "is_hygiene": true,
  • "is_new_patient": true,
  • "procedure_description": "string",
  • "note": "string",
  • "cancellation_reason": "string",
  • "reschedule_requested": true,
  • "arrived_at": "2019-08-24T14:15:22Z",
  • "seated_at": "2019-08-24T14:15:22Z",
  • "ready_for_doctor_at": "2019-08-24T14:15:22Z",
  • "ready_for_walkout_at": "2019-08-24T14:15:22Z",
  • "dismissed_at": "2019-08-24T14:15:22Z",
  • "dollars_scheduled": "string",
  • "scheduled_procedures": [
    ],
  • "custom_data": null,
  • "allow_overbooking": false,
  • "skip_validation": false
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_hygienist": "cc1b609c-8966-4136-9bf1-9a022231718a",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "treatment_plan": "c4c01122-8b32-4bce-bbce-bb1bda9a1a32",
  • "date_time": "2019-08-24T14:15:22Z",
  • "duration_minutes": 2147483647,
  • "status": "scheduled",
  • "confirmed_status": "not_called",
  • "appointment_type": "string",
  • "is_hygiene": true,
  • "is_new_patient": true,
  • "procedure_description": "string",
  • "note": "string",
  • "cancellation_reason": "string",
  • "reschedule_requested": true,
  • "arrived_at": "2019-08-24T14:15:22Z",
  • "seated_at": "2019-08-24T14:15:22Z",
  • "ready_for_doctor_at": "2019-08-24T14:15:22Z",
  • "ready_for_walkout_at": "2019-08-24T14:15:22Z",
  • "dismissed_at": "2019-08-24T14:15:22Z",
  • "dollars_scheduled": "string",
  • "patient_name": "string",
  • "provider_name": "string",
  • "provider_hygienist_name": "string",
  • "cancelled_by": "string",
  • "cancelled_by_name": "string",
  • "scheduled_procedures": [
    ],
  • "custom_data": null,
  • "allow_overbooking": false,
  • "skip_validation": false
}

practice_scheduling_appointment_partial_update

Retrieve or update a single appointment. Status changes must go through /transition/.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
appointment_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
patient
string or null <uuid>
provider
string or null <uuid>
provider_hygienist
string or null <uuid>
operatory
string or null <uuid>
treatment_plan
string or null <uuid>

Treatment plan this appointment was scheduled from

date_time
string or null <date-time>
duration_minutes
integer [ 0 .. 2147483647 ]
ConfirmedStatusEnum (string) or BlankEnum (any)
appointment_type
string <= 100 characters

e.g. New Patient Exam, Crown Prep

is_hygiene
boolean
is_new_patient
boolean
procedure_description
string
note
string
cancellation_reason
string

Patient-supplied reason for cancellation

reschedule_requested
boolean

Patient asked the front desk to reschedule

arrived_at
string or null <date-time>
seated_at
string or null <date-time>
ready_for_doctor_at
string or null <date-time>

When hygienist signaled ready for doctor exam

ready_for_walkout_at
string or null <date-time>

When patient is ready for walkout (checkout/scheduling)

dismissed_at
string or null <date-time>
dollars_scheduled
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Scheduled procedure total from the source PMS; nullable when unknown

Array of objects (AppointmentProcedureRequest)
custom_data
any
allow_overbooking
boolean
Default: false
skip_validation
boolean
Default: false

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_hygienist": "cc1b609c-8966-4136-9bf1-9a022231718a",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "treatment_plan": "c4c01122-8b32-4bce-bbce-bb1bda9a1a32",
  • "date_time": "2019-08-24T14:15:22Z",
  • "duration_minutes": 2147483647,
  • "confirmed_status": "not_called",
  • "appointment_type": "string",
  • "is_hygiene": true,
  • "is_new_patient": true,
  • "procedure_description": "string",
  • "note": "string",
  • "cancellation_reason": "string",
  • "reschedule_requested": true,
  • "arrived_at": "2019-08-24T14:15:22Z",
  • "seated_at": "2019-08-24T14:15:22Z",
  • "ready_for_doctor_at": "2019-08-24T14:15:22Z",
  • "ready_for_walkout_at": "2019-08-24T14:15:22Z",
  • "dismissed_at": "2019-08-24T14:15:22Z",
  • "dollars_scheduled": "string",
  • "scheduled_procedures": [
    ],
  • "custom_data": null,
  • "allow_overbooking": false,
  • "skip_validation": false
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_hygienist": "cc1b609c-8966-4136-9bf1-9a022231718a",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "treatment_plan": "c4c01122-8b32-4bce-bbce-bb1bda9a1a32",
  • "date_time": "2019-08-24T14:15:22Z",
  • "duration_minutes": 2147483647,
  • "status": "scheduled",
  • "confirmed_status": "not_called",
  • "appointment_type": "string",
  • "is_hygiene": true,
  • "is_new_patient": true,
  • "procedure_description": "string",
  • "note": "string",
  • "cancellation_reason": "string",
  • "reschedule_requested": true,
  • "arrived_at": "2019-08-24T14:15:22Z",
  • "seated_at": "2019-08-24T14:15:22Z",
  • "ready_for_doctor_at": "2019-08-24T14:15:22Z",
  • "ready_for_walkout_at": "2019-08-24T14:15:22Z",
  • "dismissed_at": "2019-08-24T14:15:22Z",
  • "dollars_scheduled": "string",
  • "patient_name": "string",
  • "provider_name": "string",
  • "provider_hygienist_name": "string",
  • "cancelled_by": "string",
  • "cancelled_by_name": "string",
  • "scheduled_procedures": [
    ],
  • "custom_data": null,
  • "allow_overbooking": false,
  • "skip_validation": false
}

practice_scheduling_recall_retrieve

Retrieve, update, or delete a single recall record.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
recall_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "patient_name": "string",
  • "prefers_sms": true,
  • "prefers_email": true,
  • "recall_type": "string",
  • "date_due": "2019-08-24",
  • "date_previous": "2019-08-24",
  • "date_scheduled": "2019-08-24",
  • "last_visit_date": "2019-08-24",
  • "has_future_appointment": true,
  • "last_reached_at": "2019-08-24T14:15:22Z",
  • "is_disabled": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

practice_scheduling_recall_update

Retrieve, update, or delete a single recall record.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
recall_uid
required
string <uuid>
Request Body schema:
required
patient
string <uuid>
recall_type
required
string [ 1 .. 100 ] characters
date_due
string or null <date>
date_previous
string or null <date>
date_scheduled
string or null <date>
is_disabled
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "recall_type": "string",
  • "date_due": "2019-08-24",
  • "date_previous": "2019-08-24",
  • "date_scheduled": "2019-08-24",
  • "is_disabled": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "recall_type": "string",
  • "date_due": "2019-08-24",
  • "date_previous": "2019-08-24",
  • "date_scheduled": "2019-08-24",
  • "is_disabled": true,
  • "custom_data": null
}

practice_scheduling_recall_partial_update

Retrieve, update, or delete a single recall record.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
recall_uid
required
string <uuid>
Request Body schema:
patient
string <uuid>
recall_type
string [ 1 .. 100 ] characters
date_due
string or null <date>
date_previous
string or null <date>
date_scheduled
string or null <date>
is_disabled
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "recall_type": "string",
  • "date_due": "2019-08-24",
  • "date_previous": "2019-08-24",
  • "date_scheduled": "2019-08-24",
  • "is_disabled": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "recall_type": "string",
  • "date_due": "2019-08-24",
  • "date_previous": "2019-08-24",
  • "date_scheduled": "2019-08-24",
  • "is_disabled": true,
  • "custom_data": null
}

practice_scheduling_recall_destroy

Retrieve, update, or delete a single recall record.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
recall_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_scheduling_schedule_override_retrieve

Retrieve, update, or delete a schedule override.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
override_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "schedule_date": "2019-08-24",
  • "start_time": "14:15:22Z",
  • "end_time": "14:15:22Z",
  • "schedule_type": "office_hours",
  • "blockout_type": "string",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "status": "open",
  • "note": "string",
  • "custom_data": null
}

practice_scheduling_schedule_override_update

Retrieve, update, or delete a schedule override.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
override_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
provider
string or null <uuid>
schedule_date
required
string <date>
start_time
required
string <time>
end_time
required
string <time>
schedule_type
required
string (ScheduleTypeEnum)
Enum: "office_hours" "provider" "blockout"
  • office_hours - Office Hours
  • provider - Provider Availability
  • blockout - Blockout
blockout_type
string <= 50 characters

e.g. lunch, meeting, holiday, time_off

operatory
string or null <uuid>
status
string (ScheduleOverrideStatusEnum)
Enum: "open" "closed" "holiday"
  • open - Open
  • closed - Closed
  • holiday - Holiday
note
string
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "schedule_date": "2019-08-24",
  • "start_time": "14:15:22Z",
  • "end_time": "14:15:22Z",
  • "schedule_type": "office_hours",
  • "blockout_type": "string",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "status": "open",
  • "note": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "schedule_date": "2019-08-24",
  • "start_time": "14:15:22Z",
  • "end_time": "14:15:22Z",
  • "schedule_type": "office_hours",
  • "blockout_type": "string",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "status": "open",
  • "note": "string",
  • "custom_data": null
}

practice_scheduling_schedule_override_partial_update

Retrieve, update, or delete a schedule override.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
override_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
provider
string or null <uuid>
schedule_date
string <date>
start_time
string <time>
end_time
string <time>
schedule_type
string (ScheduleTypeEnum)
Enum: "office_hours" "provider" "blockout"
  • office_hours - Office Hours
  • provider - Provider Availability
  • blockout - Blockout
blockout_type
string <= 50 characters

e.g. lunch, meeting, holiday, time_off

operatory
string or null <uuid>
status
string (ScheduleOverrideStatusEnum)
Enum: "open" "closed" "holiday"
  • open - Open
  • closed - Closed
  • holiday - Holiday
note
string
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "schedule_date": "2019-08-24",
  • "start_time": "14:15:22Z",
  • "end_time": "14:15:22Z",
  • "schedule_type": "office_hours",
  • "blockout_type": "string",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "status": "open",
  • "note": "string",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "schedule_date": "2019-08-24",
  • "start_time": "14:15:22Z",
  • "end_time": "14:15:22Z",
  • "schedule_type": "office_hours",
  • "blockout_type": "string",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "status": "open",
  • "note": "string",
  • "custom_data": null
}

practice_scheduling_schedule_override_destroy

Retrieve, update, or delete a schedule override.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
override_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_scheduling_schedule_template_retrieve

Retrieve, update, or delete a schedule template.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "day_of_week": -2147483648,
  • "start_time": "14:15:22Z",
  • "end_time": "14:15:22Z",
  • "schedule_type": "office_hours",
  • "blockout_type": "string",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "is_active": true,
  • "custom_data": null
}

practice_scheduling_schedule_template_update

Retrieve, update, or delete a schedule template.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_uid
required
string <uuid>
Request Body schema:
required
provider
string or null <uuid>
day_of_week
required
integer [ -2147483648 .. 2147483647 ]

0=Sunday, 1=Monday, ..., 6=Saturday

start_time
required
string <time>
end_time
required
string <time>
schedule_type
required
string (ScheduleTypeEnum)
Enum: "office_hours" "provider" "blockout"
  • office_hours - Office Hours
  • provider - Provider Availability
  • blockout - Blockout
blockout_type
string <= 50 characters

e.g. lunch, meeting, admin

operatory
string or null <uuid>
is_active
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "day_of_week": -2147483648,
  • "start_time": "14:15:22Z",
  • "end_time": "14:15:22Z",
  • "schedule_type": "office_hours",
  • "blockout_type": "string",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "is_active": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "day_of_week": -2147483648,
  • "start_time": "14:15:22Z",
  • "end_time": "14:15:22Z",
  • "schedule_type": "office_hours",
  • "blockout_type": "string",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "is_active": true,
  • "custom_data": null
}

practice_scheduling_schedule_template_partial_update

Retrieve, update, or delete a schedule template.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_uid
required
string <uuid>
Request Body schema:
provider
string or null <uuid>
day_of_week
integer [ -2147483648 .. 2147483647 ]

0=Sunday, 1=Monday, ..., 6=Saturday

start_time
string <time>
end_time
string <time>
schedule_type
string (ScheduleTypeEnum)
Enum: "office_hours" "provider" "blockout"
  • office_hours - Office Hours
  • provider - Provider Availability
  • blockout - Blockout
blockout_type
string <= 50 characters

e.g. lunch, meeting, admin

operatory
string or null <uuid>
is_active
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "day_of_week": -2147483648,
  • "start_time": "14:15:22Z",
  • "end_time": "14:15:22Z",
  • "schedule_type": "office_hours",
  • "blockout_type": "string",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "is_active": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "day_of_week": -2147483648,
  • "start_time": "14:15:22Z",
  • "end_time": "14:15:22Z",
  • "schedule_type": "office_hours",
  • "blockout_type": "string",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "is_active": true,
  • "custom_data": null
}

practice_scheduling_schedule_template_destroy

Retrieve, update, or delete a schedule template.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_share_list

Create / list shares scoped to the URL's practice.

  • GET -- paginated list for the My Shares UI. Supports ?status=, ?patient=, ?created_from= / ?created_to=, ?recipient_kind= (repeatable, ORs within the param), and ?mine_only=true filters. Ordered by -created (newest first).
  • POST -- mint a new share. The response is the ONLY place the caller ever sees the plaintext token / phrase / URL / QR. The model persists only hashes.
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_share_create

Create / list shares scoped to the URL's practice.

  • GET -- paginated list for the My Shares UI. Supports ?status=, ?patient=, ?created_from= / ?created_to=, ?recipient_kind= (repeatable, ORs within the param), and ?mine_only=true filters. Ordered by -created (newest first).
  • POST -- mint a new share. The response is the ONLY place the caller ever sees the plaintext token / phrase / URL / QR. The model persists only hashes.
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
patient_uid
required
string <uuid>
required
Array of objects (ShareItemInputRequest)
recipient_kind
required
string (RecipientKindEnum)
Enum: "escape_practice" "non_escape_treating" "non_treating_party" "patient"
  • escape_practice - Another Escape practice
  • non_escape_treating - Non-Escape treating practice
  • non_treating_party - Non-treating party (legal / employer / other)
  • patient - The patient themselves
recipient_label
string <= 255 characters
Default: ""
purpose
required
string [ 1 .. 2000 ] characters

Responses

Request samples

Content type
{
  • "patient_uid": "2e193f60-014a-4901-af70-2d4676096d5e",
  • "items": [
    ],
  • "recipient_kind": "escape_practice",
  • "recipient_label": "",
  • "purpose": "string"
}

Response samples

Content type
application/json
{
  • "patient_uid": "2e193f60-014a-4901-af70-2d4676096d5e",
  • "items": [
    ],
  • "recipient_kind": "escape_practice",
  • "recipient_label": "",
  • "purpose": "string"
}

practice_share_retrieve

Detail view for the My Shares audit side panel.

Reads are read-only; mutations go through the revoke endpoint. The response echoes resolved :class:ShareItem rows alongside the share fields and the embedded events timeline (api#240) so the UI can render the audit trail without a second fetch.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
share_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "share_uid": "ffaf6965-dd9b-4b11-95e4-338ab6dcedb9",
  • "patient_uid": "2e193f60-014a-4901-af70-2d4676096d5e",
  • "status": "string",
  • "recipient_kind": "string",
  • "recipient_label": "string",
  • "purpose": "string",
  • "token_preview": "string",
  • "created_at": "2019-08-24T14:15:22Z",
  • "first_viewed_at": "2019-08-24T14:15:22Z",
  • "download_count": 0,
  • "expires_at_unviewed": "2019-08-24T14:15:22Z",
  • "expires_at_post_view": "2019-08-24T14:15:22Z",
  • "revoked_at": "2019-08-24T14:15:22Z",
  • "revoke_reason": "string",
  • "created_by": {
    },
  • "items": [
    ],
  • "events": [
    ]
}

practice_share_revoke_create

Revoke a share -- stop-future-access, not recall.

Idempotent: revoking an already-revoked share returns 200 with the (unchanged) share detail so the client can retry safely. Emits a share.revoked audit event on every call, so auditors can see repeated revocation attempts (which should never happen in practice but which we log regardless).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
share_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_sms_messages_retrieve

Retrieve a single SMS row.

Read-only -- there's no legitimate reason to PATCH a message row in place. Status changes flow through the (future) Sinch DLR webhook handler, not the user-facing API.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
message_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "direction": "inbound",
  • "from_number": "string",
  • "to_number": "string",
  • "body": "string",
  • "sinch_message_id": "string",
  • "status": "queued",
  • "error_message": "string",
  • "phi_blocked": true,
  • "sent_at": "2019-08-24T14:15:22Z",
  • "delivered_at": "2019-08-24T14:15:22Z",
  • "received_at": "2019-08-24T14:15:22Z",
  • "sent_by": "40cc1a1c-5bda-4c73-bb08-df4a7613e4ee",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_staff_members_retrieve

Retrieve or update a single practice membership.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
member_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
  • "email": "string",
  • "first_name": "string",
  • "last_name": "string",
  • "role": "ADMIN",
  • "is_active": true,
  • "date_joined": "string",
  • "invited_by_name": "string",
  • "via_practice": "string",
  • "via_client": "string"
}

practice_staff_members_update

Retrieve or update a single practice membership.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
member_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
role
required
string (MemberRoleEnum)
Enum: "ADMIN" "OFFICE_MANAGER" "DENTIST" "HYGIENIST" "FRONT_DESK" "BILLING" "READ_ONLY" "IT_SUPPORT"
  • ADMIN - Administrator
  • OFFICE_MANAGER - Office Manager
  • DENTIST - Dentist
  • HYGIENIST - Hygienist
  • FRONT_DESK - Front Desk
  • BILLING - Billing
  • READ_ONLY - Read Only
  • IT_SUPPORT - IT Support
is_active
boolean

Responses

Request samples

Content type
{
  • "role": "ADMIN",
  • "is_active": true
}

Response samples

Content type
application/json
{
  • "role": "ADMIN",
  • "is_active": true
}

practice_staff_members_partial_update

Retrieve or update a single practice membership.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
member_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
role
string (MemberRoleEnum)
Enum: "ADMIN" "OFFICE_MANAGER" "DENTIST" "HYGIENIST" "FRONT_DESK" "BILLING" "READ_ONLY" "IT_SUPPORT"
  • ADMIN - Administrator
  • OFFICE_MANAGER - Office Manager
  • DENTIST - Dentist
  • HYGIENIST - Hygienist
  • FRONT_DESK - Front Desk
  • BILLING - Billing
  • READ_ONLY - Read Only
  • IT_SUPPORT - IT Support
is_active
boolean

Responses

Request samples

Content type
{
  • "role": "ADMIN",
  • "is_active": true
}

Response samples

Content type
application/json
{
  • "role": "ADMIN",
  • "is_active": true
}

practice_available_list

List practices the current user can upload to.

Returns all active practices belonging to the user's client. Staff-only: patient users should not list practices.

Authorizations:
jwtAuthbearerAuthoauth2

Responses

Response samples

Content type
application/json
[
  • {
    }
]

practice_mine_retrieve

Retrieve or update the user's default practice (first practice under their client).

Authorizations:
jwtAuthbearerAuthoauth2

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "client_name": "string",
  • "name": "string",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "phone": "string",
  • "timezone": "string",
  • "settings": null,
  • "production_goal_daily": "string",
  • "production_goal_weekly": "string",
  • "production_goal_monthly": "string",
  • "is_active": true,
  • "logo_url": "string",
  • "client_logo_url": "string",
  • "effective_logo_url": "string",
  • "client_accent_color": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null,
  • "active_banners": "string",
  • "inbound_document_email": "string"
}

practice_mine_update

Retrieve or update the user's default practice (first practice under their client).

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
required
client
string or null <uuid>
name
required
string [ 1 .. 255 ] characters
address_line1
string <= 255 characters
address_line2
string <= 255 characters
city
string <= 100 characters
state
string <= 2 characters
zip_code
string <= 10 characters ^\d{5}(-\d{4})?$
phone
string <= 128 characters
timezone
string [ 1 .. 50 ] characters
settings
any

Practice-specific configuration.

production_goal_daily
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Daily production goal in USD. Null = no goal set.

production_goal_weekly
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Weekly production goal in USD. Null = no goal set.

production_goal_monthly
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Monthly production goal in USD. Null = no goal set.

is_active
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "name": "string",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "phone": "string",
  • "timezone": "string",
  • "settings": null,
  • "production_goal_daily": "string",
  • "production_goal_weekly": "string",
  • "production_goal_monthly": "string",
  • "is_active": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "client_name": "string",
  • "name": "string",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "phone": "string",
  • "timezone": "string",
  • "settings": null,
  • "production_goal_daily": "string",
  • "production_goal_weekly": "string",
  • "production_goal_monthly": "string",
  • "is_active": true,
  • "logo_url": "string",
  • "client_logo_url": "string",
  • "effective_logo_url": "string",
  • "client_accent_color": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null,
  • "active_banners": "string",
  • "inbound_document_email": "string"
}

practice_mine_partial_update

Retrieve or update the user's default practice (first practice under their client).

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
client
string or null <uuid>
name
string [ 1 .. 255 ] characters
address_line1
string <= 255 characters
address_line2
string <= 255 characters
city
string <= 100 characters
state
string <= 2 characters
zip_code
string <= 10 characters ^\d{5}(-\d{4})?$
phone
string <= 128 characters
timezone
string [ 1 .. 50 ] characters
settings
any

Practice-specific configuration.

production_goal_daily
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Daily production goal in USD. Null = no goal set.

production_goal_weekly
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Weekly production goal in USD. Null = no goal set.

production_goal_monthly
string or null <decimal> ^-?\d{0,8}(?:\.\d{0,2})?$

Monthly production goal in USD. Null = no goal set.

is_active
boolean
custom_data
any

Responses

Request samples

Content type
{
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "name": "string",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "phone": "string",
  • "timezone": "string",
  • "settings": null,
  • "production_goal_daily": "string",
  • "production_goal_weekly": "string",
  • "production_goal_monthly": "string",
  • "is_active": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "client_name": "string",
  • "name": "string",
  • "address_line1": "string",
  • "address_line2": "string",
  • "city": "string",
  • "state": "st",
  • "zip_code": "string",
  • "phone": "string",
  • "timezone": "string",
  • "settings": null,
  • "production_goal_daily": "string",
  • "production_goal_weekly": "string",
  • "production_goal_monthly": "string",
  • "is_active": true,
  • "logo_url": "string",
  • "client_logo_url": "string",
  • "effective_logo_url": "string",
  • "client_accent_color": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null,
  • "active_banners": "string",
  • "inbound_document_email": "string"
}

OAuth Apps

List navbar-enabled third-party apps for a practice

Return the ordered list of app launchers for the practice's nine-dots menu.

Filter chain (all must be true for an app to appear):

  1. The OAuth application has an OAuthAppProfile with approval_status == APPROVED and is_first_party == False (escape-web itself must never show up as a launcher tile).
  2. The profile publishes a non-empty navbar_label — apps that haven't registered for the navbar stay invisible even if otherwise fully onboarded.
  3. There is at least one active OAuthPracticeGrant tying this application to this practice — only apps the practice has actually consented to appear in its launcher.
  4. No PracticeAppVisibility row hides the app for this practice. Absence of a row = default-visible.
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Toggle a third-party app's visibility in the practice's navbar

Practice-owner-only endpoint to hide/show a single app in the navbar.

Upserts a PracticeAppVisibility row keyed on (practice, app). Only the parent client's OWNER role (or a superuser) may hit this. Other staff — including practice ADMINs — will receive a 403.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_id
required
string
practice_uid
required
string <uuid>
Request Body schema:
is_visible
boolean

Responses

Request samples

Content type
{
  • "is_visible": true
}

Response samples

Content type
application/json
{
  • "is_visible": true
}

Disconnect (revoke) a third-party app from this practice

Revoke all OAuthPracticeGrant rows for this app + practice.

The access token cascade mirrors AppRevokeView but is scoped to a single practice rather than the entire org. Requires ADMIN/OFFICE_MANAGER practice role or OWNER/TECHNICAL client role.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_id
required
string
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_apps_connect_create

Self-registration endpoint for third-party OAuth apps.

POST /api/v1/practice/<uid>/apps/<client_id>/connect/

A third-party SPA calls this endpoint after it has obtained an access token via the standard Authorization Code + PKCE flow, to create an OAuthPracticeGrant tying itself to this practice. Once the grant exists the app appears in the nine-dots launcher for the practice.

Why not PracticeScopedMixin? PracticeScopedMixin.get_practice() enforces that an active OAuthPracticeGrant already exists before the third-party caller can access any practice-scoped endpoint. That is correct for data endpoints — but /connect/ is the endpoint that creates the grant. Using the mixin here would be a chicken-and-egg deadlock: you can't connect without already being connected.

Instead we:

  1. Verify the Bearer token is authenticated (IsAuthenticated).
  2. Directly look up the practice by URL UID and confirm the requesting user has a PracticeMembership in it.
  3. Create / reactivate the grant.

Security

  • Requires a valid Bearer token (IsAuthenticated).
  • User must have an active PracticeMembership for the practice (user.has_practice_access). This prevents a malicious token holder from manufacturing grants for practices they don't belong to.
  • The connecting client_id must be an approved, non-first-party application with a non-empty navbar_label.
  • The grant is (user, application, practice) — multi-user practices each consent independently, which is the correct per-user model.

Response

  • 201 Created — grant created or reactivated.
  • 200 OK — grant already active; idempotent re-connect.
  • 403 — user has no membership in this practice.
  • 404 — practice or app not found / not launcher-eligible.
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_id
required
string
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

Audited click-through for a third-party app launcher tile

Audited resolver for a single navbar launcher click.

The web client calls this instead of rendering a raw <a href> so that every launch produces a server-side audit record — useful both for HIPAA (who opened which third-party tool) and for product analytics (which integrations are actually used).

Success contract:

  • Returns 200 {"target_url": "..."} — web opens it in a new tab with rel=noopener,noreferrer and window.open's 3rd-arg equivalent.
  • Emits an oauth_app.launch audit event only on the success path — failed or unauthorized launches are not logged as launches.

Failure contract:

  • 404 for every navbar-ineligibility reason (unapproved, first-party, missing grant, hidden by visibility row, missing navbar_label or navbar_target_url). We deliberately use the same status for every reason so the endpoint does not leak which apps the practice has granted — that information belongs only to the owner's visibility screen.
  • 401 for unauthenticated callers (DRF default).
  • 403 for users with no access to the scoped practice (raised by PracticeScopedMixin).
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
client_id
required
string
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{}

Audit

audit_right_of_access_create

Queue a new right-of-access report for a patient.

Staff-only, practice-scoped. The report generation runs asynchronously in a Celery task; callers poll the companion endpoint for completion.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
patient_uid
required
string <uuid>
date_from
string <date>
date_to
string <date>
format
string
Default: "both"
Enum: "pdf" "json" "both"
  • pdf - pdf
  • json - json
  • both - both

Responses

Request samples

Content type
{
  • "patient_uid": "2e193f60-014a-4901-af70-2d4676096d5e",
  • "date_from": "2019-08-24",
  • "date_to": "2019-08-24",
  • "format": "both"
}

Response samples

Content type
application/json
{
  • "report_uid": "bf1f3ba6-daf7-4da1-8f23-14115cc9d017",
  • "status": "string",
  • "poll_url": "string"
}

audit_right_of_access_detail

Poll an existing right-of-access report.

Returns status + (when READY) time-limited signed download URLs. 404 on unknown report_uid; 403 if the report belongs to a different practice (enforced by PracticeScopedMixin on the URL practice_uid).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
report_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "report_uid": "bf1f3ba6-daf7-4da1-8f23-14115cc9d017",
  • "status": "string",
  • "requested_at": "2019-08-24T14:15:22Z",
  • "ready_at": "2019-08-24T14:15:22Z",
  • "date_from": "2019-08-24",
  • "date_to": "2019-08-24",
  • "event_count": 0,
  • "download_urls": {
    },
  • "error_message": "string"
}

Communications

practice_comms_commlog_list

Practice-wide commlog list and bulk create.

GET returns all commlogs for the practice (paginated, filterable by patient, date_from, date_to). POST accepts a JSON array for bulk import (up to 5000 records). PATCH accepts a JSON array of {id, ...} objects for bulk update.

Used by escape-opendental and escape-eaglesoft sync tools to avoid per-patient fetch loops. Each record must include patient in the body since the endpoint is not patient-scoped.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
date_from
string <date>

Inclusive lower bound on date_time (YYYY-MM-DD). Filters against the practice-local date portion of the comm log's timestamp.

date_to
string <date>

Inclusive upper bound on date_time (YYYY-MM-DD). Filters against the practice-local date portion of the comm log's timestamp.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

patient
string <uuid>

Filter comm logs to a single patient UID. Prefer the patient-scoped endpoint (/patient/{patient_id}/comms/commlog/) when you already have the patient in hand; this practice-wide view exists for sync tools that pull across the whole practice in one query.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_comms_commlog_create

Practice-wide commlog list and bulk create.

GET returns all commlogs for the practice (paginated, filterable by patient, date_from, date_to). POST accepts a JSON array for bulk import (up to 5000 records). PATCH accepts a JSON array of {id, ...} objects for bulk update.

Used by escape-opendental and escape-eaglesoft sync tools to avoid per-patient fetch loops. Each record must include patient in the body since the endpoint is not patient-scoped.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
patient
string or null <uuid>
date_time
string or null <date-time>
mode
string (ModeEnum)
Enum: "phone" "email" "text" "fax" "mail" "in_person" "web" "other"
  • phone - Phone
  • email - Email
  • text - Text
  • fax - Fax
  • mail - Mail
  • in_person - In Person
  • web - Web
  • other - Other
direction
string (Direction80cEnum)
Enum: "sent" "received" "neither"
  • sent - Sent
  • received - Received
  • neither - Neither
outcome
string
Enum: "success" "no_answer" "voicemail" "bounced" "bad_number" "other"

What happened on the contact attempt. Only success rows count toward the recall-list last_reached_at annotation.

  • success - Success
  • no_answer - No Answer
  • voicemail - Voicemail
  • bounced - Bounced
  • bad_number - Bad Number
  • other - Other
subject
string <= 255 characters

Short label, e.g. 'Recall reminder', 'Treatment plan follow-up'.

note
string
staff_user
string or null <uuid>

Staff member who logged the contact. Null for system-generated entries.

recall
string or null <uuid>

Optional link to the specific recall this contact addresses.

is_imported
boolean

True if this row was imported from a legacy PMS (escape-opendental, escape-eaglesoft, ...) rather than created natively in Escape. Imported rows may carry PHI in the note body that pre-dates the Escape BAA / no-PHI-in-comms policy (GH-575); clients must NOT expose 'resend' or 'use as template' affordances on imported rows, and any future send endpoint that takes a replicate_of_commlog_id MUST refuse imported sources.

custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "date_time": "2019-08-24T14:15:22Z",
  • "mode": "phone",
  • "direction": "sent",
  • "outcome": "success",
  • "subject": "string",
  • "note": "string",
  • "staff_user": "17986289-b0ef-402a-92d5-49bc6fa3367e",
  • "recall": "e7ef6ec4-8466-4387-af6a-2ed34de604a8",
  • "is_imported": true,
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "date_time": "2019-08-24T14:15:22Z",
  • "mode": "phone",
  • "direction": "sent",
  • "outcome": "success",
  • "subject": "string",
  • "note": "string",
  • "staff_user": "17986289-b0ef-402a-92d5-49bc6fa3367e",
  • "recall": "e7ef6ec4-8466-4387-af6a-2ed34de604a8",
  • "is_imported": true,
  • "custom_data": null
}

Get the practice's active fax number

Read the practice's active fax number (api#550).

GET /api/v1/practice/<uid>/fax/number/ returns the active :class:PracticeFaxNumber row, or 404 when none has been provisioned.

Open to any practice staff -- the cheat-sheet popover in the staff header surfaces the number for everyone, not just admins. Provision (POST /fax/provision/) stays admin-only.

The previous read path was sniffing the latest fax message in the inbox for a from_number (useActiveFaxNumber on the web side), which only worked after the first fax flowed through. A freshly-provisioned number is invisible to that path until somebody sends or receives one. This endpoint reads the actual provisioning row instead.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "e164_number": "string",
  • "sinch_number_id": "string",
  • "provisioned_at": "2019-08-24T14:15:22Z",
  • "deactivated_at": "2019-08-24T14:15:22Z",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

Provision a fax number for the practice

Provision a fax number for the practice (api#531).

POST /api/v1/practice/<uid>/fax/provision/ searches the upstream number inventory, picks the first candidate, rents it, and persists a :class:PracticeFaxNumber row. The flow is admin-only and idempotent on a per-practice basis -- a practice that already has an active number gets a 409 with the existing serialized row.

Per-number cost is absorbed into the base subscription, so provisioning is not plan-gated: any practice can rent a number through this endpoint. The send-side includes_fax gate (GH-443) still applies to actually transmitting documents, which is the per-page metered cost.

Body (all fields optional)::

{
    "area_code": "541",
    "preferred_locality": "OR"
}

area_code overrides the prefix sent upstream as numberPattern.searchPattern. preferred_locality is a hint today (we forward it as the regionCode-narrowing context for future cityName support). When neither is supplied we infer from the practice's address, falling back through zip_code -> state -> any-US until the upstream returns a result.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
area_code
string <= 3 characters

US area code (3 digits, e.g. 541). Sent to Sinch as the numberPattern prefix so the returned numbers all start with this code. Omit to infer from the practice's phone / ZIP.

preferred_locality
string <= 64 characters

Free-form locality hint (e.g. "OR" or "Eugene, OR") recorded on the audit trail. Sinch's Numbers API does not currently filter by city, so this is informational today.

Responses

Request samples

Content type
{
  • "area_code": "str",
  • "preferred_locality": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "e164_number": "string",
  • "sinch_number_id": "string",
  • "provisioned_at": "2019-08-24T14:15:22Z",
  • "deactivated_at": "2019-08-24T14:15:22Z",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_faxes_list

List and create faxes for the practice.

GET is read-only and open to any practice staff; POST is admin-only and gated by the practice's plan tier. The view sets practice and sent_by server-side; the serializer never trusts those from the body.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
delivery_status
Array of strings
Items Enum: "delivered" "failed" "queued" "receiving" "sending" "sent"

Filter by per-fax delivery state (the status column on the row, distinct from the ?status= triage filter). Accepts repeated params (?delivery_status=delivered&delivery_status=failed) or a comma-separated list (?delivery_status=delivered,failed); values within the filter are OR-combined. Unknown values are dropped. Primary use case: the Fax Inbox excluding receiving rows server-side so the paginated count envelope matches what the user sees (GH-611).

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

status
string
Enum: "all" "discarded" "filed" "unfiled"

Filter by triage state. unfiled returns inbound faxes still pending triage (no patient, no practice link, not discarded) — used by the Practice Inbox. filed and discarded are convenience filters for focused review. all (default) returns every fax — outbound rows always appear under all since filing only applies to inbound.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_faxes_create

List and create faxes for the practice.

GET is read-only and open to any practice staff; POST is admin-only and gated by the practice's plan tier. The view sets practice and sent_by server-side; the serializer never trusts those from the body.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema: multipart/form-data
required
to_number
required
string [ 1 .. 32 ] characters

E.164 destination.

document
required
string <binary>

The PDF to fax. Must be a single document; multi-doc batching is a phase-2 feature.

Responses

Response samples

Content type
application/json
{}

Restore a discarded fax (returns it to the unfiled queue)

Discard / un-discard an inbound fax (api#508).

Soft-flag — the underlying PDF is preserved for HIPAA retention and the row remains queryable for audit. DELETE marks the fax discarded; POST on the same path restores it (returns it to the unfiled queue).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
fax_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "direction": "inbound",
  • "from_number": "string",
  • "to_number": "string",
  • "page_count": 0,
  • "status": "queued",
  • "sinch_fax_id": "string",
  • "document_url": "string",
  • "error_message": "string",
  • "completed_at": "2019-08-24T14:15:22Z",
  • "sent_by": "40cc1a1c-5bda-4c73-bb08-df4a7613e4ee",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "practice_link": true,
  • "filed_at": "2019-08-24T14:15:22Z",
  • "filed_by": "011b59c1-1189-4a11-87df-fa9753db2861",
  • "discarded_at": "2019-08-24T14:15:22Z",
  • "discarded_by": "69474e1d-c497-4e9d-9f07-e93914ef0818",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

Discard an inbound fax (soft-flag — preserves PDF)

Discard / un-discard an inbound fax (api#508).

Soft-flag — the underlying PDF is preserved for HIPAA retention and the row remains queryable for audit. DELETE marks the fax discarded; POST on the same path restores it (returns it to the unfiled queue).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
fax_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "property1": null,
  • "property2": null
}

File an inbound fax against a patient or against the practice

File an inbound fax against a patient or against the practice (api#508).

POST body:

  • {"patient": "<uid>"} → file against the named patient.
  • {} (or {"patient": null}) → file against the practice.

Idempotent: re-filing refreshes filed_at and filed_by. Re-filing against a different target is allowed — staff who initially filed against the wrong patient can correct the assignment without an undo.

Outbound faxes are not eligible (they file themselves implicitly via the staff workflow that originated them); attempting to file one returns 400. Discarded faxes are not eligible either — restore via the discard endpoint's DELETE first.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
fax_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
patient
string or null <uuid>

UID of the patient to file the fax against. Omit (or send null) to file the fax against the practice.

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "direction": "inbound",
  • "from_number": "string",
  • "to_number": "string",
  • "page_count": 0,
  • "status": "queued",
  • "sinch_fax_id": "string",
  • "document_url": "string",
  • "error_message": "string",
  • "completed_at": "2019-08-24T14:15:22Z",
  • "sent_by": "40cc1a1c-5bda-4c73-bb08-df4a7613e4ee",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "practice_link": true,
  • "filed_at": "2019-08-24T14:15:22Z",
  • "filed_by": "011b59c1-1189-4a11-87df-fa9753db2861",
  • "discarded_at": "2019-08-24T14:15:22Z",
  • "discarded_by": "69474e1d-c497-4e9d-9f07-e93914ef0818",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_patient_comms_commlog_list

List and create communication log entries for a patient.

Supports ?date_from= and ?date_to= query params for date filtering. Bulk create is supported by POSTing an array.

GH-575: every list GET emits one comms.commlog_listed audit event carrying the actor, patient, and result count. Per-row events would N+1 the audit index on a 50-row page so we only fire once per request.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
date_from
string <date>

Inclusive lower bound on date_time (YYYY-MM-DD). Filters against the practice-local date portion of the comm log's timestamp.

date_to
string <date>

Inclusive upper bound on date_time (YYYY-MM-DD). Filters against the practice-local date portion of the comm log's timestamp.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_comms_commlog_create

List and create communication log entries for a patient.

Supports ?date_from= and ?date_to= query params for date filtering. Bulk create is supported by POSTing an array.

GH-575: every list GET emits one comms.commlog_listed audit event carrying the actor, patient, and result count. Per-row events would N+1 the audit index on a 50-row page so we only fire once per request.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
date_time
string or null <date-time>
mode
string (ModeEnum)
Enum: "phone" "email" "text" "fax" "mail" "in_person" "web" "other"
  • phone - Phone
  • email - Email
  • text - Text
  • fax - Fax
  • mail - Mail
  • in_person - In Person
  • web - Web
  • other - Other
direction
string (Direction80cEnum)
Enum: "sent" "received" "neither"
  • sent - Sent
  • received - Received
  • neither - Neither
outcome
string
Enum: "success" "no_answer" "voicemail" "bounced" "bad_number" "other"

What happened on the contact attempt. Only success rows count toward the recall-list last_reached_at annotation.

  • success - Success
  • no_answer - No Answer
  • voicemail - Voicemail
  • bounced - Bounced
  • bad_number - Bad Number
  • other - Other
subject
string <= 255 characters

Short label, e.g. 'Recall reminder', 'Treatment plan follow-up'.

note
string
staff_user
string or null <uuid>

Staff member who logged the contact. Null for system-generated entries.

recall
string or null <uuid>

Optional link to the specific recall this contact addresses.

custom_data
any

Responses

Request samples

Content type
{
  • "date_time": "2019-08-24T14:15:22Z",
  • "mode": "phone",
  • "direction": "sent",
  • "outcome": "success",
  • "subject": "string",
  • "note": "string",
  • "staff_user": "17986289-b0ef-402a-92d5-49bc6fa3367e",
  • "recall": "e7ef6ec4-8466-4387-af6a-2ed34de604a8",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "date_time": "2019-08-24T14:15:22Z",
  • "mode": "phone",
  • "direction": "sent",
  • "outcome": "success",
  • "subject": "string",
  • "note": "string",
  • "staff_user": "17986289-b0ef-402a-92d5-49bc6fa3367e",
  • "recall": "e7ef6ec4-8466-4387-af6a-2ed34de604a8",
  • "custom_data": null
}

practice_patient_comms_commlog_bulk_partial_update

Handle PATCH on the list endpoint for bulk updates.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
patient
string or null <uuid>
date_time
string or null <date-time>
mode
string (ModeEnum)
Enum: "phone" "email" "text" "fax" "mail" "in_person" "web" "other"
  • phone - Phone
  • email - Email
  • text - Text
  • fax - Fax
  • mail - Mail
  • in_person - In Person
  • web - Web
  • other - Other
direction
string (Direction80cEnum)
Enum: "sent" "received" "neither"
  • sent - Sent
  • received - Received
  • neither - Neither
outcome
string
Enum: "success" "no_answer" "voicemail" "bounced" "bad_number" "other"

What happened on the contact attempt. Only success rows count toward the recall-list last_reached_at annotation.

  • success - Success
  • no_answer - No Answer
  • voicemail - Voicemail
  • bounced - Bounced
  • bad_number - Bad Number
  • other - Other
subject
string <= 255 characters

Short label, e.g. 'Recall reminder', 'Treatment plan follow-up'.

note
string
staff_user
string or null <uuid>

Staff member who logged the contact. Null for system-generated entries.

recall
string or null <uuid>

Optional link to the specific recall this contact addresses.

custom_data
any

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "date_time": "2019-08-24T14:15:22Z",
  • "mode": "phone",
  • "direction": "sent",
  • "outcome": "success",
  • "subject": "string",
  • "note": "string",
  • "staff_user": "17986289-b0ef-402a-92d5-49bc6fa3367e",
  • "recall": "e7ef6ec4-8466-4387-af6a-2ed34de604a8",
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "date_time": "2019-08-24T14:15:22Z",
  • "mode": "phone",
  • "direction": "sent",
  • "outcome": "success",
  • "subject": "string",
  • "note": "string",
  • "phi_redacted_note": "string",
  • "staff_user": "17986289-b0ef-402a-92d5-49bc6fa3367e",
  • "recall": "e7ef6ec4-8466-4387-af6a-2ed34de604a8",
  • "is_imported": true,
  • "custom_data": null,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_sms_consents_list

List SMS consent rows for a single patient (api#637).

Returns an array of zero or one row given the unique-together (practice, patient) constraint. The list shape mirrors what web#485 already calls -- the staff UI degrades to "no row, default opted_in" when the response is empty.

The patient query parameter is required. A practice-wide list surface for a future compliance dashboard would be a separate view (the issue's optional ?state=opted_out filter); we deliberately don't conflate the two so the OpenAPI tag stays narrow.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
patient
required
string <uuid>

Filter to the single (practice, patient) consent row. Required -- the per-practice consent list is reserved for a future compliance-dashboard surface; today the patient-scoped lookup is the only supported shape.

Responses

Response samples

Content type
application/json
[
  • {
    }
]

practice_sms_messages_list

List and create SMS messages for the practice.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
direction
string
Enum: "inbound" "outbound"

Filter to inbound or outbound messages.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

patient
string <uuid>

Filter to messages associated with this patient.

status
string
Enum: "delivered" "failed" "queued" "received" "sending" "sent"

Filter by per-message delivery state.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_sms_messages_create

List and create SMS messages for the practice.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
patient
string or null <uuid>

Patient this message is for. When supplied, to_number is resolved from the patient's E.164 phone field server-side.

to_number
string <= 32 characters

E.164 destination override. Required when patient is omitted; ignored otherwise (the patient's phone wins).

body
required
string [ 1 .. 1600 ] characters

Message body. Refuses PHI -- diagnosis, prescriptions, tooth-level detail, etc. Send patients into the portal for clinical content.

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "to_number": "string",
  • "body": "string"
}

Response samples

Content type
application/json
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "to_number": "string",
  • "body": "string"
}

List the practice's provisioned SMS numbers

List SMS numbers assigned to the practice (history + active).

Read-only -- provisioning happens via an internal support tool / admin action today (see the issue body's "out of scope" + the api#622 follow-up for an admin endpoint). The active number is distinguishable by deactivated_at IS NULL on the row.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

List the calling user's SMS read receipts for this practice

List + upsert read-receipts for the calling staff user (api#643).

GET

Returns this user's read-receipts at this practice, one row per patient. The response is shaped to be cheap for the inbox to consume: [{patient_id, last_read_at}]. ?user=me is the only supported filter today; the parameter is reserved so a future cross-user surface can share the same URL.

POST

Upserts the row for (this practice, body.patient_id, this user). Idempotent and monotonic -- a write whose last_read_at is earlier than the current row's value is silently accepted as a no-op. This makes the endpoint safe for late-arriving events (slow mobile reconnecting after a laptop has already advanced the high-water mark).

Permissions: any practice member. Read-receipts aren't HIPAA- significant access events (the actual PHI-access event is the existing sms.viewed from api#636), so no audit emission here.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
user
string

Sentinel filter -- only me is supported. The list is always scoped to the calling user; the parameter exists so the URL contract reads naturally and so future cross-user surfaces (e.g. a supervisor dashboard) can extend the same path.

Responses

Response samples

Content type
application/json
{
  • "patient_id": "3854866a-5476-48be-8313-77029ccdd7a7",
  • "last_read_at": "2019-08-24T14:15:22Z"
}

Upsert this user's read-receipt for one patient thread

List + upsert read-receipts for the calling staff user (api#643).

GET

Returns this user's read-receipts at this practice, one row per patient. The response is shaped to be cheap for the inbox to consume: [{patient_id, last_read_at}]. ?user=me is the only supported filter today; the parameter is reserved so a future cross-user surface can share the same URL.

POST

Upserts the row for (this practice, body.patient_id, this user). Idempotent and monotonic -- a write whose last_read_at is earlier than the current row's value is silently accepted as a no-op. This makes the endpoint safe for late-arriving events (slow mobile reconnecting after a laptop has already advanced the high-water mark).

Permissions: any practice member. Read-receipts aren't HIPAA- significant access events (the actual PHI-access event is the existing sms.viewed from api#636), so no audit emission here.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
patient_id
required
string <uuid>

Patient whose thread the user just finished reading.

last_read_at
required
string <date-time>

ISO-8601 UTC datetime of the most-recently-read message. Must include a timezone suffix ('Z' or '+HH:MM'). The server applies 'no earlier than' semantics -- a write older than the current row is silently accepted as a no-op.

Responses

Request samples

Content type
{
  • "patient_id": "3854866a-5476-48be-8313-77029ccdd7a7",
  • "last_read_at": "2019-08-24T14:15:22Z"
}

Response samples

Content type
application/json
{
  • "patient_id": "3854866a-5476-48be-8313-77029ccdd7a7",
  • "last_read_at": "2019-08-24T14:15:22Z"
}

Intake

practice_intake_new_patient_draft_create

POST a fresh draft from the kiosk.

Mirrors :class:apps.tablets.views_checkin.KioskCheckInView's auth contract: the calling tablet's OAuth bearer is the auth, and the tablet's bound practice must match the URL practice. A staff session is rejected with 401 -- the kiosk submit surface is exclusively for in-office tablets so we don't accidentally accept a draft from somewhere that isn't running the kiosk wizard.

On success the draft is created in pending and the response carries only the new draft uid -- the kiosk does not need the full record back.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
submitted_via
string
Default: "kiosk"
Enum: "kiosk" "portal" "staff_form"

Source channel; defaults to kiosk.

  • kiosk - Kiosk
  • portal - Patient Portal
  • staff_form - Staff-entered form
personal_info
any

Demographics; mirrors Patient model field names so approve can copy 1:1.

insurance_info
any

Insurance demographics; photo refs point at doccenter rows.

medical_history
any

Conditions / allergies / medications; mirrors clinical models' shape.

signature_b64
string
Default: ""

Base64-encoded raw signed-consent capture (image or pad blob). Stored as bytes server-side; legal evidence.

Responses

Request samples

Content type
{
  • "submitted_via": "kiosk",
  • "personal_info": null,
  • "insurance_info": null,
  • "medical_history": null,
  • "signature_b64": ""
}

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_intake_new_patient_drafts_list

List drafts at the calling practice.

Default filter is status=pending (the inbox view). Pass ?status=approved|merged|rejected|all to widen the scope. The list endpoint is staff manager+ because the JSON buckets contain raw PHI.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_intake_new_patient_drafts_retrieve

Full draft including JSON buckets.

Logs intake.draft_viewed on every GET because the body is PHI.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
draft_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "submitted_via": "kiosk",
  • "submitted_at": "2019-08-24T14:15:22Z",
  • "tablet": "46d0c8fb-00bd-41e9-bcab-ebcb205c05ad",
  • "personal_info": null,
  • "insurance_info": null,
  • "medical_history": null,
  • "signature_b64": "string",
  • "status": "pending",
  • "reviewed_by": "92ab4dbc-1b27-40ce-b24b-7dde8f4709be",
  • "reviewed_at": "2019-08-24T14:15:22Z",
  • "merged_into_patient": "eae1c63b-a395-425f-a8d7-ec1627ff32ae",
  • "approved_patient": "57687379-a30a-4785-a564-991cdb98b023",
  • "rejection_reason": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_intake_new_patient_drafts_approve_create

Approve a draft, minting a new :class:apps.patients.models.Patient.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
draft_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_intake_new_patient_drafts_merge_create

Merge a draft into an existing :class:apps.patients.models.Patient.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
draft_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
target_patient_uid
required
string <uuid>

UUID of the existing patient that should absorb this draft.

Responses

Request samples

Content type
{
  • "target_patient_uid": "e93aa6ec-2ecf-4b23-b671-922d08049e1d"
}

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_intake_new_patient_drafts_reject_create

Reject a draft with a free-text reason.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
draft_uid
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
reason
required
string [ 1 .. 255 ] characters

Free-text reason for rejection; stays on the row for audit.

Responses

Request samples

Content type
{
  • "reason": "string"
}

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

Messaging

List conversations

List conversations the user participates in, or create a new one.

GET returns a paginated list of conversations ordered by most recent activity, filtered to only those the requesting user is a participant of. POST creates a new conversation and optionally sends the first message.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create conversation

List conversations the user participates in, or create a new one.

GET returns a paginated list of conversations ordered by most recent activity, filtered to only those the requesting user is a participant of. POST creates a new conversation and optionally sends the first message.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
participant_ids
Array of strings <uuid> [ items <uuid > ]

UUIDs of the users to include (the sender is added automatically).

conversation_type
string
Default: "direct"
Enum: "direct" "operatory" "system"
  • direct - Direct
  • operatory - Operatory
  • system - System
title
string <= 255 characters
Default: ""
operatory
string or null <uuid>
body
string
Default: ""

Optional first message body.

Responses

Request samples

Content type
{
  • "participant_ids": [
    ],
  • "conversation_type": "direct",
  • "title": "",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "body": ""
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "title": "string",
  • "conversation_type": "direct",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "participants": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

Retrieve conversation

Retrieve a single conversation.

Direct conversations require explicit participant membership. Operatory conversations are visible to any active practice member.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
conversation_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "title": "string",
  • "conversation_type": "direct",
  • "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
  • "participants": [
    ],
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

List messages

List messages in a conversation or send a new one.

GET returns messages in chronological order (oldest first), paginated. POST creates a new message and updates the conversation's modified timestamp so it bubbles to the top of the list.

Operatory conversations are accessible to every practice member.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
conversation_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Send message

List messages in a conversation or send a new one.

GET returns messages in chronological order (oldest first), paginated. POST creates a new message and updates the conversation's modified timestamp so it bubbles to the top of the list.

Operatory conversations are accessible to every practice member.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
conversation_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

Mark conversation as read

Update the requesting user's last_read_at timestamp.

PATCH (no body required) sets last_read_at to now, clearing the unread badge for this conversation.

For operatory conversations the user may not have an explicit participant record yet, so we create one on-the-fly via update_or_create.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
conversation_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

List active chair-presence rows

Return every active chair-presence row in this practice.

Powers the messaging-menu's "OP 3 -- Jane S." occupant labels. Only rows where released_at IS NULL are returned; auto-released rows are filtered out so the UI never shows a stale claim past the 8-hour sanity cutoff.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Claim an operatory (chair presence)

Claim a chair as the calling user's current operatory.

POST body: {"operatory_id": "<uuid>"}.

Idempotent: a repeat claim on the same chair returns 200 with the existing row. A claim on a different chair releases the caller's previous claim first (a user is at one chair at a time).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
operatory_id
required
string <uuid>

Responses

Request samples

Content type
{
  • "operatory_id": "700062e2-3e2d-40d4-aa03-805aad7e7b9e"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "operatory_id": "700062e2-3e2d-40d4-aa03-805aad7e7b9e",
  • "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
  • "first_name": "string",
  • "last_name": "string",
  • "claimed_at": "2019-08-24T14:15:22Z",
  • "auto_release_at": "2019-08-24T14:15:22Z"
}

Get the active occupant for a specific chair

Return the active occupant for <operatory_uid>, or 404.

Used when the messaging menu wants a single chair's occupant without pulling the practice-wide list (e.g. opening a thread directly).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
operatory_uid
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "operatory_id": "700062e2-3e2d-40d4-aa03-805aad7e7b9e",
  • "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
  • "first_name": "string",
  • "last_name": "string",
  • "claimed_at": "2019-08-24T14:15:22Z",
  • "auto_release_at": "2019-08-24T14:15:22Z"
}

Release the caller's chair presence

Release the calling user's claim on an operatory.

POST body: {"operatory_id": "<uuid>"}. Returns 200 with {"released": true|false} -- false indicating the user had no active claim on the chair (still a success, just a no-op).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
operatory_id
required
string <uuid>

Responses

Request samples

Content type
{
  • "operatory_id": "700062e2-3e2d-40d4-aa03-805aad7e7b9e"
}

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

Get or create operatory conversation

Convenience endpoint for operatory-addressed messaging.

GET .../operatory/<operatory_id>/ — returns the operatory's conversation, creating it if one doesn't exist yet.

POST .../operatory/<operatory_id>/ — finds (or creates) the operatory conversation and sends a message in a single round-trip.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
operatory_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Send message to operatory conversation

Convenience endpoint for operatory-addressed messaging.

GET .../operatory/<operatory_id>/ — returns the operatory's conversation, creating it if one doesn't exist yet.

POST .../operatory/<operatory_id>/ — finds (or creates) the operatory conversation and sends a message in a single round-trip.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
operatory_id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

List practice member presence

Return online/offline status and last_seen_at for all practice members.

GET /api/v1/practice/<uid>/messaging/presence/

A member is considered online if they have an active WebSocket connection. Since presence is tracked via in-memory channel-layer groups (not database state), this endpoint reports last_seen_at from the User model as a fallback for offline users. The frontend should use the presence.update WebSocket event for real-time changes and this endpoint only for initial page load.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Patient Inbox

practice_patient_inbox_list

Staff-facing inbox for unreviewed :class:NewPatientDraft rows.

Mounted at /api/v1/practice/<uid>/patient-inbox/ with the standard ViewSet routes plus three @action transitions:

  • POST .../<id>/convert/ -- mint a new patient.
  • POST .../<id>/merge/ -- fold into an existing patient.
  • POST .../<id>/dismiss/ -- terminal, no patient created.

The endpoint is manager-or-above on read AND write because the JSON buckets ARE PHI (api#770 mirrors the api#761 pattern); the enforce_role_on_read = True flag is what makes the role gate fire on GET as well as POST.

Audit

Every state change emits an intake.* semantic event with PHI- scrubbed metadata. List + retrieve also emit access events so a HIPAA reviewer can reconstruct who read the staging table.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

status
string
Enum: "all" "approved" "converted" "dismissed" "merged" "pending" "ready_for_review" "rejected"

Filter drafts by lifecycle status. Default is the open states (pending + ready_for_review); pass an explicit value to widen, or all for every state.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_inbox_retrieve

Staff-facing inbox for unreviewed :class:NewPatientDraft rows.

Mounted at /api/v1/practice/<uid>/patient-inbox/ with the standard ViewSet routes plus three @action transitions:

  • POST .../<id>/convert/ -- mint a new patient.
  • POST .../<id>/merge/ -- fold into an existing patient.
  • POST .../<id>/dismiss/ -- terminal, no patient created.

The endpoint is manager-or-above on read AND write because the JSON buckets ARE PHI (api#770 mirrors the api#761 pattern); the enforce_role_on_read = True flag is what makes the role gate fire on GET as well as POST.

Audit

Every state change emits an intake.* semantic event with PHI- scrubbed metadata. List + retrieve also emit access events so a HIPAA reviewer can reconstruct who read the staging table.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "submitted_via": "kiosk",
  • "submitted_at": "2019-08-24T14:15:22Z",
  • "tablet": "46d0c8fb-00bd-41e9-bcab-ebcb205c05ad",
  • "personal_info": null,
  • "insurance_info": null,
  • "medical_history": null,
  • "signature_b64": "string",
  • "status": "pending",
  • "reviewed_by": "92ab4dbc-1b27-40ce-b24b-7dde8f4709be",
  • "reviewed_at": "2019-08-24T14:15:22Z",
  • "merged_into_patient": "eae1c63b-a395-425f-a8d7-ec1627ff32ae",
  • "converted_to_patient": "9bc32040-0306-4132-bc06-10e779b712a9",
  • "approved_patient": "57687379-a30a-4785-a564-991cdb98b023",
  • "rejection_reason": "string",
  • "dedup_candidates": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_patient_inbox_convert_create

Convert a draft into a brand-new :class:Patient.

Mints a fresh patient row from the draft's structured fields, links it via converted_to_patient, flips the draft into converted, and audit-logs the transition. Returns the same shape the legacy approve endpoint emits plus the source draft id for the staff UI's success toast.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_inbox_dismiss_create

Dismiss a draft as spam / accidental submission.

Reason is optional; staff who supply one get it persisted on the row for audit. No patient is created or modified.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string
practice_uid
required
string <uuid>
Request Body schema:
reason
string <= 255 characters
Default: ""

Optional free-text reason; persisted on the draft for audit.

Responses

Request samples

Content type
{
  • "reason": ""
}

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_inbox_merge_create

Fold a draft into an existing :class:Patient.

Demographics on the target are left alone -- the merge only attaches the draft's insurance + medical-history child rows. Staff who want to refresh the patient's name / DOB / address should use the regular patient-edit surface.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string
practice_uid
required
string <uuid>
Request Body schema:
required
patient_id
required
string <uuid>

UUID of the existing patient that should absorb this draft.

Responses

Request samples

Content type
{
  • "patient_id": "3854866a-5476-48be-8313-77029ccdd7a7"
}

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

Prescriptions

practice_patient_prescription_list

List and create prescriptions.

GET /v1/practice//prescription/ POST /v1/practice//prescription/

Query params

patient — filter by patient UUID status — filter by status (draft/final/cancelled) search — case-insensitive drug name search

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_patient_prescription_create

List and create prescriptions.

GET /v1/practice//prescription/ POST /v1/practice//prescription/

Query params

patient — filter by patient UUID status — filter by status (draft/final/cancelled) search — case-insensitive drug name search

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
patient
required
string <uuid>
provider
string or null <uuid>

The prescribing/responsible provider. Required to finalise.

drug_name
required
string [ 1 .. 200 ] characters

e.g. Amoxicillin

drug_strength
string <= 100 characters

e.g. 500mg

drug_form
string <= 100 characters

Dosage form: Capsule, Tablet, Solution, Cream, etc.

quantity
string <= 50 characters

e.g. #21 or 30 mL

directions
required
string non-empty

Sig / patient instructions e.g. 'Take 1 capsule by mouth three times daily for 7 days'

refills
integer [ 0 .. 32767 ]

Number of refills (0 = no refills). Controlled substances may not be refilled in many states.

substitution_permitted
boolean

Allow pharmacist to substitute generic equivalent.

cs_schedule
string
Enum: "none" "II" "III" "IV" "V"

DEA Controlled Substance Schedule. Non-Controlled for the vast majority of dental prescriptions (antibiotics, NSAIDs, fluoride, chlorhexidine). Use Schedule II–V only for opioids, benzodiazepines, etc.

  • none - Non-Controlled
  • II - Schedule II
  • III - Schedule III
  • IV - Schedule IV
  • V - Schedule V
diagnosis_description
string <= 255 characters

Brief clinical indication e.g. 'Post-extraction infection'.

appointment
string or null <uuid>
notes
string

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "diagnosis_description": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "notes": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "patient_name": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "is_controlled": true,
  • "diagnosis_description": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "status": "draft",
  • "finalized_at": "2019-08-24T14:15:22Z",
  • "finalized_by": "ca059483-923c-4d0a-bf3a-a20808c35301",
  • "finalized_by_name": "string",
  • "notes": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_patient_prescription_retrieve

Retrieve or update a prescription (draft only).

GET /v1/practice//prescription// PATCH /v1/practice//prescription//

Only draft prescriptions may be edited. Use the /finalise/ action to advance to final.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
prescription_id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "patient_name": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "is_controlled": true,
  • "diagnosis_description": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "status": "draft",
  • "finalized_at": "2019-08-24T14:15:22Z",
  • "finalized_by": "ca059483-923c-4d0a-bf3a-a20808c35301",
  • "finalized_by_name": "string",
  • "notes": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_patient_prescription_update

Retrieve or update a prescription (draft only).

GET /v1/practice//prescription// PATCH /v1/practice//prescription//

Only draft prescriptions may be edited. Use the /finalise/ action to advance to final.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
prescription_id
required
string <uuid>
Request Body schema:
required
patient
required
string <uuid>
provider
string or null <uuid>

The prescribing/responsible provider. Required to finalise.

drug_name
required
string [ 1 .. 200 ] characters

e.g. Amoxicillin

drug_strength
string <= 100 characters

e.g. 500mg

drug_form
string <= 100 characters

Dosage form: Capsule, Tablet, Solution, Cream, etc.

quantity
string <= 50 characters

e.g. #21 or 30 mL

directions
required
string non-empty

Sig / patient instructions e.g. 'Take 1 capsule by mouth three times daily for 7 days'

refills
integer [ 0 .. 32767 ]

Number of refills (0 = no refills). Controlled substances may not be refilled in many states.

substitution_permitted
boolean

Allow pharmacist to substitute generic equivalent.

cs_schedule
string
Enum: "none" "II" "III" "IV" "V"

DEA Controlled Substance Schedule. Non-Controlled for the vast majority of dental prescriptions (antibiotics, NSAIDs, fluoride, chlorhexidine). Use Schedule II–V only for opioids, benzodiazepines, etc.

  • none - Non-Controlled
  • II - Schedule II
  • III - Schedule III
  • IV - Schedule IV
  • V - Schedule V
diagnosis_description
string <= 255 characters

Brief clinical indication e.g. 'Post-extraction infection'.

appointment
string or null <uuid>
notes
string

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "diagnosis_description": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "notes": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "patient_name": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "is_controlled": true,
  • "diagnosis_description": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "status": "draft",
  • "finalized_at": "2019-08-24T14:15:22Z",
  • "finalized_by": "ca059483-923c-4d0a-bf3a-a20808c35301",
  • "finalized_by_name": "string",
  • "notes": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_patient_prescription_partial_update

Retrieve or update a prescription (draft only).

GET /v1/practice//prescription// PATCH /v1/practice//prescription//

Only draft prescriptions may be edited. Use the /finalise/ action to advance to final.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
prescription_id
required
string <uuid>
Request Body schema:
patient
string <uuid>
provider
string or null <uuid>

The prescribing/responsible provider. Required to finalise.

drug_name
string [ 1 .. 200 ] characters

e.g. Amoxicillin

drug_strength
string <= 100 characters

e.g. 500mg

drug_form
string <= 100 characters

Dosage form: Capsule, Tablet, Solution, Cream, etc.

quantity
string <= 50 characters

e.g. #21 or 30 mL

directions
string non-empty

Sig / patient instructions e.g. 'Take 1 capsule by mouth three times daily for 7 days'

refills
integer [ 0 .. 32767 ]

Number of refills (0 = no refills). Controlled substances may not be refilled in many states.

substitution_permitted
boolean

Allow pharmacist to substitute generic equivalent.

cs_schedule
string
Enum: "none" "II" "III" "IV" "V"

DEA Controlled Substance Schedule. Non-Controlled for the vast majority of dental prescriptions (antibiotics, NSAIDs, fluoride, chlorhexidine). Use Schedule II–V only for opioids, benzodiazepines, etc.

  • none - Non-Controlled
  • II - Schedule II
  • III - Schedule III
  • IV - Schedule IV
  • V - Schedule V
diagnosis_description
string <= 255 characters

Brief clinical indication e.g. 'Post-extraction infection'.

appointment
string or null <uuid>
notes
string

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "diagnosis_description": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "notes": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "patient_name": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "is_controlled": true,
  • "diagnosis_description": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "status": "draft",
  • "finalized_at": "2019-08-24T14:15:22Z",
  • "finalized_by": "ca059483-923c-4d0a-bf3a-a20808c35301",
  • "finalized_by_name": "string",
  • "notes": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_patient_prescription_cancel_create

Cancel a prescription (draft or final).

POST /v1/practice//prescription//cancel/

Any staff member may cancel a draft. Only ADMIN/PROVIDER may cancel a finalised prescription (e.g. if an error was discovered after printing).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
prescription_id
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_prescription_finalise_create

Finalise a draft prescription.

POST /v1/practice//prescription//finalise/

Only a user who holds a prescribing-provider role (ADMIN or PROVIDER in the practice membership) may finalise. This represents the provider reviewing the draft entered by staff and giving their sign-off.

For controlled substances, the provider must still physically sign the printed paper prescription. This endpoint is NOT an EPCS action and does not constitute an electronic DEA signature.

Returns the updated prescription payload.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
prescription_id
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_patient_prescription_pdf_retrieve

Render a prescription as a printable PDF.

GET /v1/practice//prescription//pdf/

Returns application/pdf. Only final prescriptions may be rendered; draft prescriptions return 400.

The PDF is formatted as a standard paper Rx form including:

  • Practice name, address, phone
  • Provider name, NPI, DEA number
  • Patient name, date of birth
  • Date of prescription
  • Drug details and directions
  • Blank diagonal line below the drug entry (tamper-evident, required for controlled substance paper prescriptions in many states)
  • Provider signature line

Emits a prescription.printed audit event so there is a permanent record of when the form was accessed for printing.

Note: For paper controlled-substance prescriptions, the provider must physically sign the printed form. This endpoint is not an EPCS action and does not constitute a DEA electronic signature.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
patient_id
required
string <uuid>
practice_uid
required
string <uuid>
prescription_id
required
string <uuid>

Responses

practice_prescription_list

List and create prescriptions.

GET /v1/practice//prescription/ POST /v1/practice//prescription/

Query params

patient — filter by patient UUID status — filter by status (draft/final/cancelled) search — case-insensitive drug name search

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_prescription_create

List and create prescriptions.

GET /v1/practice//prescription/ POST /v1/practice//prescription/

Query params

patient — filter by patient UUID status — filter by status (draft/final/cancelled) search — case-insensitive drug name search

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
patient
required
string <uuid>
provider
string or null <uuid>

The prescribing/responsible provider. Required to finalise.

drug_name
required
string [ 1 .. 200 ] characters

e.g. Amoxicillin

drug_strength
string <= 100 characters

e.g. 500mg

drug_form
string <= 100 characters

Dosage form: Capsule, Tablet, Solution, Cream, etc.

quantity
string <= 50 characters

e.g. #21 or 30 mL

directions
required
string non-empty

Sig / patient instructions e.g. 'Take 1 capsule by mouth three times daily for 7 days'

refills
integer [ 0 .. 32767 ]

Number of refills (0 = no refills). Controlled substances may not be refilled in many states.

substitution_permitted
boolean

Allow pharmacist to substitute generic equivalent.

cs_schedule
string
Enum: "none" "II" "III" "IV" "V"

DEA Controlled Substance Schedule. Non-Controlled for the vast majority of dental prescriptions (antibiotics, NSAIDs, fluoride, chlorhexidine). Use Schedule II–V only for opioids, benzodiazepines, etc.

  • none - Non-Controlled
  • II - Schedule II
  • III - Schedule III
  • IV - Schedule IV
  • V - Schedule V
diagnosis_description
string <= 255 characters

Brief clinical indication e.g. 'Post-extraction infection'.

appointment
string or null <uuid>
notes
string

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "diagnosis_description": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "notes": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "patient_name": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "is_controlled": true,
  • "diagnosis_description": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "status": "draft",
  • "finalized_at": "2019-08-24T14:15:22Z",
  • "finalized_by": "ca059483-923c-4d0a-bf3a-a20808c35301",
  • "finalized_by_name": "string",
  • "notes": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_prescription_retrieve

Retrieve or update a prescription (draft only).

GET /v1/practice//prescription// PATCH /v1/practice//prescription//

Only draft prescriptions may be edited. Use the /finalise/ action to advance to final.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
prescription_id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "patient_name": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "is_controlled": true,
  • "diagnosis_description": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "status": "draft",
  • "finalized_at": "2019-08-24T14:15:22Z",
  • "finalized_by": "ca059483-923c-4d0a-bf3a-a20808c35301",
  • "finalized_by_name": "string",
  • "notes": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_prescription_update

Retrieve or update a prescription (draft only).

GET /v1/practice//prescription// PATCH /v1/practice//prescription//

Only draft prescriptions may be edited. Use the /finalise/ action to advance to final.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
prescription_id
required
string <uuid>
Request Body schema:
required
patient
required
string <uuid>
provider
string or null <uuid>

The prescribing/responsible provider. Required to finalise.

drug_name
required
string [ 1 .. 200 ] characters

e.g. Amoxicillin

drug_strength
string <= 100 characters

e.g. 500mg

drug_form
string <= 100 characters

Dosage form: Capsule, Tablet, Solution, Cream, etc.

quantity
string <= 50 characters

e.g. #21 or 30 mL

directions
required
string non-empty

Sig / patient instructions e.g. 'Take 1 capsule by mouth three times daily for 7 days'

refills
integer [ 0 .. 32767 ]

Number of refills (0 = no refills). Controlled substances may not be refilled in many states.

substitution_permitted
boolean

Allow pharmacist to substitute generic equivalent.

cs_schedule
string
Enum: "none" "II" "III" "IV" "V"

DEA Controlled Substance Schedule. Non-Controlled for the vast majority of dental prescriptions (antibiotics, NSAIDs, fluoride, chlorhexidine). Use Schedule II–V only for opioids, benzodiazepines, etc.

  • none - Non-Controlled
  • II - Schedule II
  • III - Schedule III
  • IV - Schedule IV
  • V - Schedule V
diagnosis_description
string <= 255 characters

Brief clinical indication e.g. 'Post-extraction infection'.

appointment
string or null <uuid>
notes
string

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "diagnosis_description": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "notes": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "patient_name": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "is_controlled": true,
  • "diagnosis_description": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "status": "draft",
  • "finalized_at": "2019-08-24T14:15:22Z",
  • "finalized_by": "ca059483-923c-4d0a-bf3a-a20808c35301",
  • "finalized_by_name": "string",
  • "notes": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_prescription_partial_update

Retrieve or update a prescription (draft only).

GET /v1/practice//prescription// PATCH /v1/practice//prescription//

Only draft prescriptions may be edited. Use the /finalise/ action to advance to final.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
prescription_id
required
string <uuid>
Request Body schema:
patient
string <uuid>
provider
string or null <uuid>

The prescribing/responsible provider. Required to finalise.

drug_name
string [ 1 .. 200 ] characters

e.g. Amoxicillin

drug_strength
string <= 100 characters

e.g. 500mg

drug_form
string <= 100 characters

Dosage form: Capsule, Tablet, Solution, Cream, etc.

quantity
string <= 50 characters

e.g. #21 or 30 mL

directions
string non-empty

Sig / patient instructions e.g. 'Take 1 capsule by mouth three times daily for 7 days'

refills
integer [ 0 .. 32767 ]

Number of refills (0 = no refills). Controlled substances may not be refilled in many states.

substitution_permitted
boolean

Allow pharmacist to substitute generic equivalent.

cs_schedule
string
Enum: "none" "II" "III" "IV" "V"

DEA Controlled Substance Schedule. Non-Controlled for the vast majority of dental prescriptions (antibiotics, NSAIDs, fluoride, chlorhexidine). Use Schedule II–V only for opioids, benzodiazepines, etc.

  • none - Non-Controlled
  • II - Schedule II
  • III - Schedule III
  • IV - Schedule IV
  • V - Schedule V
diagnosis_description
string <= 255 characters

Brief clinical indication e.g. 'Post-extraction infection'.

appointment
string or null <uuid>
notes
string

Responses

Request samples

Content type
{
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "diagnosis_description": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "notes": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "patient": "a7129932-7174-432d-a8dd-570510e145bb",
  • "patient_name": "string",
  • "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
  • "provider_name": "string",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "is_controlled": true,
  • "diagnosis_description": "string",
  • "appointment": "c776433a-7ab1-49de-96dc-e0f963546e2e",
  • "status": "draft",
  • "finalized_at": "2019-08-24T14:15:22Z",
  • "finalized_by": "ca059483-923c-4d0a-bf3a-a20808c35301",
  • "finalized_by_name": "string",
  • "notes": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_prescription_cancel_create

Cancel a prescription (draft or final).

POST /v1/practice//prescription//cancel/

Any staff member may cancel a draft. Only ADMIN/PROVIDER may cancel a finalised prescription (e.g. if an error was discovered after printing).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
prescription_id
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_prescription_finalise_create

Finalise a draft prescription.

POST /v1/practice//prescription//finalise/

Only a user who holds a prescribing-provider role (ADMIN or PROVIDER in the practice membership) may finalise. This represents the provider reviewing the draft entered by staff and giving their sign-off.

For controlled substances, the provider must still physically sign the printed paper prescription. This endpoint is NOT an EPCS action and does not constitute an electronic DEA signature.

Returns the updated prescription payload.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
prescription_id
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_prescription_pdf_retrieve

Render a prescription as a printable PDF.

GET /v1/practice//prescription//pdf/

Returns application/pdf. Only final prescriptions may be rendered; draft prescriptions return 400.

The PDF is formatted as a standard paper Rx form including:

  • Practice name, address, phone
  • Provider name, NPI, DEA number
  • Patient name, date of birth
  • Date of prescription
  • Drug details and directions
  • Blank diagonal line below the drug entry (tamper-evident, required for controlled substance paper prescriptions in many states)
  • Provider signature line

Emits a prescription.printed audit event so there is a permanent record of when the form was accessed for printing.

Note: For paper controlled-substance prescriptions, the provider must physically sign the printed form. This endpoint is not an EPCS action and does not constitute a DEA electronic signature.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
prescription_id
required
string <uuid>

Responses

practice_prescription_template_list

List and create practice prescription templates.

GET /v1/practice//prescription/template/ POST /v1/practice//prescription/template/

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

practice_prescription_template_create

List and create practice prescription templates.

GET /v1/practice//prescription/template/ POST /v1/practice//prescription/template/

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 200 ] characters

Template display name shown in the picker e.g. 'Amoxicillin 500mg #21'

drug_name
required
string [ 1 .. 200 ] characters
drug_strength
string <= 100 characters
drug_form
string <= 100 characters
quantity
string <= 50 characters
directions
required
string non-empty
refills
integer [ 0 .. 32767 ]
substitution_permitted
boolean
cs_schedule
string (CsScheduleEnum)
Enum: "none" "II" "III" "IV" "V"
  • none - Non-Controlled
  • II - Schedule II
  • III - Schedule III
  • IV - Schedule IV
  • V - Schedule V
is_active
boolean

Responses

Request samples

Content type
{
  • "name": "string",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "is_active": true
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "is_active": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_prescription_template_retrieve

Retrieve, update, or delete a prescription template.

GET /v1/practice//prescription/template// PATCH /v1/practice//prescription/template// DELETE /v1/practice//prescription/template//

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "is_active": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_prescription_template_update

Retrieve, update, or delete a prescription template.

GET /v1/practice//prescription/template// PATCH /v1/practice//prescription/template// DELETE /v1/practice//prescription/template//

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_id
required
string <uuid>
Request Body schema:
required
name
required
string [ 1 .. 200 ] characters

Template display name shown in the picker e.g. 'Amoxicillin 500mg #21'

drug_name
required
string [ 1 .. 200 ] characters
drug_strength
string <= 100 characters
drug_form
string <= 100 characters
quantity
string <= 50 characters
directions
required
string non-empty
refills
integer [ 0 .. 32767 ]
substitution_permitted
boolean
cs_schedule
string (CsScheduleEnum)
Enum: "none" "II" "III" "IV" "V"
  • none - Non-Controlled
  • II - Schedule II
  • III - Schedule III
  • IV - Schedule IV
  • V - Schedule V
is_active
boolean

Responses

Request samples

Content type
{
  • "name": "string",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "is_active": true
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "is_active": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_prescription_template_partial_update

Retrieve, update, or delete a prescription template.

GET /v1/practice//prescription/template// PATCH /v1/practice//prescription/template// DELETE /v1/practice//prescription/template//

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_id
required
string <uuid>
Request Body schema:
name
string [ 1 .. 200 ] characters

Template display name shown in the picker e.g. 'Amoxicillin 500mg #21'

drug_name
string [ 1 .. 200 ] characters
drug_strength
string <= 100 characters
drug_form
string <= 100 characters
quantity
string <= 50 characters
directions
string non-empty
refills
integer [ 0 .. 32767 ]
substitution_permitted
boolean
cs_schedule
string (CsScheduleEnum)
Enum: "none" "II" "III" "IV" "V"
  • none - Non-Controlled
  • II - Schedule II
  • III - Schedule III
  • IV - Schedule IV
  • V - Schedule V
is_active
boolean

Responses

Request samples

Content type
{
  • "name": "string",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "is_active": true
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "drug_name": "string",
  • "drug_strength": "string",
  • "drug_form": "string",
  • "quantity": "string",
  • "directions": "string",
  • "refills": 32767,
  • "substitution_permitted": true,
  • "cs_schedule": "none",
  • "is_active": true,
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

practice_prescription_template_destroy

Retrieve, update, or delete a prescription template.

GET /v1/practice//prescription/template// PATCH /v1/practice//prescription/template// DELETE /v1/practice//prescription/template//

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
template_id
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

Patient Submissions

practice_portal_patient_submissions_list

List patient submissions for a practice.

GET /api/v1/practice//patient-submissions/

Defaults to pending submissions. Use ?status=approved or ?status=rejected to filter.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json

Default ordering is newest-first by created. Filter with ?status=pending / ?status=approved / ?status=rejected to scope the front-desk review queue.

{
  • "count": 123,
  • "results": [
    ]
}

practice_portal_patient_submissions_retrieve

Retrieve a single patient submission with full detail.

GET /api/v1/practice//patient-submissions//

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json

Returned to staff reviewing a submission. submitted_data is an open JSON object -- shape is defined by the intake form the patient filled out. No schema validation is enforced here; the approve step copies known fields to the Patient record.

{
  • "id": "abababab-abab-4bab-8bab-abababababab",
  • "practice": "99999999-9999-4999-8999-999999999999",
  • "invite_token": "example-synthetic-token-DO-NOT-USE-0123456789",
  • "invite_expires_at": "2026-05-20T00:00:00Z",
  • "status": "approved",
  • "submitted_at": "2026-05-14T10:15:00Z",
  • "reviewed_at": "2026-05-14T11:02:47Z",
  • "reviewed_by": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
  • "patient": "11111111-1111-4111-8111-111111111111",
  • "created": "2026-05-13T12:00:00Z",
  • "submitted_data": {
    },
  • "rejection_reason": ""
}

practice_portal_patient_submissions_approve_create

Approve a patient submission — creates a Patient record.

POST /api/v1/practice//patient-submissions//approve/

Extracts demographics from submitted_data to create the Patient record, links it to the submission, and sets status=approved.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string <uuid>
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json

The server creates a Patient record from submitted_data and sets status=approved, reviewed_by to the current user, and patient to the new record's id.

{
  • "id": "abababab-abab-4bab-8bab-abababababab",
  • "practice": "99999999-9999-4999-8999-999999999999",
  • "invite_token": "example-synthetic-token-DO-NOT-USE-0123456789",
  • "invite_expires_at": "2026-05-20T00:00:00Z",
  • "status": "approved",
  • "submitted_at": "2026-05-14T10:15:00Z",
  • "reviewed_at": "2026-05-14T11:02:47Z",
  • "reviewed_by": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
  • "patient": "11111111-1111-4111-8111-111111111111",
  • "created": "2026-05-13T12:00:00Z",
  • "submitted_data": {
    },
  • "rejection_reason": ""
}

practice_portal_patient_submissions_reject_create

Reject a patient submission with a reason.

POST /api/v1/practice//patient-submissions//reject/

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string <uuid>
practice_uid
required
string <uuid>
Request Body schema:
required
rejection_reason
required
string non-empty

Staff-provided reason for the rejection.

Responses

Request samples

Content type

rejection_reason is required and surfaced to the patient (not stored as PHI).

{
  • "rejection_reason": "Duplicate submission -- patient already has an active record."
}

Response samples

Content type
application/json

Returns the full submission with status=rejected and the reviewer stamped.

{
  • "id": "abababab-abab-4bab-8bab-abababababab",
  • "practice": "99999999-9999-4999-8999-999999999999",
  • "invite_token": "example-synthetic-token-DO-NOT-USE-0123456789",
  • "invite_expires_at": "2026-05-20T00:00:00Z",
  • "status": "rejected",
  • "submitted_at": "2026-05-14T10:15:00Z",
  • "reviewed_at": "2026-05-14T11:02:47Z",
  • "reviewed_by": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
  • "patient": null,
  • "created": "2026-05-13T12:00:00Z",
  • "submitted_data": {
    },
  • "rejection_reason": "Duplicate submission -- patient already has an active record."
}

practice_portal_patient_submissions_invite_create

Generate a one-time invite link for a prospective patient.

POST /api/v1/practice//patient-submissions/invite/

Only Office Manager or above may generate invites. Creates a PatientSubmission with a unique token and 7-day expiry.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json

Front-desk staff copies invite_token into the invite URL (/api/v1/portal/submission/<token>/) and emails or texts it to the prospective patient. Expires after 7 days or on first use, whichever comes first.

{
  • "id": "eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee",
  • "invite_token": "example-synthetic-token-DO-NOT-USE-0123456789",
  • "invite_expires_at": "2026-05-20T00:00:00Z",
  • "created": "2026-05-13T12:00:00Z"
}

Signatures

List signature evidence rows for the practice.

Returns the practice's signature rows in -signed_at order. Compact list shape -- the signed image URL is omitted to keep payloads small; open the detail view to fetch it.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
query Parameters
attached_content_type
string

Filter to signatures attached to a given content type, as "app_label.model" (e.g. "portal.formsubmission").

object_id
string

Filter to signatures attached to a specific object id. Typically combined with attached_content_type.

page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

patient
string <uuid>

Filter to signatures by a specific patient.

signer_type
string

Filter by signer type: patient / staff.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

Capture a digital signature (staff-side, multipart upload).

Accepts a rendered signature PNG plus signer metadata and stores the row as immutable evidence. Body is multipart/form-data with the PNG attached as the image field; the remaining fields ride alongside as standard form fields. Server-managed fields (practice, signed_at, ip_address, user_agent) are populated server-side and any client-supplied values are ignored. Returns the detail shape on 201 so the caller can render or download the just-captured signature without an extra GET.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
signer_type
required
string
Enum: "patient" "staff"

Whether a patient or a staff user signed.

  • patient - Patient
  • staff - Staff
signer_patient
string or null <uuid>

Patient who signed (set when signer_type='patient').

signer_user
string or null <uuid>

Staff user who signed (set when signer_type='staff').

signer_name_typed
required
string [ 1 .. 255 ] characters

Full name the signer typed alongside the signature pad (legal identity claim).

image
required
string <binary>

Rendered signature PNG produced by the signature-pad widget.

image_mime_type
string [ 1 .. 64 ] characters

MIME type of the stored signature image.

attached_content_type
string

ContentType of the attached object as "app_label.model" (e.g. "portal.formsubmission").

object_id
string <= 64 characters

PK of the attached object (generic FK; CharField to accept either UUID or int).

consent_text_snapshot
required
string non-empty

Literal text the signer agreed to, frozen at signing time (non-repudiation).

Responses

Request samples

Content type
No sample

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "signer_type": "patient",
  • "signer_patient": "e2df84cb-0278-4b4c-808c-00db992be652",
  • "patient_first_name": "string",
  • "patient_last_name": "string",
  • "signer_user": "468f6f61-a020-441a-9595-8fee67f9ae9e",
  • "signer_email": "user@example.com",
  • "signer_name_typed": "string",
  • "image_url": "string",
  • "image_mime_type": "string",
  • "attached_content_type": "string",
  • "object_id": "string",
  • "consent_text_snapshot": "string",
  • "signed_at": "2019-08-24T14:15:22Z",
  • "ip_address": "string",
  • "user_agent": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

Read a single signature evidence row (with signed image URL).

Returns the full row, including a short-lived signed URL for the captured image and the consent-text snapshot. Every read fires a signature.viewed audit event so the access trail is complete -- signature images are legal evidence and access must be traced.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
signature_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "practice": "735297b8-a875-445a-9746-8588a75f65f2",
  • "signer_type": "patient",
  • "signer_patient": "e2df84cb-0278-4b4c-808c-00db992be652",
  • "patient_first_name": "string",
  • "patient_last_name": "string",
  • "signer_user": "468f6f61-a020-441a-9595-8fee67f9ae9e",
  • "signer_email": "user@example.com",
  • "signer_name_typed": "string",
  • "image_url": "string",
  • "image_mime_type": "string",
  • "attached_content_type": "string",
  • "object_id": "string",
  • "consent_text_snapshot": "string",
  • "signed_at": "2019-08-24T14:15:22Z",
  • "ip_address": "string",
  • "user_agent": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

Render a standalone PDF preview of a signature row.

Returns a single-page application/pdf containing the captured signature image, the typed signer name, the signed-at timestamp, and the verbatim consent-text snapshot. Useful for letting a practice user eyeball a captured signature before binding it to a final document, and as an appendix the form-generation pipeline can attach to generated paperwork.

Emits a signature.viewed audit event because the rendered PDF contains the same evidence the detail GET exposes -- the access trail must remain complete.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
signature_uid
required
string <uuid>

Responses

Voting

practice_voting_poll_list

CRUD for practice polls with vote, results, and active-count actions.

  • list: All visible polls (unexpired + up to 12h after expiration).
  • create: OFFICE_MANAGER or ADMIN only.
  • retrieve: Any practice member.
  • destroy: Creator or ADMIN only.
  • vote: POST /poll/{id}/vote/ with option_id.
  • results: GET /poll/{id}/results/ (403 if poll not yet expired).
  • active_count: GET /poll/active-count/ for badge display.
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
[
  • {
    }
]

practice_voting_poll_create

CRUD for practice polls with vote, results, and active-count actions.

  • list: All visible polls (unexpired + up to 12h after expiration).
  • create: OFFICE_MANAGER or ADMIN only.
  • retrieve: Any practice member.
  • destroy: Creator or ADMIN only.
  • vote: POST /poll/{id}/vote/ with option_id.
  • results: GET /poll/{id}/results/ (403 if poll not yet expired).
  • active_count: GET /poll/active-count/ for badge display.
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>
Request Body schema:
required
question
required
string [ 1 .. 500 ] characters
is_anonymous
boolean

When true, results show vote counts but not voter identity.

expires_at
required
string <date-time>

UTC timestamp when the poll closes for voting.

required
Array of objects (PollOptionWriteRequest)

Responses

Request samples

Content type
{
  • "question": "string",
  • "is_anonymous": true,
  • "expires_at": "2019-08-24T14:15:22Z",
  • "options": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "question": "string",
  • "is_anonymous": true,
  • "expires_at": "2019-08-24T14:15:22Z",
  • "options": [
    ]
}

practice_voting_poll_retrieve

CRUD for practice polls with vote, results, and active-count actions.

  • list: All visible polls (unexpired + up to 12h after expiration).
  • create: OFFICE_MANAGER or ADMIN only.
  • retrieve: Any practice member.
  • destroy: Creator or ADMIN only.
  • vote: POST /poll/{id}/vote/ with option_id.
  • results: GET /poll/{id}/results/ (403 if poll not yet expired).
  • active_count: GET /poll/active-count/ for badge display.
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "question": "string",
  • "is_anonymous": true,
  • "expires_at": "2019-08-24T14:15:22Z",
  • "is_expired": true,
  • "options": [
    ],
  • "has_voted": "string",
  • "my_vote_option_id": "string",
  • "created_by_name": "string",
  • "created": "2019-08-24T14:15:22Z"
}

practice_voting_poll_destroy

CRUD for practice polls with vote, results, and active-count actions.

  • list: All visible polls (unexpired + up to 12h after expiration).
  • create: OFFICE_MANAGER or ADMIN only.
  • retrieve: Any practice member.
  • destroy: Creator or ADMIN only.
  • vote: POST /poll/{id}/vote/ with option_id.
  • results: GET /poll/{id}/results/ (403 if poll not yet expired).
  • active_count: GET /poll/active-count/ for badge display.
Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_voting_poll_results_retrieve

Return aggregated results. Returns 403 if the poll has not yet expired.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string
practice_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "poll_id": "712230da-d683-493a-8a4d-ca41e4ceb233",
  • "question": "string",
  • "is_anonymous": true,
  • "total_votes": 0,
  • "options": [
    ]
}

practice_voting_poll_vote_create

Cast a vote on this poll. Returns 409 if the user already voted.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
id
required
string
practice_uid
required
string <uuid>
Request Body schema:
required
option_id
required
string <uuid>

Responses

Request samples

Content type
{
  • "option_id": "ab22e710-5ce4-4e7e-a3db-bd6fdad8fe36"
}

Response samples

Content type
application/json
Example
{
  • "detail": "This practice or its parent organization is disabled.",
  • "code": "inactive_practice"
}

practice_voting_poll_active_count_retrieve

Return the count of unexpired polls for the practice (badge display).

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
practice_uid
required
string <uuid>

Responses

Plans

practice_plans_list

List active subscription tiers, cheapest first.

Public-readable: the marketing site renders pricing tiles from this endpoint, so AnonymousUser is allowed. Pagination is disabled because the result set is bounded by the four canonical tiers and the frontend expects a flat array, not a paginated envelope.

Authorizations:
bearerAuthoauth2None

Responses

Response samples

Content type
application/json
[
  • {
    }
]

share

share_retrieve

GET /api/v1/share/<share_uid>/ -- landing-page payload.

Requires a share-session JWT whose per-share audience matches the URL share_uid. Cross-share JWT reuse is rejected by :class:SharePermission with HTTP 403 so the recipient UI can distinguish "not logged in" (401) from "wrong share" (403).

Authorizations:
bearerAuthoauth2
path Parameters
share_uid
required
string <uuid>

Responses

share_download_create

POST /api/v1/share/<share_uid>/download/ -- bundle URL.

Returns {bundle_url, expires_in, status}.

  • status="ready" -- a cached bundle exists and its object is still live in storage. bundle_url is a 15-minute presigned GET URL (DO Spaces in prod, a filesystem path in local-dev).
  • status="pending" -- no matching bundle; a Celery task has been queued to build one. Callers poll this endpoint until the status flips.

On the happy path this endpoint also flips the share to downloaded status and records a bundle_downloaded audit event. The status transition happens on the FIRST successful signed-URL issuance; subsequent polls against the same bundle don't re-flip the status (the model's helper short-circuits) but do emit additional audit events so the download timeline is complete.

.. note:: The bundle generator itself ships in api#174. This endpoint assumes :func:apps.sharing.tasks.generate_bundle returns a Spaces object key on success; if the task is stubbed or failing locally we fall through to a filesystem-backed URL so the recipient at least sees something rather than a confusing 500.

Authorizations:
bearerAuthoauth2
path Parameters
share_uid
required
string <uuid>

Responses

share_import_create

Copy share items into the destination practice (api#175).

Auth: regular staff-session JWT on Authorization AND a share-session JWT on X-Share-Token. The dual-credential requirement is what makes this the "authenticated scope" version of the share JWT: the caller has proven both that they are a known Escape user and that they hold a valid share-session token whose audience matches the share being imported.

Body: see :class:apps.sharing.serializers.ShareImportRequestSerializer.

Per-item transaction: each item is copied inside its own atomic block so a single bad UUID does not roll back the whole batch. The response errors[] array carries a short non-PHI reason code for each failure. The outer request is NOT transactional -- callers get partial success on purpose.

Audit: on success, a single share.imported event is emitted with dest_practice_uid, dest_patient_uid, imported_count. The share row is also transitioned to downloaded via :meth:Share.mark_downloaded so the sender-side My Shares UI shows the correct terminal state.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
share_uid
required
string <uuid>

Responses

share_items_retrieve

Render a single item in the share.

Routing is resource-type aware:

  • Document -> streamed application/pdf (or the original mime if non-PDF).
  • Imaging Exam -> streamed application/dicom (first image of the exam; multi-image bundles go through /download/).
  • Perio Exam / Clinical Note / Patient Summary -> application/json with the same shape as the legacy /items/<type>/<id>/ endpoint so web#158 can consume either.

The item_uid is looked up inside the share -- an item UUID that isn't listed in the share returns 404 rather than 200, even if it exists on the same patient. Combined with the per-share JWT audience check this gives us defence in depth against JWT reuse.

Authorizations:
bearerAuthoauth2
path Parameters
item_uid
required
string <uuid>
share_uid
required
string <uuid>

Responses

share_redeem_authenticated_create

Authenticated redemption -- caller proves staff session AND token.

Uses DRF's default authentication stack so the staff session JWT on Authorization: Bearer ... is validated normally by SimpleJWT. On top of that, the caller must still present a valid share token or Diceware phrase in the body. Both checks must pass; a caller with only a session token sees a 400 (missing body field) rather than a free pass, and a caller with only a token is routed to the guest endpoint by the URL.

The resulting JWT carries scope=authenticated and sub=user:<user_uid> so audit records can link the redemption to the Escape staff user who drove it. The session JWT is not re-embedded -- spec §6 calls for re-issue via the staff session, but the details of that re-issue (e.g. auto-re-mint on JWT expiry from the portal UI) are outside the HTTP surface defined here.

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
token
string [ 1 .. 128 ] characters
phrase
string [ 1 .. 256 ] characters

Responses

Request samples

Content type
{
  • "token": "string",
  • "phrase": "string"
}

Response samples

Content type
application/json
{
  • "token": "string",
  • "phrase": "string"
}

share_redeem_guest_create

Guest redemption -- anyone with a valid token / phrase may call.

No session required. The resulting JWT carries scope=guest and a hashed-IP sub claim so downstream audit records can distinguish guest traffic from authenticated-staff traffic.

Rate limited to 5 per IP per 5 minutes per share_uid prefix via :class:ShareSessionRedeemThrottle; on top of that, 5 consecutive failures trip a 15-minute lockout tracked in the cache.

Authorizations:
bearerAuthoauth2None
Request Body schema:
token
string [ 1 .. 128 ] characters
phrase
string [ 1 .. 256 ] characters

Responses

Request samples

Content type
{
  • "token": "string",
  • "phrase": "string"
}

Response samples

Content type
application/json
{
  • "token": "string",
  • "phrase": "string"
}

support

List inbound import issues (staff-only).

Supports ?status=, ?kind=, ?importer=, ?occurred_from= / ?occurred_to= filters. Ordered by -created (newest first). Returns the compact list shape; open a detail view to read the full context payload.

Authorizations:
jwtAuthbearerAuthoauth2
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

Receive an import-error report from an escape-importer instance.

Accepts a structured failure report (schema_change / data_shape / runtime). Authenticated by a first-party OAuth token carrying import:write scope -- the importer holds this token; the web app and third-party apps cannot reach this endpoint. The request body may carry unredacted PHI in context; rows are PHI-bearing and gated to staff users on the read side.

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
required
importer
required
string [ 1 .. 64 ] characters

Slug of the reporting importer, e.g. 'escape-eaglesoft'.

importer_version
string <= 64 characters

Self-reported version of the importer that raised the issue.

pms
required
string [ 1 .. 32 ] characters

Slug of the upstream practice management system.

pms_version
string <= 64 characters

Self-reported PMS version, when the importer can read it.

practice_uid
string or null <uuid>

Practice UUID the importer was syncing, when established.

client_uid
string or null <uuid>

Client (parent of practice) UUID, when established.

kind
required
string
Enum: "schema_change" "data_shape" "runtime"

Failure class (schema change / data shape / runtime).

  • schema_change - Schema change
  • data_shape - Data shape surprise
  • runtime - Runtime error
occurred_at
required
string <date-time>

Timestamp the importer recorded the error (importer's clock).

summary
required
string [ 1 .. 500 ] characters

One-line description for the inbox list view (PHI-free).

context
any

Structured failure payload (PHI permitted; staff-only on read).

Responses

Request samples

Content type
{
  • "importer": "string",
  • "importer_version": "string",
  • "pms": "string",
  • "pms_version": "string",
  • "practice_uid": "5a13cce7-156f-4a3d-9428-686a502340e4",
  • "client_uid": "b865ed9a-e140-4b8a-85ef-febd691ba840",
  • "kind": "schema_change",
  • "occurred_at": "2019-08-24T14:15:22Z",
  • "summary": "string",
  • "context": null
}

Response samples

Content type
application/json
{
  • "importer": "string",
  • "importer_version": "string",
  • "pms": "string",
  • "pms_version": "string",
  • "practice_uid": "5a13cce7-156f-4a3d-9428-686a502340e4",
  • "client_uid": "b865ed9a-e140-4b8a-85ef-febd691ba840",
  • "kind": "schema_change",
  • "occurred_at": "2019-08-24T14:15:22Z",
  • "summary": "string",
  • "context": null
}

Read a single import issue (staff-only).

Returns the full report including the PHI-bearing context JSON. Staff-only.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
issue_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "importer": "string",
  • "importer_version": "string",
  • "pms": "string",
  • "pms_version": "string",
  • "practice_uid": "5a13cce7-156f-4a3d-9428-686a502340e4",
  • "client_uid": "b865ed9a-e140-4b8a-85ef-febd691ba840",
  • "kind": "schema_change",
  • "occurred_at": "2019-08-24T14:15:22Z",
  • "summary": "string",
  • "context": null,
  • "status": "new",
  • "assigned_to": "b9f52997-ff03-4166-bbff-22fd35e12939",
  • "assigned_to_email": "user@example.com",
  • "resolution_note": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

Update triage state on an import issue (staff-only).

Writable fields: status, assigned_to, resolution_note. Everything else is read-only -- the originating report body is immutable after intake.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
issue_uid
required
string <uuid>
Request Body schema:
status
string
Enum: "new" "triaged" "resolved" "wontfix"

Triage state.

  • new - New
  • triaged - Triaged
  • resolved - Resolved
  • wontfix - Won't fix
assigned_to
string or null <uuid>

Staff user who owns this issue's triage, when assigned.

resolution_note
string

Free-form note set when the issue moves to resolved/wontfix.

Responses

Request samples

Content type
{
  • "status": "new",
  • "assigned_to": "b9f52997-ff03-4166-bbff-22fd35e12939",
  • "resolution_note": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "importer": "string",
  • "importer_version": "string",
  • "pms": "string",
  • "pms_version": "string",
  • "practice_uid": "5a13cce7-156f-4a3d-9428-686a502340e4",
  • "client_uid": "b865ed9a-e140-4b8a-85ef-febd691ba840",
  • "kind": "schema_change",
  • "occurred_at": "2019-08-24T14:15:22Z",
  • "summary": "string",
  • "context": null,
  • "status": "new",
  • "assigned_to": "b9f52997-ff03-4166-bbff-22fd35e12939",
  • "assigned_to_email": "user@example.com",
  • "resolution_note": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z"
}

Support

List support sessions (audit log). Support-staff only.

GET lists past sessions (filterable); POST mints a new one.

Both methods are restricted to support staff (:class:apps.support.permissions.IsSupportStaff) -- the audit list exposes the inverse side of the redemption surface and so inherits the same gate.

Authorizations:
jwtAuthbearerAuthoauth2
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{
  • "count": 123,
  • "results": [
    ]
}

Mint a support code + subscriber token. Support-staff only.

Mint a :class:SupportSession row + subscriber token.

The row, the audit event, and the token mint are committed together inside an explicit transaction.atomic() block -- a partial commit on a LiveKit-config failure would leave dangling sessions for which no token was ever issued. The atomic block re-raises :class:LiveKitNotConfigured, which triggers a clean rollback; the outer try catches it after the rollback has run and surfaces the 503 response.

Authorizations:
jwtAuthbearerAuthoauth2

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "status": "string",
  • "code": "string",
  • "code_expires_at": "2019-08-24T14:15:22Z",
  • "livekit_url": "string",
  • "livekit_token": "string",
  • "livekit_room": "string",
  • "token_expires_at": 0
}

End a support session. Either party may call.

End an active session. Idempotent on already-ended rows.

Either the originating tech or the redeeming user may call; any other authenticated user gets 403. The endpoint deliberately does not let an arbitrary support-staff member end someone else's session -- the audit story is cleaner if the actor is one of the two participants.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
session_id
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "status": "string",
  • "ended_at": "2019-08-24T14:15:22Z"
}

Redeem a support code. Any authenticated user.

Validate the code, mark redeemed, mint publisher token.

The endpoint runs two distinct transactions:

  1. An "expired-or-bust" atomic block that picks up the row, checks the TTL, and -- if expired -- commits the EXPIRED transition + audit event before raising :class:ValidationError. Without the split, a single outer atomic would roll back the EXPIRED save when the ValidationError propagates out, and the row would stay stuck in PENDING for the next reader.

  2. A "redeem-or-bust" atomic block that flips the row to ACTIVE, mints the publisher token, and emits the REDEEMED audit event. On :class:LiveKitNotConfigured the block rolls back so the user does not end up associated with a session it cannot connect to.

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
required
code
required
string [ 1 .. 32 ] characters

Responses

Request samples

Content type
{
  • "code": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "status": "string",
  • "livekit_url": "string",
  • "livekit_token": "string",
  • "livekit_room": "string",
  • "token_expires_at": 0
}

webhooks

webhooks_subscriptions_list

List and create webhook subscriptions.

GET — returns all subscriptions owned by the authenticated user's OAuth applications. POST — creates a new subscription (URL must pass validation, events must be known).

Authorizations:
jwtAuthbearerAuthoauth2

Responses

Response samples

Content type
application/json
[
  • {
    }
]

webhooks_subscriptions_create

List and create webhook subscriptions.

GET — returns all subscriptions owned by the authenticated user's OAuth applications. POST — creates a new subscription (URL must pass validation, events must be known).

Authorizations:
jwtAuthbearerAuthoauth2
Request Body schema:
required
application
required
integer
client
required
string <uuid>
target_url
required
string <uri> [ 1 .. 2048 ] characters
events
any

List of event patterns, e.g. ['patient.created', 'appointment.*']

all_practices
boolean

Subscribe to events across all practices, or select specific ones

practices
Array of strings <uuid> [ items <uuid > ]

Specific practices (when all_practices=False)

custom_data
any

Responses

Request samples

Content type
{
  • "application": 0,
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "target_url": "http://example.com",
  • "events": null,
  • "all_practices": true,
  • "practices": [
    ],
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "application": 0,
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "target_url": "http://example.com",
  • "events": null,
  • "all_practices": true,
  • "practices": [
    ],
  • "custom_data": null
}

webhooks_subscriptions_retrieve

Retrieve, update, or delete a single webhook subscription.

Scoped to subscriptions owned by the authenticated user's OAuth applications.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
subscription_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "application": 0,
  • "application_name": "string",
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "client_name": "string",
  • "target_url": "http://example.com",
  • "events": null,
  • "all_practices": true,
  • "practices": [
    ],
  • "is_active": true,
  • "is_verified": true,
  • "consecutive_failures": 0,
  • "last_failure_at": "2019-08-24T14:15:22Z",
  • "disabled_reason": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "modified": "2019-08-24T14:15:22Z",
  • "custom_data": null
}

webhooks_subscriptions_update

Retrieve, update, or delete a single webhook subscription.

Scoped to subscriptions owned by the authenticated user's OAuth applications.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
subscription_uid
required
string <uuid>
Request Body schema:
required
application
required
integer
client
required
string <uuid>
target_url
required
string <uri> [ 1 .. 2048 ] characters
events
any

List of event patterns, e.g. ['patient.created', 'appointment.*']

all_practices
boolean

Subscribe to events across all practices, or select specific ones

practices
Array of strings <uuid> [ items <uuid > ]

Specific practices (when all_practices=False)

custom_data
any

Responses

Request samples

Content type
{
  • "application": 0,
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "target_url": "http://example.com",
  • "events": null,
  • "all_practices": true,
  • "practices": [
    ],
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "application": 0,
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "target_url": "http://example.com",
  • "events": null,
  • "all_practices": true,
  • "practices": [
    ],
  • "custom_data": null
}

webhooks_subscriptions_partial_update

Retrieve, update, or delete a single webhook subscription.

Scoped to subscriptions owned by the authenticated user's OAuth applications.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
subscription_uid
required
string <uuid>
Request Body schema:
application
integer
client
string <uuid>
target_url
string <uri> [ 1 .. 2048 ] characters
events
any

List of event patterns, e.g. ['patient.created', 'appointment.*']

all_practices
boolean

Subscribe to events across all practices, or select specific ones

practices
Array of strings <uuid> [ items <uuid > ]

Specific practices (when all_practices=False)

custom_data
any

Responses

Request samples

Content type
{
  • "application": 0,
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "target_url": "http://example.com",
  • "events": null,
  • "all_practices": true,
  • "practices": [
    ],
  • "custom_data": null
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "application": 0,
  • "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
  • "target_url": "http://example.com",
  • "events": null,
  • "all_practices": true,
  • "practices": [
    ],
  • "custom_data": null
}

webhooks_subscriptions_destroy

Retrieve, update, or delete a single webhook subscription.

Scoped to subscriptions owned by the authenticated user's OAuth applications.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
subscription_uid
required
string <uuid>

Responses

webhooks_subscriptions_deliveries_list

List delivery logs for a specific subscription.

Paginated (50 per page) and scoped to subscriptions owned by the authenticated user's OAuth applications.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
subscription_uid
required
string <uuid>
query Parameters
page
integer

A page number within the paginated result set.

page_size
integer

Number of results to return per page.

Responses

Response samples

Content type
application/json
{}

xrays

xrays_sessions_retrieve

Get capture session status for crash recovery.

Returns session state, image count, and template info.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
session_uid
required
string <uuid>

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "status": "pending",
  • "exam": "76d06126-4ce7-4fb4-98c2-d484d7e9ee38",
  • "template": "060ce75e-87d6-4677-b330-eaee58e54138",
  • "template_name": "string",
  • "workstation_name": "string",
  • "image_count": "string",
  • "created": "2019-08-24T14:15:22Z"
}

xrays_sessions_images_create

Upload a single dental image to a capture session.

Called by the desktop app after each image is captured via TWAIN/WIA.

Authorizations:
jwtAuthbearerAuthoauth2
path Parameters
session_uid
required
string <uuid>
Request Body schema:
required
file
required
string <binary>
template_slot
string or null <uuid>

Which slot in the exam template grid this image fills

ImageTypeEnum (string) or BlankEnum (any)
capture_device
string <= 255 characters

Device name from browser getUserMedia

tooth_numbers
any

Universal numbering: 1-32 permanent, A-T primary

description
string <= 255 characters

Short description/label for the image

notes
string

Responses

Response samples

Content type
application/json
{
  • "template_slot": "a8f6b7f7-6b3b-48c7-a4e4-e20bd837e2e6",
  • "image_type": "pa",
  • "capture_device": "string",
  • "tooth_numbers": null,
  • "description": "string",
  • "notes": "string"
}