Escape Dental API (1.0.0)
Download OpenAPI specification:Download
Practice management platform API for Escape Dental.
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). TheStatus.BROKENchoice is labelledBroken/No-Showin 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 ofbrokenappointments for the patient scoped to this practice (ignores other practices).patient_phone-- patient's best reach-out number (phone_mobilepreferred, thenphone_home, thenphone_work).patient_outstanding_balance-- the patient's current aged receivables snapshot (Patient.balance_current).cancel_reason-- the appointment'scancellation_reasonif set.
These fields are null on rows that are not no-shows, keeping the
payload lean for normal schedule queries.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| from | string <date> Examples:
Inclusive lower bound on |
| no_show_between | string Examples:
Shortcut for the No-show report: two ISO dates separated by a comma ( |
| page | integer 1-indexed page number. Pagination is keyed by |
| 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 |
| patient | integer Filter by patient integer PK. Combine with |
| 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):
|
| to | string <date> Examples:
Inclusive upper bound on |
Responses
Response samples
- 200
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": [
- {
- "count": 3,
- "next": null,
- "previous": null,
- "results": [
- {
- "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": [
- {
- "id": 1001,
- "procedure_code": null,
- "proc_code": "D2740",
- "description": "Crown - porcelain/ceramic substrate",
- "fee": "1150.00",
- "tooth_num": "14",
- "surface": "",
- "status": "planned",
- "custom_data": { }
}
], - "custom_data": { }
}, - {
- "id": "66666666-6666-4666-8666-666666666666",
- "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-14T10:30:00-07:00",
- "duration_minutes": 45,
- "status": "scheduled",
- "confirmed_status": "confirmed",
- "appointment_type": "Recall / Prophy",
- "is_hygiene": true,
- "is_new_patient": false,
- "procedure_description": "D1110 Prophylaxis - adult",
- "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, John",
- "provider_name": "Synthetic, Dr. Dana",
- "provider_hygienist_name": "Synthetic, Hollis",
- "scheduled_procedures": [
- {
- "id": 1002,
- "procedure_code": null,
- "proc_code": "D1110",
- "description": "Prophylaxis - adult",
- "fee": "110.00",
- "tooth_num": "",
- "surface": "",
- "status": "planned",
- "custom_data": { }
}
], - "custom_data": { }
}, - {
- "id": "77777777-7777-4777-8777-777777777777",
- "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-15T14:00:00-07:00",
- "duration_minutes": 90,
- "status": "scheduled",
- "confirmed_status": "not_called",
- "appointment_type": "New Patient Exam",
- "is_hygiene": false,
- "is_new_patient": true,
- "procedure_description": "D0150 Comprehensive oral evaluation",
- "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, Alex",
- "provider_name": "Synthetic, Dr. Dana",
- "provider_hygienist_name": "Synthetic, Hollis",
- "scheduled_procedures": [
- {
- "id": 1003,
- "procedure_code": null,
- "proc_code": "D0150",
- "description": "Comprehensive oral evaluation",
- "fee": "95.00",
- "tooth_num": "",
- "surface": "",
- "status": "planned",
- "custom_data": { }
}
], - "custom_data": { }
}
]
}
]
}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). TheStatus.BROKENchoice is labelledBroken/No-Showin 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 ofbrokenappointments for the patient scoped to this practice (ignores other practices).patient_phone-- patient's best reach-out number (phone_mobilepreferred, thenphone_home, thenphone_work).patient_outstanding_balance-- the patient's current aged receivables snapshot (Patient.balance_current).cancel_reason-- the appointment'scancellation_reasonif set.
These fields are null on rows that are not no-shows, keeping the
payload lean for normal schedule queries.
Authorizations:
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"
|
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
- Payload
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": [
- {
- "proc_code": "D2740",
- "description": "Crown - porcelain/ceramic substrate",
- "fee": "1150.00",
- "tooth_num": "14"
}
]
}Response samples
- 201
- 403
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": [
- {
- "id": 1001,
- "procedure_code": null,
- "proc_code": "D2740",
- "description": "Crown - porcelain/ceramic substrate",
- "fee": "1150.00",
- "tooth_num": "14",
- "surface": "",
- "status": "planned",
- "custom_data": { }
}
], - "custom_data": { }
}practice_scheduling_appointment_bulk_partial_update
Handle PATCH on the list endpoint for bulk updates.
Authorizations:
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
- Payload
{- "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
- 200
- 403
{- "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": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "proc_code": "string",
- "description": "string",
- "fee": "string",
- "tooth_num": "string",
- "surface": "string",
- "status": "planned",
- "custom_data": null
}
], - "custom_data": null
}practice_scheduling_appointment_status_list
Read-only list of appointment status metadata.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
[- {
- "slug": "string",
- "label": "string",
- "color": "string",
- "is_visible": true,
- "blocks_slot": true,
- "sort_order": 0
}
]practice_scheduling_appointment_status_retrieve
Read-only list of appointment status metadata.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
| slug required | string A unique value identifying this appointment status. |
Responses
Response samples
- 200
{- "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:
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"
|
Responses
Request samples
- Payload
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
- 200
- 403
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": [
- {
- "id": 1001,
- "procedure_code": null,
- "proc_code": "D2740",
- "description": "Crown - porcelain/ceramic substrate",
- "fee": "1150.00",
- "tooth_num": "14",
- "surface": "",
- "status": "planned",
- "custom_data": { }
}
], - "custom_data": { }
}practice_scheduling_appointment_history_list
Return the status transition history for an appointment.
Authorizations:
path Parameters
| appointment_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
One entry per transition, oldest first. changed_by is null for automated transitions (e.g. system auto-marking broken appointments overnight).
[- [
- {
- "id": 1,
- "previous_status": "scheduled",
- "new_status": "arrived",
- "changed_by": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
- "changed_by_name": "Dana Synthetic",
- "changed_at": "2026-05-14T16:00:12Z",
- "note": "Checked in at front desk.",
- "custom_data": { }
}, - {
- "id": 2,
- "previous_status": "arrived",
- "new_status": "seated",
- "changed_by": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
- "changed_by_name": "Dana Synthetic",
- "changed_at": "2026-05-14T16:05:48Z",
- "note": "",
- "custom_data": { }
}
]
]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:
path Parameters
| appointment_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "appointment": {
- "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": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "proc_code": "string",
- "description": "string",
- "fee": "string",
- "tooth_num": "string",
- "surface": "string",
- "status": "planned",
- "custom_data": null
}
], - "custom_data": null
}, - "patient": {
- "uid": "string",
- "name": "string",
- "dob": "2019-08-24",
- "chart_number": "string",
- "phone": "string",
- "medical_alerts": [
- "string"
]
}, - "procedures": [
- {
- "cdt_code": "string",
- "description": "string",
- "fee": "string",
- "tooth": "string"
}
], - "insurance": {
- "primary_carrier": "string",
- "primary_plan": "string",
- "member_id": "string",
- "group_id": "string"
}, - "provider": {
- "name": "string",
- "initials": "string"
}, - "operatory": {
- "name": "string",
- "abbreviation": "string"
}
}practice_scheduling_appointment_transition_create
Transition an appointment to a new status with validation and audit logging.
POST {"status": "complete", "note": "optional reason"}
Authorizations:
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"
|
| note | string Default: "" |
Responses
Request samples
- Payload
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
- 200
- 403
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": [
- {
- "id": 1001,
- "procedure_code": null,
- "proc_code": "D2740",
- "description": "Crown - porcelain/ceramic substrate",
- "fee": "1150.00",
- "tooth_num": "14",
- "surface": "",
- "status": "planned",
- "custom_data": { }
}
], - "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:
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;arrivedis lobby-only,completesetsdismissed_at). dismissed_at IS NULLas 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 —
OperatoryPresencetracks staff occupancy, not patients). Theappointment_idfield 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:
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
- 200
{- "date": "string",
- "operatories": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "abbreviation": "string",
- "is_hygiene": true,
- "provider_dentist": {
- "property1": null,
- "property2": null
}, - "provider_hygienist": {
- "property1": null,
- "property2": null
}, - "in_chair_patient": {
- "patient_id": "3854866a-5476-48be-8313-77029ccdd7a7",
- "patient_name": "string",
- "appointment_id": "21634f0d-2156-4d4b-a142-2e7c783a9212",
- "since": "2019-08-24T14:15:22Z"
}
}
], - "blocks": [
- {
- "property1": null,
- "property2": null
}
], - "appointments": [
- {
- "property1": null,
- "property2": null
}
]
}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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| availability_windows | Array of strings Disjoint availability windows. Each value is |
| days_of_week | string Legacy single-window shorthand: comma-separated weekday ints (0=Mon..6=Sun). Mutually exclusive with |
| duration_minutes required | integer Required duration |
| earliest_time | string Legacy single-window shorthand: earliest start time (HH:MM). Mutually exclusive with |
| 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 |
| 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-01stays on that date regardless of the server's wall clock. appointment_countandproductionboth exclude appointments whose status iscancelledorbroken, matching the client-side filter the web app used to apply.productionsumsAppointmentProcedure.feefor 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/toare 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:
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
- 200
{- "from": "2019-08-24",
- "to": "2019-08-24",
- "days": {
- "property1": {
- "appointment_count": 0,
- "production": "string"
}, - "property2": {
- "appointment_count": 0,
- "production": "string"
}
}
}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:
dateis 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
cancelledorbroken(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/closeare 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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| date required | string <date> Examples:
Target date ( |
Responses
Response samples
- 200
{- "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:
path Parameters
| operatory_id required | string <uuid> |
| practice_uid required | string <uuid> |
Request Body schema: required
| patient required | string <uuid> |
Responses
Request samples
- Payload
{- "patient": "a7129932-7174-432d-a8dd-570510e145bb"
}Response samples
- 201
- 403
{- "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:
path Parameters
| operatory_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| due_after | string <date> Examples:
Inclusive lower bound on |
| due_before | string <date> Examples:
Inclusive upper bound on |
| is_disabled | string Enum: "false" "true" Filter by disabled status. Accepts |
| 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:
Filter by recall type slug. The field is free-form ( |
| unscheduled | string Enum: "false" "true" Filter to recalls whose |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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_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:
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
- Payload
{- "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
- 201
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Request Body schema:
| custom_data | any |
Responses
Request samples
- Payload
{- "custom_data": null
}Response samples
- 200
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "results": [
- "string"
]
}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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| cancelled_between | string Two ISO dates separated by a comma ( |
| from | string <date> Inclusive start date (YYYY-MM-DD, practice TZ). Ignored when |
| to | string <date> Inclusive end date (YYYY-MM-DD, practice TZ). Ignored when |
Responses
Response samples
- 200
{- "results": [
- {
- "id": "string",
- "cancelled_at": "2019-08-24T14:15:22Z",
- "scheduled_start": "2019-08-24T14:15:22Z",
- "lead_time_hours": "string",
- "patient_id": "string",
- "patient_name": "string",
- "provider_name": "string",
- "operatory_name": "string",
- "procedure_description": "string",
- "cancel_reason": "string",
- "cancelled_by_id": "string",
- "cancelled_by_name": "string",
- "rebooked": true,
- "rebook_appointment_id": "string",
- "rebook_date": "2019-08-24",
- "rebook_lag_days": 0,
- "scheduled_production": "string"
}
]
}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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| from required | string <date> Inclusive start date in the practice's local timezone (ISO 8601 |
| granularity | string Enum: "day" "month" "week" Bucket size: |
| provider | Array of strings Restrict the report to specific providers. Repeat the parameter for a multi-select filter, e.g. |
| to required | string <date> Inclusive end date in the practice's local timezone (ISO 8601 |
Responses
Response samples
- 200
{- "results": [
- {
- "provider_id": "string",
- "provider_name": "string",
- "bucket_start": "2019-08-24",
- "bucket_end": "2019-08-24",
- "template_hours": "string",
- "blocked_hours": "string",
- "available_hours": "string",
- "scheduled_hours": "string",
- "open_hours": "string",
- "utilization_pct": "string",
- "appointment_count": 0,
- "production_scheduled": "string",
- "production_completed": "string"
}
]
}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:
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
- 200
{- "date": "string",
- "date_from": "string",
- "date_to": "string",
- "blocks": [
- {
- "property1": null,
- "property2": null
}
], - "schedule": {
- "property1": [
- {
- "property1": null,
- "property2": null
}
], - "property2": [
- {
- "property1": null,
- "property2": null
}
]
}
}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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| date_from | string <date> Examples:
Inclusive lower bound on |
| date_to | string <date> Examples:
Inclusive upper bound on |
| 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. |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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_create
List and create date-specific schedule overrides.
Supports filtering by provider, date_from/date_to range, and schedule_type.
Authorizations:
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"
|
| blockout_type | string <= 50 characters e.g. lunch, meeting, holiday, time_off |
| operatory | string or null <uuid> |
| status | string (ScheduleOverrideStatusEnum) Enum: "open" "closed" "holiday"
|
| note | string |
| custom_data | any |
Responses
Request samples
- Payload
{- "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
- 201
- 403
{- "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:
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 |
| 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 | string Enum: "blockout" "office_hours" "provider" Filter by template kind. |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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_create
List and create recurring schedule templates.
Supports filtering by provider, day_of_week, and schedule_type.
Authorizations:
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"
|
| blockout_type | string <= 50 characters e.g. lunch, meeting, admin |
| operatory | string or null <uuid> |
| is_active | boolean |
| custom_data | any |
Responses
Request samples
- Payload
{- "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
- 201
- 403
{- "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_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:
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
- Payload
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
- 200
- 403
Safe to book — no conflicts, no warnings.
{- "valid": true,
- "issues": [ ]
}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:
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 ( |
Responses
Request samples
- Payload
{- "last_name": "string",
- "date_of_birth": "2019-08-24"
}Response samples
- 200
- 403
{- "patient": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "first_name": "string",
- "last_name": "string",
- "date_of_birth": "2019-08-24",
- "phone_mobile": "string"
}, - "appointment": {
- "property1": null,
- "property2": null
}
}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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| as_of | string <date> Reference date for the |
| first_visit_date_from | string <date> Include only patients whose first completed visit (earliest |
| first_visit_date_to | string <date> Include only patients whose first completed visit is on or before this date (inclusive). Combine with |
| 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 ( |
| has_future_appointment | boolean When |
| include | string Comma-separated list of optional serializer field groups to include on every row. Supported values: |
| 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: |
| 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 |
| provider | Array of strings <uuid> [ items <uuid > ] Filter by provider UUID. May be repeated ( |
| search | string Case-insensitive substring search. Single-token queries fan out across |
| status | string Enum: "active" "archived" "deceased" "inactive" "prospective" Filter by patient status. |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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_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:
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 |
string <email> <= 254 characters | |
| date_of_birth | string or null <date> |
| gender | string (GenderEnum) Enum: "male" "female" "other" "unknown"
|
| status | string (PatientStatusEnum) Enum: "active" "inactive" "archived" "deceased" "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
- Payload
{- "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
- 201
- 403
{- "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:
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 |
string <email> <= 254 characters | |
| date_of_birth | string or null <date> |
| gender | string (GenderEnum) Enum: "male" "female" "other" "unknown"
|
| status | string (PatientStatusEnum) Enum: "active" "inactive" "archived" "deceased" "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
- Payload
{- "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
- 200
- 403
{- "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:
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 |
string <email> <= 254 characters | |
| npi | string <= 20 characters |
| is_doctor | boolean |
| custom_data | any |
Responses
Request samples
- Payload
{- "first_name": "string",
- "last_name": "string",
- "specialty": "string",
- "phone": "string",
- "email": "user@example.com",
- "npi": "string",
- "is_doctor": true,
- "custom_data": null
}Response samples
- 200
- 403
{- "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"
}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:
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 |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "body": "string",
- "category": "string",
- "prompts": [
- {
- "property1": null,
- "property2": null
}
], - "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "custom_data": null
}
]
}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:
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
- Payload
{- "name": "string",
- "body": "string",
- "category": "string",
- "prompts": [
- {
- "property1": null,
- "property2": null
}
], - "custom_data": null
}Response samples
- 200
- 201
- 403
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "body": "string",
- "category": "string",
- "prompts": [
- {
- "property1": null,
- "property2": null
}
], - "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:
path Parameters
| auto_note_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "body": "string",
- "category": "string",
- "prompts": [
- {
- "property1": null,
- "property2": null
}
], - "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:
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
- Payload
{- "name": "string",
- "body": "string",
- "category": "string",
- "prompts": [
- {
- "property1": null,
- "property2": null
}
], - "custom_data": null
}Response samples
- 200
- 403
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "body": "string",
- "category": "string",
- "prompts": [
- {
- "property1": null,
- "property2": null
}
], - "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:
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
- Payload
{- "name": "string",
- "body": "string",
- "category": "string",
- "prompts": [
- {
- "property1": null,
- "property2": null
}
], - "custom_data": null
}Response samples
- 200
- 403
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "body": "string",
- "category": "string",
- "prompts": [
- {
- "property1": null,
- "property2": null
}
], - "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:
path Parameters
| auto_note_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| active | string Enum: "false" "true" Filter by active status. Accepts |
| 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
- 200
{- "count": 123,
- "results": [
- {
- "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_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:
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
- Payload
{- "name": "string",
- "category": "exam",
- "content": "string",
- "is_active": true,
- "sort_order": 2147483647,
- "custom_data": null
}Response samples
- 201
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| date_from | string <date> Inclusive lower bound on |
| date_to | string <date> Inclusive upper bound on |
| 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 |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "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_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:
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
- Payload
{- "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
- 201
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| active | string Enum: "false" "true" Filter by active status. Accepts |
| 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 |
| 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
- 200
{- "count": 123,
- "results": [
- {
- "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_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:
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
- Payload
{- "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
- 201
- 403
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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/
Checks if the patient has any completed D4341/D4342 (SRP) procedures. If yes, suggests D4910 (perio maintenance) instead of D1110 (prophylaxis).
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| query | string Search query for procedure code suggestions |
Responses
practice_patient_clinical_anesthesia_list
List and create anesthesia records for a patient.
Supports filtering by appointment and date range.
Authorizations:
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 |
| date_to | string <date> Inclusive upper bound on |
| page | integer A page number within the paginated result set. |
| page_size | integer Number of results to return per page. |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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_create
List and create anesthesia records for a patient.
Supports filtering by appointment and date range.
Authorizations:
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"
|
| agent_other | string <= 100 characters If agent=other, specify here |
| route | string (RouteEnum) Enum: "infiltration" "block" "topical" "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
- Payload
{- "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
- 201
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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 |
| date_to | string <date> Inclusive upper bound on |
| 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
- 200
{- "count": 123,
- "results": [
- {
- "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_create
List and create patient education records for a patient.
Supports filtering by appointment, topic, and date range.
Authorizations:
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"
|
| 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
- Payload
{- "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
- 201
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
query Parameters
| date_from | string <date> Inclusive lower bound on |
| date_to | string <date> Inclusive upper bound on |
| 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 |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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_create
List and create clinical notes for a patient.
Supports filtering by note_type, provider, date range, and free-text search.
Authorizations:
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"
|
| 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
- Payload
{- "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
- 201
- 403
{- "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:
path Parameters
| note_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| perio_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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=
Authorizations:
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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
query Parameters
| date_from | string <date> Inclusive lower bound on |
| date_to | string <date> Inclusive upper bound on |
| 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 |
| status | string Enum: "complete" "existing_current" "existing_other" Filter by procedure status. Common values are |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "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_create
List and create procedures for a patient.
Supports filtering by provider, date range, status, and free-text search.
Authorizations:
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
- Payload
{- "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
- 201
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Request Body schema:
| custom_data | any |
Responses
Request samples
- Payload
{- "custom_data": null
}Response samples
- 200
- 403
{- "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": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "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:
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:
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 |
| 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. |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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_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:
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"
|
| dentition | string (DentitionEnum) Enum: "permanent" "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
- Payload
{- "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
- 201
- 403
{- "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:
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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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": [
- {
- "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
}
], - "item_count": 0,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "custom_data": null
}
]
}practice_patient_clinical_treatment_plan_create
List and create treatment plans for a patient.
Supports filtering by status.
Authorizations:
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"
|
| date_accepted | string or null <date> |
| custom_data | any |
Array of objects (TreatmentPlanItemWriteRequest) |
Responses
Request samples
- Payload
{- "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
- "name": "string",
- "note": "string",
- "status": "active",
- "date_accepted": "2019-08-24",
- "custom_data": null,
- "items": [
- {
- "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",
- "est_primary_ins": "string",
- "est_secondary_ins": "string",
- "plan_name": "string",
- "priority": 2147483647,
- "custom_data": null
}
]
}Response samples
- 201
- 403
{- "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
- "name": "string",
- "note": "string",
- "status": "active",
- "date_accepted": "2019-08-24",
- "custom_data": null,
- "items": [
- {
- "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",
- "est_primary_ins": "string",
- "est_secondary_ins": "string",
- "plan_name": "string",
- "priority": 2147483647,
- "custom_data": null
}
]
}practice_patient_clinical_treatment_plan_accept_create
Accept a treatment plan. Sets status=accepted and date_accepted=today.
Authorizations:
path Parameters
| patient_id required | string <uuid> |
| plan_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| plan_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| plan_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| plan_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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 |
| date_to | string <date> Inclusive upper bound on |
| page | integer A page number within the paginated result set. |
| page_size | integer Number of results to return per page. |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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_create
List and create vital sign readings for a patient.
Supports filtering by appointment and date range. Ordered by most recent reading first.
Authorizations:
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
- Payload
{- "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
- 201
- 403
{- "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_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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| active | string Value: "true" Filter by active status. Only |
| 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 |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "phone": "string",
- "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_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:
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
- Payload
{- "name": "string",
- "phone": "string",
- "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
- 201
- 403
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "phone": "string",
- "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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| date_from | string <date> Inclusive lower bound on |
| date_to | string <date> Inclusive upper bound on |
| 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 |
| 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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "procedures": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "procedure_code": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "proc_code": "string",
- "fee_billed": "string",
- "ins_pay_est": "string",
- "ins_pay_amt": "string",
- "ded_applied": "string",
- "write_off": "string",
- "status": "string",
- "proc_date": "2019-08-24",
- "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
- "modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f",
- "practice": "735297b8-a875-445a-9746-8588a75f65f2",
- "claim": "7e60fd1d-575d-4043-a73d-5a2fe9049027",
- "patient": "a7129932-7174-432d-a8dd-570510e145bb",
- "procedure": "d851bde4-b989-444b-aa77-4e67fb9f8d2c"
}
], - "status_log": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "claim": "7e60fd1d-575d-4043-a73d-5a2fe9049027",
- "from_status": "string",
- "to_status": "string",
- "changed_by": "3e89c7a5-3fa2-4d93-b1c0-5c0519bb2681",
- "changed_by_email": "string",
- "changed_at": "2019-08-24T14:15:22Z",
- "note": "string",
- "custom_data": null
}
], - "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_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/
Authorizations:
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:
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 |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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",
- "entry_count": 0,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "custom_data": null
}
]
}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:
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
- Payload
{- "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
- 201
- 403
{- "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": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "proc_code": "string",
- "allowed_amount": "string",
- "description": "string",
- "custom_data": null
}
], - "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:
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
- Payload
{- "proc_code": "string",
- "allowed_amount": "string",
- "description": "string",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
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. |
| 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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "benefits": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "procedure_code": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "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"
}
], - "carrier_detail": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "phone": "string",
- "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
}, - "plan_detail": {
- "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",
- "is_active": true,
- "enrollment_count": 0,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "custom_data": null
}, - "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_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:
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
- Payload
{- "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
- 201
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| active | string Value: "true" Filter by active status. Only |
| 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 |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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",
- "is_active": true,
- "enrollment_count": 0,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "custom_data": null
}
]
}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:
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
- Payload
{- "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": [
- {
- "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
}
], - "custom_data": null
}Response samples
- 201
- 403
{- "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": [
- {
- "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
}
], - "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:
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
- Payload
{- "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": [
- {
- "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
}
], - "custom_data": null
}Response samples
- 200
- 403
{- "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": [
- {
- "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
}
], - "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "procedure_code": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "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_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:
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
- Payload
{- "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
- 201
- 403
{- "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-- UUIDinsurance_plan-- UUIDverified_between--from,toISO 8601 datetimes (inclusive)
Emits insurance.verification_viewed on GET and
insurance.verification_created on POST.
Authorizations:
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 |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "plan_name": "string",
- "group_number": "string",
- "carrier_name": "string"
}, - "patient_summary": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "initials": "string"
}, - "verified_by_summary": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "display_name": "string"
}, - "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z"
}
]
}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:
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"
|
| 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
- Payload
{- "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
- 201
- 403
{- "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": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "plan_name": "string",
- "group_number": "string",
- "carrier_name": "string"
}, - "patient_summary": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "initials": "string"
}, - "verified_by_summary": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "display_name": "string"
}, - "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "procedures": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "procedure_code": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "proc_code": "string",
- "fee_billed": "string",
- "ins_pay_est": "string",
- "ins_pay_amt": "string",
- "ded_applied": "string",
- "write_off": "string",
- "status": "string",
- "proc_date": "2019-08-24",
- "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
- "modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f",
- "practice": "735297b8-a875-445a-9746-8588a75f65f2",
- "claim": "7e60fd1d-575d-4043-a73d-5a2fe9049027",
- "patient": "a7129932-7174-432d-a8dd-570510e145bb",
- "procedure": "d851bde4-b989-444b-aa77-4e67fb9f8d2c"
}
], - "status_log": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "claim": "7e60fd1d-575d-4043-a73d-5a2fe9049027",
- "from_status": "string",
- "to_status": "string",
- "changed_by": "3e89c7a5-3fa2-4d93-b1c0-5c0519bb2681",
- "changed_by_email": "string",
- "changed_at": "2019-08-24T14:15:22Z",
- "note": "string",
- "custom_data": null
}
], - "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_create
Insurance claims for a patient. POST to create a new claim in draft status.
Authorizations:
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
- Payload
{- "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": [
- {
- "procedure": "d851bde4-b989-444b-aa77-4e67fb9f8d2c",
- "proc_code": "string",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "fee_billed": "string",
- "ins_pay_est": "string",
- "ded_applied": "string",
- "write_off": "string",
- "custom_data": null
}
], - "custom_data": null
}Response samples
- 201
- 403
{- "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": [
- {
- "procedure": "d851bde4-b989-444b-aa77-4e67fb9f8d2c",
- "proc_code": "string",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "fee_billed": "string",
- "ins_pay_est": "string",
- "ded_applied": "string",
- "write_off": "string",
- "custom_data": null
}
], - "custom_data": null
}practice_patient_insurance_claim_transition_create
Transition a claim's status through the state machine.
POST /practice/
Authorizations:
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"
|
| note | string Default: "" |
Responses
Request samples
- Payload
{- "new_status": "draft",
- "note": ""
}Response samples
- 200
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "benefits": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "procedure_code": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "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"
}
], - "carrier_detail": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "phone": "string",
- "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
}, - "plan_detail": {
- "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",
- "is_active": true,
- "enrollment_count": 0,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "custom_data": null
}, - "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_create
List and create insurance plans for a patient.
Authorizations:
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
- Payload
{- "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
- 201
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "procedure_code": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "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_create
List and create benefits for a patient insurance plan.
Authorizations:
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
- Payload
{- "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
- 201
- 403
{- "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
}client_billing_portal_session_create
Mint a Stripe-hosted billing portal session for the caller's Client.
POST /api/v1/client/
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:
path Parameters
| client_uid required | string <uuid> |
Request Body schema:
| return_url | string <uri> non-empty |
Responses
Request samples
- Payload
{
}Response samples
- 200
- 422
- 502
- 503
{
}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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| adj_type | Array of strings Filter by the free-text |
| date_from | string <date> Inclusive lower bound on |
| date_to | string <date> Inclusive upper bound on |
| 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 ( |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "adj_date": "2019-08-24",
- "adj_amount": "string",
- "adj_type": "string",
- "adj_note": "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"
}
]
}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:
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
- Payload
{- "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
- 201
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| date_from | string <date> Earliest |
| date_to | string <date> Latest |
| method | Array of strings Filter by payment-method bucket. Repeatable. One of |
| 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. |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "splits": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "procedure_code": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "split_amount": "string",
- "proc_code": "string",
- "procedure_date": "2019-08-24",
- "note": "string",
- "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
- "modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f",
- "practice": "735297b8-a875-445a-9746-8588a75f65f2",
- "payment": "4f07e784-b611-49dd-affc-3320a4f95555",
- "patient": "a7129932-7174-432d-a8dd-570510e145bb"
}
], - "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_billing_payment_create
Practice-wide payment list. GET all payments, POST to create (patient in body).
Authorizations:
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
- Payload
{- "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": [
- {
- "split_amount": "string",
- "proc_code": "string",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "procedure_date": "2019-08-24",
- "note": "string",
- "custom_data": null
}
]
}Response samples
- 201
- 403
{- "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": [
- {
- "split_amount": "string",
- "proc_code": "string",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "procedure_date": "2019-08-24",
- "note": "string",
- "custom_data": null
}
]
}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:
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. |
| include_archived | boolean When |
Responses
Response samples
- 200
{- "summary": {
- "total_ar": "string",
- "current": "string",
- "days_31_60": "string",
- "days_61_90": "string",
- "over_90": "string",
- "patient_count": 0
}, - "top_balances": [
- {
- "patient_id": "string",
- "patient_name": "string",
- "balance_total": "string",
- "bal_0_30": "string",
- "bal_31_60": "string",
- "bal_61_90": "string",
- "bal_over_90": "string",
- "last_payment_date": "string",
- "last_payment_amount": "string"
}
], - "by_provider": [
- {
- "provider_id": "string",
- "provider_name": "string",
- "bal_0_30": "string",
- "bal_31_60": "string",
- "bal_61_90": "string",
- "bal_over_90": "string",
- "balance_total": "string"
}
], - "by_insurance": [
- {
- "carrier_id": "string",
- "carrier_name": "string",
- "bal_0_30": "string",
- "bal_31_60": "string",
- "bal_61_90": "string",
- "bal_over_90": "string",
- "balance_total": "string"
}
]
}practice_billing_reports_aging_jobs_create
Kick off an async aging report computation.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}practice_billing_reports_aging_jobs_create_2
Kick off an async aging report computation.
Authorizations:
path Parameters
| as_of_date required | string |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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 |
| carrier | string <uuid> Restrict to patients whose primary insurance ( |
| min_balance | number <double> Exclude rows whose |
| provider | string <uuid> Restrict to patients whose |
| status | string Patient status filter: |
Responses
Response samples
- 200
{- "count": 0,
- "next": "string",
- "previous": "string",
- "results": [
- {
- "patient_id": "string",
- "patient_name": "string",
- "balance_total": "string",
- "bal_0_30": "string",
- "bal_31_60": "string",
- "bal_61_90": "string",
- "bal_over_90": "string",
- "last_payment_date": "string",
- "last_payment_amount": "string",
- "primary_provider_id": "string",
- "primary_provider_name": "string",
- "primary_carrier_id": "string",
- "primary_carrier_name": "string",
- "status": "string"
}
], - "summary": {
- "total_ar": "string",
- "current": "string",
- "days_31_60": "string",
- "days_61_90": "string",
- "over_90": "string",
- "patient_count": 0
}
}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:
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 ( |
Responses
Response samples
- 200
{- "date_from": "string",
- "date_to": "string",
- "summary": {
- "total_production": "string",
- "total_collections": "string",
- "total_adjustments": "string",
- "net_production": "string",
- "procedure_count": 0
}, - "by_provider": [
- {
- "provider_id": "fe3d49af-4061-436b-ae60-f7044f252a44",
- "provider_name": "string",
- "production": "string",
- "completed_production": "string",
- "scheduled_production": "string",
- "collections": "string",
- "adjustments": "string",
- "procedure_count": 0
}
], - "by_procedure": [
- {
- "proc_code": "string",
- "description": "string",
- "count": 0,
- "total_production": "string",
- "avg_fee": "string"
}
]
}practice_billing_reports_production_trending_retrieve
GET bucketed production-trending report (api#157).
Backs the Production Trending report UI (web#137). Returns one row
per bucket (day / week / month) between from and to, with
totals summed across the range.
Query params:
from (YYYY-MM-DD, required)
to (YYYY-MM-DD, required)
bucket (day | week | month, optional — defaults by range size)
provider (UUID, repeatable — narrows to listed providers)
metric (production,collections,adjustments,net_production —
comma-separated; controls which amounts appear in
each bucket row. appointment_count is always
returned.)
The single-range /reports/production/ endpoint is preserved for
backwards compatibility; this endpoint replaces its call site only
when the caller wants a time-series breakdown.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| bucket | string Bucket granularity: |
| from required | string <date> Start of the report range (inclusive, YYYY-MM-DD, practice TZ). |
| metric | string Comma-separated list of amount fields to include in each bucket row. Valid values: |
| provider | Array of strings <uuid> [ items <uuid > ] Filter to these providers only. Repeatable ( |
| to required | string <date> End of the report range (inclusive, YYYY-MM-DD, practice TZ). |
Responses
Response samples
- 200
{- "date_from": "string",
- "date_to": "string",
- "bucket": "string",
- "metrics": [
- "string"
], - "rows": [
- {
- "bucket_start": "string",
- "bucket_end": "string",
- "production": "string",
- "collections": "string",
- "adjustments": "string",
- "net_production": "string",
- "appointment_count": 0
}
], - "totals": {
- "property1": "string",
- "property2": "string"
}
}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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "adj_date": "2019-08-24",
- "adj_amount": "string",
- "adj_type": "string",
- "adj_note": "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"
}
]
}practice_patient_billing_adjustment_create
Paginated adjustment history for a patient. POST to create a new adjustment.
Authorizations:
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
- Payload
{- "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
- 201
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "appointment_id": "21634f0d-2156-4d4b-a142-2e7c783a9212",
- "procedures": [
- {
- "proc_code": "string",
- "description": "",
- "fee": "string",
- "tooth_num": "",
- "surface": "",
- "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9"
}
], - "payment": {
- "amount": "string",
- "type": "",
- "note": ""
}, - "create_claim": true
}Response samples
- 201
- 400
- 403
{- "procedures_count": 0,
- "payment_amount": "string",
- "claim_id": "string",
- "balance_summary": {
- "total_charges": "string",
- "total_payments": "string",
- "total_adjustments": "string",
- "insurance_paid": "string",
- "balance": "string"
}
}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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "splits": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "procedure_code": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "split_amount": "string",
- "proc_code": "string",
- "procedure_date": "2019-08-24",
- "note": "string",
- "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
- "modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f",
- "practice": "735297b8-a875-445a-9746-8588a75f65f2",
- "payment": "4f07e784-b611-49dd-affc-3320a4f95555",
- "patient": "a7129932-7174-432d-a8dd-570510e145bb"
}
], - "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_create
Paginated payment history for a patient. POST to create a new payment.
Authorizations:
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
- Payload
{- "pay_date": "2019-08-24",
- "pay_amount": "string",
- "pay_type": "string",
- "pay_note": "string",
- "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
- "custom_data": null,
- "splits": [
- {
- "split_amount": "string",
- "proc_code": "string",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "procedure_date": "2019-08-24",
- "note": "string",
- "custom_data": null
}
]
}Response samples
- 201
- 403
{- "pay_date": "2019-08-24",
- "pay_amount": "string",
- "pay_type": "string",
- "pay_note": "string",
- "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
- "custom_data": null,
- "splits": [
- {
- "split_amount": "string",
- "proc_code": "string",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "procedure_date": "2019-08-24",
- "note": "string",
- "custom_data": null
}
]
}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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "charges": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "charge_date": "2019-08-24",
- "principal": "string",
- "interest": "string",
- "note": "string",
- "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
- "modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f",
- "practice": "735297b8-a875-445a-9746-8588a75f65f2",
- "payment_plan": "f6fbe592-d05d-426b-90f5-7a7d5b227e98",
- "patient": "a7129932-7174-432d-a8dd-570510e145bb"
}
], - "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_create
Payment plans for a patient. Unpaginated. POST to create a new plan.
Authorizations:
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
- Payload
{- "guarantor": "2dc581b4-936d-4ab3-8a7d-1fc8f857bc6f",
- "plan_date": "2019-08-24",
- "apr": "string",
- "completed_amt": "string",
- "is_closed": true,
- "charges": [
- {
- "charge_date": "2019-08-24",
- "principal": "string",
- "interest": "string",
- "note": "string",
- "custom_data": null
}
], - "custom_data": null
}Response samples
- 201
- 403
{- "guarantor": "2dc581b4-936d-4ab3-8a7d-1fc8f857bc6f",
- "plan_date": "2019-08-24",
- "apr": "string",
- "completed_amt": "string",
- "is_closed": true,
- "charges": [
- {
- "charge_date": "2019-08-24",
- "principal": "string",
- "interest": "string",
- "note": "string",
- "custom_data": null
}
], - "custom_data": null
}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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}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:
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:
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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| category | string <uuid> Filter by document category UID. Categories are returned by |
| page | integer A page number within the paginated result set. |
| page_size | integer Number of results to return per page. |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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_delete_destroy
Soft-delete a document (HIPAA retention).
Authorizations:
path Parameters
| doc_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| category | string Optional category slug (e.g. |
| 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
- 200
- 400
- 503
{- "count": 0,
- "next": "string",
- "previous": "string",
- "results": [
- {
- "document": {
- "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
}, - "score": 0.1,
- "highlights": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}
}
]
}practice_doccenter_document_upload_create
Upload a practice-level document.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| inbox_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| inbox_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}practice_doccenter_inbox_upload_create
Upload a file to the inbox.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}practice_doccenter_scan_to_email_create
GET: return config. POST: enable scan-to-email. DELETE: disable.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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: |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "document_id": "b792e8ae-2cb4-4209-85b9-32be4c2fcdd6",
- "caller_id": "string",
- "received_at": "2019-08-24T14:15:22Z",
- "audio_url": "string",
- "transcript": "string",
- "transcript_confidence": 0.1,
- "current_patient_id": "80b282e8-2da8-459c-9f23-21b3d556031d",
- "suggested_patients": [
- {
- "patient_id": "3854866a-5476-48be-8313-77029ccdd7a7",
- "display_name": "string",
- "match_reason": "string"
}
], - "resolved_at": "2019-08-24T14:15:22Z",
- "processing_state": "string",
- "processing_error": "string"
}
]
}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:
path Parameters
| doc_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
- 403
- 404
{- "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:
path Parameters
| doc_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
- 403
- 404
{- "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:
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 |
| page | integer A page number within the paginated result set. |
| page_size | integer Number of results to return per page. |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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_delete_destroy
Soft-delete a document (HIPAA retention).
Authorizations:
path Parameters
| doc_id required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_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:
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"
|
| 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
- Payload
{- "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
- 201
- 403
{- "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:
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"
|
| 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
- Payload
{- "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
- 200
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_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:
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
- Payload
{- "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
- 201
- 403
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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_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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
[- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "role": "ADMIN",
- "status": "PENDING",
- "email_status": "NOT_SENT",
- "expires_at": "2019-08-24T14:15:22Z",
- "invited_at": "2019-08-24T14:15:22Z",
- "invited_by_name": "string"
}
]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:
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
- Payload
{- "email": "user@example.com",
- "role": "string"
}Response samples
- 201
- 403
{- "email": "user@example.com",
- "role": "string"
}practice_staff_invitations_revoke_create
Revoke a pending practice invitation.
Authorizations:
path Parameters
| invitation_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
PracticeMembershipfor the practice (direct members, active and deactivated alike), serialized withvia_practice=True; - every :class:
ClientMembershipof the practice's parent client (organization-level admins -- OWNER / BILLING / TECHNICAL), serialized withvia_client=Trueso 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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
[- {
- "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"
}
]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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
[- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user": "76f62a58-5404-486d-9afc-07bded328704",
- "user_email": "user@example.com",
- "user_first_name": "string",
- "user_last_name": "string",
- "permission": "patient.can_share",
- "granted": true,
- "granted_by_email": "string",
- "granted_at": "2019-08-24T14:15:22Z",
- "note": "string"
}
]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:
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"
|
| 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
- Payload
{- "user": "76f62a58-5404-486d-9afc-07bded328704",
- "permission": "patient.can_share",
- "granted": true,
- "note": "string"
}Response samples
- 201
- 403
{- "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:
path Parameters
| grant_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}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:
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
- 200
{- "count": 123,
- "results": [
- {
- "code": "string",
- "status": "string",
- "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
- "created_by_email": "user@example.com",
- "created_at": "2019-08-24T14:15:22Z",
- "expires_at": "2019-08-24T14:15:22Z",
- "redeemed_at": "2019-08-24T14:15:22Z",
- "redeemed_by_client_name": "string"
}
]
}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:
Request Body schema:
| client | string or null <uuid> |
Responses
Request samples
- Payload
{- "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8"
}Response samples
- 201
{- "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:
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:
Responses
Response samples
- 200
{- "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:
Responses
Response samples
- 200
{- "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": [
- {
- "practice_id": "ab8b92c6-fdd4-4c27-ab69-c61896d976bd",
- "practice_name": "string",
- "client_id": "5b3fa7ba-57d3-4017-a65b-d57dcd2db643",
- "role": "ADMIN",
- "is_active": true
}
], - "client_memberships": [
- {
- "client_id": "5b3fa7ba-57d3-4017-a65b-d57dcd2db643",
- "client_name": "string",
- "role": "OWNER",
- "is_active": true
}
], - "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:
Responses
Response samples
- 200
{- "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:
Responses
Response samples
- 200
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": {
- "sidebar_collapsed": true,
- "default_view": "schedule"
}, - "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:
Request Body schema:
| data | any |
Responses
Request samples
- Payload
PUT replaces the entire data object for the current OAuth2 application.
{- "data": {
- "sidebar_collapsed": true,
- "default_view": "schedule"
}
}Response samples
- 200
{- "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:
Request Body schema:
| data | any |
Responses
Request samples
- Payload
{- "data": null
}Response samples
- 200
{- "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:
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 oflight,dark, orsystem. Any other value (including missing) is treated assystemwhen the value is read back, so the OS-levelprefers-color-schemesetting 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:
Responses
Response samples
- 200
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": {
- "theme": "dark"
}, - "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 oflight,dark, orsystem. Any other value (including missing) is treated assystemwhen the value is read back, so the OS-levelprefers-color-schemesetting 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:
Request Body schema:
| data | any |
Responses
Request samples
- Payload
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": {
- "theme": "dark"
}
}Response samples
- 200
Returned after a successful PUT or PATCH that updated the theme.
{- "id": "11111111-1111-4111-8111-111111111111",
- "data": {
- "theme": "dark"
}, - "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 oflight,dark, orsystem. Any other value (including missing) is treated assystemwhen the value is read back, so the OS-levelprefers-color-schemesetting 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:
Request Body schema:
| data | any |
Responses
Request samples
- Payload
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": {
- "theme": "light"
}
}Response samples
- 200
Returned after a successful PUT or PATCH that updated the theme.
{- "id": "11111111-1111-4111-8111-111111111111",
- "data": {
- "theme": "dark"
}, - "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-wideanonscope so it can't be turned into a Client-creation cannon.When the
invited_signup_requiredWaffle flag is off for the request,invite_codeis ignored -- a missing or invalid code does not block signup. This is the day-one default.When the flag is on,
invite_codeis required and is atomically redeemed inside the same transaction that creates the User, Client, and ClientMembership. The redemption usesselect_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:
- Create the new :class:
apps.practices.models.Client. - Create the new :class:
User(passwordless -- the next step in the signup wizard is magic-link → passkey enrolment). - Create the :class:
ClientMembershipwith roleOWNER. - (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:
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 |
| npi | string^\d{10}$ 10-digit National Provider Identifier. Required when the |
| state | string <= 2 characters Two-letter US state code where the practice operates. Required when the |
Responses
Request samples
- Payload
{- "email": "user@example.com",
- "first_name": "string",
- "last_name": "string",
- "client_name": "string",
- "invite_code": "string",
- "npi": "string",
- "state": "st"
}Response samples
- 201
- 400
{- "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_tokencookie (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
Authorizationheader (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:
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
refreshfield, the view falls back to reading theescape_refresh_tokenHttpOnly 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
refreshfield 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:
Request Body schema: required
| refresh required | string non-empty |
Responses
Request samples
- Payload
{- "refresh": "string"
}Response samples
- 200
{- "refresh": "string",
- "access": "string"
}client_invite_codes_list
List or mint invite codes scoped to a single Client (GH-649).
GET /api/v1/client/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/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:
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
- 200
{- "count": 123,
- "results": [
- {
- "code": "string",
- "status": "string",
- "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
- "created_by_email": "user@example.com",
- "created_at": "2019-08-24T14:15:22Z",
- "expires_at": "2019-08-24T14:15:22Z",
- "redeemed_at": "2019-08-24T14:15:22Z",
- "redeemed_by_client_name": "string"
}
]
}client_invite_codes_create
List or mint invite codes scoped to a single Client (GH-649).
GET /api/v1/client/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/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:
path Parameters
| client_uid required | string <uuid> |
Responses
Response samples
- 201
{- "code": "string",
- "expires_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z"
}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:
Request Body schema: application/json
| name required | string Organization name |
Responses
Request samples
- Payload
{- "name": "string"
}Response samples
- 201
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Request Body schema: multipart/form-datarequired
| file required | string <binary> |
Responses
Response samples
- 200
- 403
{
}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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Request Body schema: multipart/form-datarequired
| file required | string <binary> |
Responses
Response samples
- 200
- 403
{
}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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "inbox_owner_user_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "inbox_owner_users": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "full_name": "string"
}
]
}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:
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
- Payload
{- "inbox_owner_user_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
]
}Response samples
- 200
- 403
{- "inbox_owner_user_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "inbox_owner_users": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "full_name": "string"
}
]
}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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
Responses
Response samples
- 201
- 402
{- "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_sync_export_counts_retrieve
Return entity counts for a practice (lightweight preview).
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "practice_name": "string",
- "counts": {
- "property1": 0,
- "property2": 0
}, - "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:
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"
|
required | Array of objects |
Responses
Request samples
- Payload
{- "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
- "entity_type": "definitions",
- "records": [
- {
- "property1": null,
- "property2": null
}
]
}Response samples
- 200
- 403
- 404
- 409
{- "created": 0,
- "skipped": 0,
- "errors": 0,
- "error_messages": [
- "string"
]
}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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
[- {
- "id": "string",
- "source": "string",
- "status": "string",
- "started_at": "string",
- "completed_at": "string",
- "created_by": "user@example.com",
- "record_counts": {
- "property1": 0,
- "property2": 0
}, - "total_records": 0
}
]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:
path Parameters
| practice_uid required | string <uuid> |
Request Body schema: required
| source required | string (ImportSessionCreateSourceEnum) Enum: "opendental" "eaglesoft" "dentrix" "restore" "faker"
|
Responses
Request samples
- Payload
{- "source": "opendental"
}Response samples
- 201
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| session_id required | string <uuid> |
Responses
Response samples
- 200
- 404
{- "id": "string",
- "source": "string",
- "status": "string",
- "started_at": "string",
- "completed_at": "string",
- "created_by": "user@example.com",
- "record_counts": {
- "property1": 0,
- "property2": 0
}, - "total_records": 0,
- "conversion_error_count": 0,
- "import_report": {
- "property1": null,
- "property2": null
}, - "import_error_details": [
- {
- "property1": null,
- "property2": null
}
], - "has_schema": true,
- "conversion": {
- "entities": [
- {
- "entity_type": "string",
- "status": "string",
- "total": 0,
- "converted": 0,
- "skipped": 0,
- "errors": 0,
- "error_messages": [
- "string"
]
}
], - "total_converted": 0,
- "total_errors": 0,
- "total_skipped": 0,
- "is_complete": true
}
}practice_sync_import_session_destroy
Retrieve session detail with conversion progress (GET) or delete (DELETE).
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
| session_id required | string <uuid> |
Responses
Response samples
- 403
- 404
- 409
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| session_id required | string <uuid> |
Responses
Response samples
- 200
- 403
- 404
- 409
{- "detail": "string",
- "session_id": "string"
}practice_sync_import_session_complete_create
Mark an import session as completed.
Authorizations:
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
- Payload
{- "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
- "results": [
- {
- "property1": null,
- "property2": null
}
], - "report": {
- "property1": null,
- "property2": null
}
}Response samples
- 200
- 403
- 404
{- "session_id": "string",
- "status": "string",
- "completed_at": "string",
- "record_counts": {
- "property1": 0,
- "property2": 0
}
}practice_sync_import_session_convert_create
Trigger conversion of a completed import session to live data.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
| session_id required | string <uuid> |
Responses
Response samples
- 202
- 403
- 404
- 409
{- "detail": "string",
- "session_id": "string"
}practice_sync_import_session_error_report_retrieve
Download a conversion error report as JSON or CSV.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
| session_id required | string <uuid> |
Responses
Response samples
- 200
- 404
{- "records": [
- {
- "entity_type": "string",
- "external_id": "string",
- "type": "string",
- "error_message": "string"
}
]
}practice_sync_import_session_rollback_create
Delete all normalized data for this session and reset to uploaded status.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
| session_id required | string <uuid> |
Responses
Response samples
- 200
- 403
- 404
- 409
{- "detail": "string"
}practice_sync_import_session_schema_create
Upload a source PMS schema dump for an import session.
Authorizations:
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
- Payload
{- "schema_text": "string",
- "source_type": "string",
- "metadata": {
- "property1": null,
- "property2": null
}
}Response samples
- 201
- 403
- 404
{- "detail": "string"
}practice_sync_status_list
List all sync status records for a practice.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
[- {
- "entity_type": "string",
- "last_synced_at": "string",
- "last_record_count": 0,
- "is_running": true,
- "error_message": "string"
}
]practice_sync_status_retrieve
Get or update a sync status record for a specific entity type.
Authorizations:
path Parameters
| entity_type required | string |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
- 404
{- "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:
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
- Payload
{- "last_synced_at": "2019-08-24T14:15:22Z",
- "last_record_count": 0,
- "is_running": false,
- "error_message": ""
}Response samples
- 200
- 201
- 403
{- "entity_type": "string",
- "last_synced_at": "string",
- "last_record_count": 0,
- "is_running": true,
- "error_message": "string"
}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:
path Parameters
| subscription_uid required | string <uuid> |
Responses
account_magic_link_request_create
Request a magic link for authentication.
POST /api/v1/account/magic-link/request/ Body: { "email": "user@example.com" }
Always returns 200 regardless of whether the email exists (no oracle).
Authorizations:
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:
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:
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:
Request Body schema: required
| token required | string non-empty |
Responses
Request samples
- Payload
{- "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:
query Parameters
| cursor | string The pagination cursor value. |
Responses
Response samples
- 200
{- "results": [
- {
- "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": [
- {
- "practice_id": "ab8b92c6-fdd4-4c27-ab69-c61896d976bd",
- "practice_name": "string",
- "client_id": "5b3fa7ba-57d3-4017-a65b-d57dcd2db643",
- "role": "ADMIN",
- "is_active": true
}
], - "client_memberships": [
- {
- "client_id": "5b3fa7ba-57d3-4017-a65b-d57dcd2db643",
- "client_name": "string",
- "role": "OWNER",
- "is_active": true
}
], - "max_session_hours": "string",
- "current_practice_id": "edf1be34-8ae4-41f5-bad6-133af3513eac",
- "practice_timezone": "string"
}
]
}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:
path Parameters
| user_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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": [
- {
- "practice_id": "ab8b92c6-fdd4-4c27-ab69-c61896d976bd",
- "practice_name": "string",
- "client_id": "5b3fa7ba-57d3-4017-a65b-d57dcd2db643",
- "role": "ADMIN",
- "is_active": true
}
], - "client_memberships": [
- {
- "client_id": "5b3fa7ba-57d3-4017-a65b-d57dcd2db643",
- "client_name": "string",
- "role": "OWNER",
- "is_active": true
}
], - "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:
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
- Payload
{- "first_name": "string",
- "last_name": "string"
}Response samples
- 200
{- "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": [
- {
- "practice_id": "ab8b92c6-fdd4-4c27-ab69-c61896d976bd",
- "practice_name": "string",
- "client_id": "5b3fa7ba-57d3-4017-a65b-d57dcd2db643",
- "role": "ADMIN",
- "is_active": true
}
], - "client_memberships": [
- {
- "client_id": "5b3fa7ba-57d3-4017-a65b-d57dcd2db643",
- "client_name": "string",
- "role": "OWNER",
- "is_active": true
}
], - "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:
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
- Payload
{- "first_name": "string",
- "last_name": "string"
}Response samples
- 200
{- "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": [
- {
- "practice_id": "ab8b92c6-fdd4-4c27-ab69-c61896d976bd",
- "practice_name": "string",
- "client_id": "5b3fa7ba-57d3-4017-a65b-d57dcd2db643",
- "role": "ADMIN",
- "is_active": true
}
], - "client_memberships": [
- {
- "client_id": "5b3fa7ba-57d3-4017-a65b-d57dcd2db643",
- "client_name": "string",
- "role": "OWNER",
- "is_active": true
}
], - "max_session_hours": "string",
- "current_practice_id": "edf1be34-8ae4-41f5-bad6-133af3513eac",
- "practice_timezone": "string"
}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:
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 |
| 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
- 200
{- "count": 123,
- "results": [
- {
- "scope": "client",
- "scope_id": "string",
- "window_start": "2019-08-24T14:15:22Z",
- "window_end": "2019-08-24T14:15:22Z",
- "method": "string",
- "count": 0,
- "app_name": "string"
}
]
}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:
query Parameters
| actor_email | string Exact-match actor email; matched against the keyword field |
| event_type | string Dotted-name event type (e.g. |
| 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 |
| until | string <date-time> ISO8601 upper bound (inclusive) on |
Responses
Response samples
- 200
[- {
- "occurred_at": "string",
- "actor_user_email": "string",
- "actor_user_name": "string",
- "actor_role": "string",
- "actor_ip": "string",
- "actor_user_agent": "string",
- "event_type": "string",
- "event_category": "string",
- "resource_type": "string",
- "resource_id": "string",
- "outcome": "string",
- "purpose": "string"
}
]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:
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
- Payload
{- "is_active": true,
- "reason": "string"
}Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "is_active": true
}admin_magic_link_create
Generate a magic link for any user.
Staff-only endpoint. Creates a time-limited, single-use magic link
that can be handed to a user out-of-band for passkey recovery.
Reuses the same infrastructure as the create_magic_link management
command.
Authorizations:
Request Body schema: required
| email required | string <email> non-empty Email address of the user to mint a link for. |
| purpose | string Default: "passkey_recovery" Value: "passkey_recovery" Purpose of the magic link.
|
| expires_in_minutes | integer [ 1 .. 1440 ] Default: 15 Link TTL in minutes (1-1440). Default: 15. |
Responses
Request samples
- Payload
{- "email": "user@example.com",
- "purpose": "passkey_recovery",
- "expires_in_minutes": 15
}Response samples
- 201
{- "token": "string",
- "expires_at": "2019-08-24T14:15:22Z",
- "user_email": "user@example.com"
}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:
Responses
Response samples
- 200
[- {
- "name": "string",
- "description": "string",
- "required_scopes": [
- "string"
], - "pass_context": true
}
]Get OAuth application detail
Return the public payload for a single OAuth application.
Authorizations:
path Parameters
| client_id required | string |
Responses
Response samples
- 200
{- "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": [
- "string"
], - "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:
path Parameters
| client_id required | string |
Request Body schema:
| throttle_mode | string Enum: "default" "audit" "enforce" Target throttle mode.
|
| reason | string [ 5 .. 1024 ] characters Free-text justification recorded in the audit log (min 5 chars). |
Responses
Request samples
- Payload
{- "throttle_mode": "default",
- "reason": "string"
}Response samples
- 200
{- "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": [
- "string"
], - "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:
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
- Payload
{- "is_active": true,
- "reason": "string"
}Response samples
- 200
{- "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:
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
- Payload
{- "reason": "string",
- "limit": 1,
- "mime": [
- "string"
], - "force": false,
- "dry_run": false
}Response samples
- 200
{- "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:
path Parameters
| id required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "enabled": true,
- "note": ""
}Response samples
- 200
- 201
{- "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:
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:
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
- Payload
{- "is_active": true,
- "reason": "string"
}Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "first_name": "string",
- "last_name": "string",
- "is_active": true
}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 againstnameORclient_id. Empty/missing means "no filter". Translates toQ(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 asdefaultso?throttle_mode=defaultreturns them too — implemented with aLEFT JOIN+Coalesceannotation 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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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": [
- "string"
], - "url_template": "",
- "approved_at": "2019-08-24T14:15:22Z",
- "approved_by_email": "string"
}
]
}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:
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:
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:
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:
path Parameters
| practice_id required | string <uuid> |
Responses
Response samples
- 200
[- {
- "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"
}
]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
qis UUID-shaped, does an exact match onPatient.id. - Otherwise, performs a case-insensitive prefix match against
first_nameORlast_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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "initials": "string",
- "practice": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string"
}, - "status": "active",
- "last_appointment_at": "string",
- "balance_outstanding": "string",
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z"
}
]
}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:
path Parameters
| id required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "initials": "string",
- "practice": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string"
}, - "status": "active",
- "last_appointment_at": "string",
- "balance_outstanding": "string",
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z"
}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:
Responses
Response samples
- 200
[- {
- "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"
}
]clients_reports_adjustments_retrieve
Per-practice adjustments breakdown by adj_type.
Authorizations:
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
- 200
{- "date_from": "string",
- "date_to": "string",
- "grand_total": "string",
- "practices": [
- {
- "practice_id": "string",
- "practice_name": "string",
- "total_adjustments": "string",
- "by_type": [
- {
- "adj_type": "string",
- "amount": "string",
- "count": 0
}
]
}
]
}clients_reports_ar_aging_retrieve
Four-bucket AR aging totals + per-practice breakdown.
Authorizations:
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
- 200
{- "as_of": "string",
- "totals": {
- "total_ar": "string",
- "current": "string",
- "days_31_60": "string",
- "days_61_90": "string",
- "over_90": "string",
- "patient_count": 0
}, - "practices": [
- {
- "practice_id": "string",
- "practice_name": "string",
- "total_ar": "string",
- "current": "string",
- "days_31_60": "string",
- "days_61_90": "string",
- "over_90": "string",
- "patient_count": 0
}
]
}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_pctanddelayed_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.ServiceTypecodes (e.g.major,endodontics) that narrows the queryset to plan items whose linked :class:ProcedureCode.service_typeis in the set. Items with no linked code are excluded once a filter is supplied.
Authorizations:
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
- 200
{- "date_from": "string",
- "date_to": "string",
- "totals": {
- "presented_amount": "string",
- "accepted_amount": "string",
- "acceptance_rate_pct": "string",
- "same_visit_accepted_pct": "string",
- "delayed_accepted_pct": "string"
}, - "practices": [
- {
- "practice_id": "string",
- "practice_name": "string",
- "presented_amount": "string",
- "accepted_amount": "string",
- "acceptance_rate_pct": "string",
- "same_visit_accepted_pct": "string",
- "delayed_accepted_pct": "string"
}
]
}clients_reports_hygiene_recare_retrieve
Per-practice hygiene-recare compliance counts and rate.
api#507 adds two pieces:
avg_days_late_among_non_compliantper practice -- the mean number of days pastdate_dueacross 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 separatewithout_active_recare_countbucket so consumers can show "of every active patient, what fraction are actually on a recare track".
Authorizations:
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 |
Responses
Response samples
- 200
{- "as_of": "string",
- "totals": {
- "compliant_count": 0,
- "upcoming_count": 0,
- "overdue_count": 0,
- "without_active_recare_count": 0,
- "recall_total": 0,
- "compliance_rate_pct": "string",
- "avg_days_late_among_non_compliant": "string"
}, - "practices": [
- {
- "practice_id": "string",
- "practice_name": "string",
- "compliant_count": 0,
- "upcoming_count": 0,
- "overdue_count": 0,
- "without_active_recare_count": 0,
- "recall_total": 0,
- "compliance_rate_pct": "string",
- "avg_days_late_among_non_compliant": "string"
}
]
}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:
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
- 200
{- "as_of": "string",
- "totals": {
- "today_production": "string",
- "week_production": "string",
- "ar_total": "string",
- "no_show_rate_pct": "string",
- "practice_count": 0
}, - "practices": [
- {
- "practice_id": "string",
- "practice_name": "string",
- "today_production": "string",
- "week_production": "string",
- "ar_total": "string",
- "no_show_rate_pct": "string"
}
]
}clients_reports_payer_mix_retrieve
Per-practice payer mix derived from each patient's primary insurance.
Authorizations:
path Parameters
| client_uid required | string <uuid> |
Responses
Response samples
- 200
{- "practices": [
- {
- "practice_id": "string",
- "practice_name": "string",
- "patient_total": 0,
- "carriers": [
- {
- "carrier_id": "string",
- "carrier_name": "string",
- "patient_count": 0,
- "share_pct": "string"
}
]
}
]
}clients_reports_production_by_provider_retrieve
Per-practice / per-provider production with production-per-hour.
Authorizations:
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
- 200
{- "date_from": "string",
- "date_to": "string",
- "practices": [
- {
- "practice_id": "string",
- "practice_name": "string",
- "providers": [
- {
- "provider_id": "string",
- "provider_name": "string",
- "production": "string",
- "collections": "string",
- "adjustments": "string",
- "procedure_count": 0,
- "hours": "string",
- "production_per_hour": "string"
}
]
}
]
}clients_reports_production_vs_collections_retrieve
Per-practice production / collections / adjustments table.
Authorizations:
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
- 200
{- "date_from": "string",
- "date_to": "string",
- "totals": {
- "production": "string",
- "collections": "string",
- "adjustments": "string",
- "net_production": "string",
- "collection_pct": "string"
}, - "practices": [
- {
- "practice_id": "string",
- "practice_name": "string",
- "production": "string",
- "collections": "string",
- "adjustments": "string",
- "net_production": "string",
- "collection_pct": "string"
}
]
}desktop_documents_sessions_retrieve
Get capture session status for crash recovery.
Authorizations:
path Parameters
| session_uid required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "status": "pending",
- "workstation_name": "string",
- "item_count": "string",
- "created": "2019-08-24T14:15:22Z"
}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:
query Parameters
| client | string <uuid> Filter by client UUID. |
| occurred_from | string <date> Filter rows whose |
| occurred_to | string <date> Filter rows whose |
| 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: |
| user | string <uuid> Filter by submitter user UUID. |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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",
- "url": "string",
- "user_agent": "string",
- "status": "new",
- "has_screenshot": true,
- "triaged_by": "918c35b9-bedc-437d-84b5-ebe932e91c8b",
- "triaged_at": "2019-08-24T14:15:22Z",
- "resolved_by": "d0d57369-b08b-4db8-8952-8cdeedd9aebc",
- "resolved_at": "2019-08-24T14:15:22Z",
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z"
}
]
}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:
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
- Payload
{- "practice": "735297b8-a875-445a-9746-8588a75f65f2",
- "title": "string",
- "details": "string",
- "screenshot": "string",
- "url": "string",
- "viewport": null,
- "user_agent": "string",
- "js_errors": null
}Response samples
- 201
{- "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:
path Parameters
| feedback_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
path Parameters
| feedback_uid required | string <uuid> |
Request Body schema: required
| status required | string (FeedbackStatusEnum) Enum: "new" "triaged" "resolved"
|
| resolution_note | string Default: "" |
Responses
Request samples
- Payload
{- "status": "new",
- "resolution_note": ""
}Response samples
- 200
{- "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"
}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:
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
- 202
{- "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:
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
- 200
- 202
{- "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:
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
- 202
- 404
{- "property1": null,
- "property2": null
}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:
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:
FormSendOutis required; submitting against a session withcurrent_sendout=Noneis a 400 (the kiosk shouldn't be rendering a form yet anyway). - Submissions are tagged
submitted_via='kiosk'; thesubmitted_viafield in the payload is ignored if present. - The sendout's
statusis NOT flipped tosubmitted: 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_aton 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:
path Parameters
| token required | string |
Responses
forms_public_retrieve
GET /api/v1/forms/public/
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:
path Parameters
| token required | string |
Responses
forms_public_submit_create
POST /api/v1/forms/public/
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:
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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "description": "string",
- "is_default_new_patient": true,
- "items": [
- {
- "template": "060ce75e-87d6-4677-b330-eaee58e54138",
- "template_name": "string",
- "order": 2147483647
}
], - "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z"
}
]
}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:
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
- Payload
{- "name": "string",
- "description": "string",
- "is_default_new_patient": true,
- "template_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
]
}Response samples
- 201
- 403
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "description": "string",
- "is_default_new_patient": true,
- "items": [
- {
- "template": "060ce75e-87d6-4677-b330-eaee58e54138",
- "template_name": "string",
- "order": 2147483647
}
], - "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:
path Parameters
| bundle_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "description": "string",
- "is_default_new_patient": true,
- "items": [
- {
- "template": "060ce75e-87d6-4677-b330-eaee58e54138",
- "template_name": "string",
- "order": 2147483647
}
], - "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:
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
- Payload
{- "name": "string",
- "description": "string",
- "is_default_new_patient": true,
- "template_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
]
}Response samples
- 200
- 403
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "description": "string",
- "is_default_new_patient": true,
- "items": [
- {
- "template": "060ce75e-87d6-4677-b330-eaee58e54138",
- "template_name": "string",
- "order": 2147483647
}
], - "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:
path Parameters
| bundle_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "description": "string",
- "is_default_new_patient": true,
- "items": [
- {
- "template": "060ce75e-87d6-4677-b330-eaee58e54138",
- "template_name": "string",
- "order": 2147483647
}
], - "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_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:
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
- Payload
{- "device_label": "string",
- "idle_timeout_seconds": 2147483647
}Response samples
- 201
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| session_id required | string <uuid> |
Responses
Response samples
- 200
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| session_id required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| session_id required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_retrieve
GET /api/v1/practice/<uid>/forms/mapping-proposals/<id>/
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
| proposal_id required | string <uuid> |
Responses
Response samples
- 200
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| proposal_id required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| proposal_id required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_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:
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).
|
| expires_at | string <date-time> |
Responses
Request samples
- Payload
{- "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
- 201
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| sendout_id required | string <uuid> |
Responses
Response samples
- 200
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| sendout_id required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| sendout_id required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "sendout": "16923f90-ef9c-4aae-86f5-f8c83143e987",
- "template": "060ce75e-87d6-4677-b330-eaee58e54138",
- "template_name": "string",
- "template_version": 0,
- "submitted_at": "2019-08-24T14:15:22Z",
- "submitted_via": "portal",
- "applied_to_patient": true,
- "attached_document": "0bfc4d00-d425-4f8f-9d22-bd1dde36db96",
- "attached_document_url": "string",
- "created": "2019-08-24T14:15:22Z"
}
]
}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:
path Parameters
| practice_uid required | string <uuid> |
| sendout_id required | string <uuid> |
Responses
practice_forms_submissions_pdf_retrieve
GET /api/v1/practice/
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:
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/POST /v1/practice/
Authorizations:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "version_group": "270269c2-f759-4e54-adee-ae78012a3e32",
- "version": 1,
- "name": "string",
- "description": "string",
- "is_active": true,
- "fields": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "order": 2147483647,
- "field_type": "text",
- "label": "string",
- "help_text": "string",
- "required": true,
- "options": null,
- "maps_to_patient_field": "string",
- "consent_text": "string"
}
], - "prefill_map": null,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z"
}
]
}practice_forms_templates_create
List or create form templates for a practice.
GET /v1/practice/POST /v1/practice/
Authorizations:
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: |
Responses
Request samples
- Payload
{- "name": "string",
- "description": "string",
- "fields": [
- {
- "order": 2147483647,
- "field_type": "text",
- "label": "string",
- "help_text": "string",
- "required": true,
- "options": null,
- "maps_to_patient_field": "string",
- "consent_text": "string"
}
], - "prefill_map": null
}Response samples
- 201
- 403
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "version_group": "270269c2-f759-4e54-adee-ae78012a3e32",
- "version": 1,
- "name": "string",
- "description": "string",
- "is_active": true,
- "fields": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "order": 2147483647,
- "field_type": "text",
- "label": "string",
- "help_text": "string",
- "required": true,
- "options": null,
- "maps_to_patient_field": "string",
- "consent_text": "string"
}
], - "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/PATCH /v1/practice/
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:
path Parameters
| practice_uid required | string <uuid> |
| template_id required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "version_group": "270269c2-f759-4e54-adee-ae78012a3e32",
- "version": 1,
- "name": "string",
- "description": "string",
- "is_active": true,
- "fields": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "order": 2147483647,
- "field_type": "text",
- "label": "string",
- "help_text": "string",
- "required": true,
- "options": null,
- "maps_to_patient_field": "string",
- "consent_text": "string"
}
], - "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/PATCH /v1/practice/
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:
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: |
Responses
Request samples
- Payload
{- "name": "string",
- "description": "string",
- "fields": [
- {
- "order": 2147483647,
- "field_type": "text",
- "label": "string",
- "help_text": "string",
- "required": true,
- "options": null,
- "maps_to_patient_field": "string",
- "consent_text": "string"
}
], - "prefill_map": null
}Response samples
- 200
- 403
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "version_group": "270269c2-f759-4e54-adee-ae78012a3e32",
- "version": 1,
- "name": "string",
- "description": "string",
- "is_active": true,
- "fields": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "order": 2147483647,
- "field_type": "text",
- "label": "string",
- "help_text": "string",
- "required": true,
- "options": null,
- "maps_to_patient_field": "string",
- "consent_text": "string"
}
], - "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:
path Parameters
| practice_uid required | string <uuid> |
| template_id required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| template_id required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
| template_id required | string <uuid> |
Responses
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:
IsAuthenticated-- session or bearer; practically staff sessions from the web nine-dots.IsStaffUser-- patient users cannot launch 3rd-party apps.- Explicit check that the authenticated user has practice access.
- Explicit check that the user's active
:class:
OAuthPracticeGrantauthorizes this app for this practice. - Rate limit (see :class:
LaunchTokenCreateThrottle).
Authorizations:
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
- Payload
{- "application": "string",
- "practice": "735297b8-a875-445a-9746-8588a75f65f2"
}Response samples
- 200
{- "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:
Responses
Response samples
- 200
{- "count": 0,
- "results": [
- {
- "app_id": "string",
- "client_id": "string",
- "name": "string",
- "logo_url": "string",
- "scopes": [
- "string"
], - "first_granted_at": "2019-08-24T14:15:22Z",
- "last_used_at": "2019-08-24T14:15:22Z"
}
]
}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:
path Parameters
| app_id required | string |
Responses
Response samples
- 200
{- "grants_revoked": 0,
- "tokens_revoked": 0
}oauth_tablet_pair_create
Public pair-completion endpoint.
No authentication is required -- the unguessable pair_token IS the auth. The endpoint:
- Verifies the JWT signature + expiry.
- 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).
- Atomically:
a. Inserts :class:
PairTokenRedemption(Postgres unique constraint races a second redemption into 410). b. Creates the :class:Tabletrow from the JWT claims + posted public key. c. Mints a DOT AccessToken + RefreshToken bound to theescape-kiosk-tabletApplication and the new Tablet. - 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:
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
- Payload
{- "pair_token": "string",
- "public_key": "string"
}practice_kiosk_check_in_create
POST /api/v1/practice/
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:
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
- Payload
{- "last_name": "string",
- "dob": "2019-08-24"
}Response samples
- 200
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
[- {
- "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_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:
path Parameters
| practice_uid required | string <uuid> |
| tablet_id required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}practice_tablets_form_session_submit_create
POST /api/v1/practice/
Tablet-authenticated. See module docstring for the full contract.
Authorizations:
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: |
| 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 |
Responses
Request samples
- Payload
{- "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
- "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
- "values": null,
- "signature_b64": ""
}Response samples
- 200
- 201
- 403
{- "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:
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
- Payload
{- "name": "string"
}Response samples
- 200
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| tablet_id required | string <uuid> |
Responses
Response samples
- 200
- 403
{- "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:
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
- Payload
{- "action": "string",
- "payload": {
- "property1": null,
- "property2": null
}, - "form_session": {
- "bundle_id": "fc6f5a67-caa1-4339-9c14-a67826143b60",
- "template_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "patient_id": "3854866a-5476-48be-8313-77029ccdd7a7",
- "appointment_id": "21634f0d-2156-4d4b-a142-2e7c783a9212"
}
}Response samples
- 403
{- "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:
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
- Payload
{- "name": "string"
}Response samples
- 201
- 403
{- "pair_token": "string",
- "expires_at": "2019-08-24T14:15:22Z"
}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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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",
- "page_url": "string",
- "user_agent": "string",
- "status": "new",
- "triaged_by": "918c35b9-bedc-437d-84b5-ebe932e91c8b",
- "triaged_at": "2019-08-24T14:15:22Z",
- "resolved_by": "d0d57369-b08b-4db8-8952-8cdeedd9aebc",
- "resolved_at": "2019-08-24T14:15:22Z",
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z"
}
]
}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:
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
- Payload
{- "title": "string",
- "details": "string",
- "page_url": "string",
- "viewport": null,
- "user_agent": "string"
}Response samples
- 201
{- "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:
path Parameters
| patient_feedback_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
path Parameters
| patient_feedback_uid required | string <uuid> |
Request Body schema: required
| status required | string (FeedbackStatusEnum) Enum: "new" "triaged" "resolved"
|
| resolution_note | string Default: "" |
Responses
Request samples
- Payload
{- "status": "new",
- "resolution_note": ""
}Response samples
- 200
{- "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_list
List payment history for the authenticated patient.
Authorizations:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "stripe_payment_intent_id": "string",
- "amount_cents": 0,
- "amount_dollars": "string",
- "status": "PENDING",
- "description": "string",
- "created": "2019-08-24T14:15:22Z"
}
]
}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:
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 ( |
Responses
Request samples
- Payload
{- "amount_cents": 50,
- "description": "",
- "practice": "735297b8-a875-445a-9746-8588a75f65f2",
- "save_for_future_use": false,
- "payment_method": ""
}Response samples
- 200
- 503
{- "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:
Responses
Response samples
- 200
- 503
{- "status": "string"
}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:
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: |
| to | string <date> Latest appointment date to include (YYYY-MM-DD, practice timezone, inclusive). |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "uid": "07cc67f4-45d6-494b-adac-09b5cbc7e2b5",
- "start_time": "2019-08-24T14:15:22Z",
- "duration_minutes": 0,
- "provider_name": "string",
- "procedure_description": "string",
- "status": "string"
}
]
}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:
Responses
Response samples
- 200
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:
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
- 200
[- {
- "client_id": "string",
- "name": "string",
- "icon_url": "string",
- "url_template": "string"
}
]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:
Responses
Response samples
- 200
[- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "string",
- "conversation_type": "direct",
- "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
- "participants": [
- {
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "first_name": "string",
- "last_name": "string",
- "last_read_at": "2019-08-24T14:15:22Z"
}
], - "last_message": {
- "property1": null,
- "property2": null
}, - "unread_count": 0,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z"
}
]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:
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 |
Responses
Request samples
- Payload
{- "body": "string",
- "subject": ""
}Response samples
- 201
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "string",
- "conversation_type": "direct",
- "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
- "participants": [
- {
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "first_name": "string",
- "last_name": "string",
- "last_read_at": "2019-08-24T14:15:22Z"
}
], - "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:
path Parameters
| conversation_id required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "string",
- "conversation_type": "direct",
- "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
- "participants": [
- {
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "first_name": "string",
- "last_name": "string",
- "last_read_at": "2019-08-24T14:15:22Z"
}
], - "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:
path Parameters
| conversation_id required | string <uuid> |
Responses
Response samples
- 200
[- {
- "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"
}
]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:
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
- Payload
{- "body": "string"
}Response samples
- 201
{- "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:
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:
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:
Responses
Response samples
- 200
[- {
- "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_portal_appointment_book_create
Book an appointment as an authenticated patient.
POST /api/v1/practice/
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:
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
- Payload
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": [
- "D1110"
], - "notes": "First availability in the morning, please."
}Response samples
- 201
- 403
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/
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:
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
- Payload
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": [
- "D1110"
], - "notes": "First availability in the morning, please."
}Response samples
- 403
{- "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/
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:
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
- Payload
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
- 200
- 403
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/
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:
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/
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_DAYSdays.overdue_charges-- portion of the balance from charges dated more than_PORTAL_OVERDUE_DAYSdays ago. Capped atmax(0, total_balance).last_payment_date/last_payment_amount-- most recent patient-paid (non-insurance) payment, or null if none.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
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/
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:
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). |
| 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/
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:
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
- 200
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": [
- {
- "date": "2026-03-02",
- "entry_type": "charge",
- "description": "D1110 Prophylaxis - adult",
- "amount": "110.00",
- "running_balance": "110.00"
}, - {
- "date": "2026-03-02",
- "entry_type": "payment",
- "description": "Balance on previous visit",
- "amount": "75.00",
- "running_balance": "35.00"
}, - {
- "date": "2026-05-14",
- "entry_type": "charge",
- "description": "D2740 Crown - porcelain/ceramic substrate",
- "amount": "1150.00",
- "running_balance": "1185.00"
}, - {
- "date": "2026-05-14",
- "entry_type": "payment",
- "description": "Co-pay for cleaning",
- "amount": "150.00",
- "running_balance": "1035.00"
}
], - "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:
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
- 200
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": [
- {
- "count": 2,
- "next": null,
- "previous": null,
- "results": [
- {
- "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": { }
}, - {
- "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_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:
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
- Payload
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
- 201
- 403
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:
path Parameters
| message_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
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/
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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
- 503
{- "results": [
- {
- "id": "string",
- "brand": "string",
- "last4": "string",
- "exp_month": 0,
- "exp_year": 0,
- "created": 0
}
]
}practice_portal_payment_methods_destroy
Detach a single saved payment method.
DELETE /api/v1/practice/
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:
path Parameters
| pm_id required | string |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
- 503
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
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.
[- [
- {
- "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"
}, - {
- "id": "dadadada-dada-4ada-8ada-dadadadadada",
- "pay_date": "2026-03-02",
- "pay_amount": "75.00",
- "pay_type": "online_patient_portal",
- "pay_note": "Balance on previous visit",
- "created": "2026-03-02T15:44:02Z"
}
]
]practice_portal_payments_create
Record a patient payment from the portal — charge-then-persist.
The flow is:
- Validate the payload.
- If a Stripe
payment_methodtoken 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 — noPaymentRecordis written. - Only after a successful charge (or a non-Stripe payload — for
e.g. the initial post-deploy window when
STRIPE_SECRET_KEYis unset) do we persist thePaymentRecord.
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:
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
- Payload
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
- 201
- 403
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/
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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
- 403
- 503
{- "client_secret": "string",
- "setup_intent_id": "string",
- "customer_id": "string"
}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:
path Parameters
| token required | string |
Request Body schema: required
| submitted_data required | any Patient intake data (demographics, etc.). |
Responses
Request samples
- Payload
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": {
- "first_name": "John",
- "last_name": "Doe",
- "email": "john.doe@example.com",
- "date_of_birth": "1990-04-12",
- "gender": "M",
- "phone_home": "+15555550100",
- "phone_mobile": "+15555550101",
- "phone_work": "",
- "address": "123 Example St",
- "address2": "",
- "city": "Springfield",
- "state": "IL",
- "zip_code": "62701",
- "insurance": {
- "carrier": "Synthetic Dental PPO",
- "subscriber_id": "SYN-000-0001",
- "group_number": "GRP-9999"
}, - "medical_history": {
- "allergies": [ ],
- "medications": [ ],
- "conditions": [ ]
}
}
}Response samples
- 200
The token is now marked used; replaying it returns 410 Gone.
{- "detail": "Submission received."
}practice_list
List practices (admin-only).
Authorizations:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_clinical_note_template_retrieve
Retrieve, update, or delete a clinical note template.
Authorizations:
path Parameters
| note_template_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "name": "string",
- "category": "exam",
- "content": "string",
- "is_active": true,
- "sort_order": 2147483647,
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
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
- Payload
{- "name": "string",
- "category": "exam",
- "content": "string",
- "is_active": true,
- "sort_order": 2147483647,
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
path Parameters
| note_template_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Request Body schema:
| custom_data | any |
Responses
Request samples
- Payload
{- "custom_data": null
}Response samples
- 200
- 403
{- "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": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "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:
path Parameters
| practice_uid required | string <uuid> |
| procedure_code_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
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"
|
| direction | string (Direction80cEnum) Enum: "sent" "received" "neither"
|
| outcome | string Enum: "success" "no_answer" "voicemail" "bounced" "bad_number" "other" What happened on the contact attempt. Only
|
| 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 |
| custom_data | any |
Responses
Request samples
- Payload
{- "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
- 200
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "slug": "string",
- "label": "string",
- "icon": "string",
- "sort_order": 32767,
- "custom_data": null
}
]
}practice_doccenter_category_create
List system + practice categories; POST creates a practice-custom category.
Authorizations:
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
- Payload
{- "slug": "string",
- "label": "string",
- "icon": "string",
- "sort_order": 32767,
- "custom_data": null
}Response samples
- 201
- 403
{- "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:
path Parameters
| category_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "slug": "string",
- "label": "string",
- "icon": "string",
- "sort_order": 32767,
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
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
- Payload
{- "slug": "string",
- "label": "string",
- "icon": "string",
- "sort_order": 32767,
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
path Parameters
| category_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}practice_doccenter_document_retrieve
Retrieve or update document metadata.
Authorizations:
path Parameters
| doc_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "patient": "a7129932-7174-432d-a8dd-570510e145bb",
- "category": "86d23d13-9dbb-46f3-82d0-25253c7750c3",
- "title": "string",
- "description": "string",
- "caller_id": "string",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
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
- Payload
{- "patient": "a7129932-7174-432d-a8dd-570510e145bb",
- "category": "86d23d13-9dbb-46f3-82d0-25253c7750c3",
- "title": "string",
- "description": "string",
- "caller_id": "string",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_retrieve
View or update inbox item (title, notes).
Authorizations:
path Parameters
| inbox_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "title": "string",
- "notes": "string",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
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
- Payload
{- "title": "string",
- "notes": "string",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
path Parameters
| fax_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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": [
- {
- "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
}
], - "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "custom_data": null
}
]
}practice_imaging_mount_create
List mounts in a practice and create new mounts from a template.
Authorizations:
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
- Payload
{- "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
- 201
- 403
{- "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": [
- {
- "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
}
], - "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "code": "string",
- "description": "string",
- "slot_layout": null,
- "slot_count": 0,
- "is_active": true,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z"
}
]
}practice_imaging_mount_retrieve
Retrieve, update metadata on, or delete a mount.
Authorizations:
path Parameters
| mount_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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": [
- {
- "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
}
], - "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:
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
- Payload
{- "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
- 200
- 403
{- "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": [
- {
- "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
}
], - "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:
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
- Payload
{- "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
- 200
- 403
{- "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": [
- {
- "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
}
], - "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:
path Parameters
| mount_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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
- Payload
{- "image": "89f204d4-24d2-439a-b6e8-e97405cb1f8e",
- "rotation": 2147483647,
- "flipped": true,
- "label": "string",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
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
- Payload
{- "image": "89f204d4-24d2-439a-b6e8-e97405cb1f8e",
- "rotation": 2147483647,
- "flipped": true,
- "label": "string",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_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:
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"
|
| is_active | boolean |
| notes | string |
| custom_data | any |
Responses
Request samples
- Payload
{- "name": "string",
- "source_type": "webcam",
- "is_active": true,
- "notes": "string",
- "custom_data": null
}Response samples
- 201
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| source_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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"
|
| is_active | boolean |
| notes | string |
| custom_data | any |
Responses
Request samples
- Payload
{- "name": "string",
- "source_type": "webcam",
- "is_active": true,
- "notes": "string",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
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"
|
| is_active | boolean |
| notes | string |
| custom_data | any |
Responses
Request samples
- Payload
{- "name": "string",
- "source_type": "webcam",
- "is_active": true,
- "notes": "string",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| source_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "row": 2147483647,
- "col": 2147483647,
- "label": "string",
- "custom_data": null
}
], - "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "custom_data": null
}
]
}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:
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
- Payload
{- "name": "string",
- "description": "string",
- "grid_rows": 2147483647,
- "grid_cols": 2147483647,
- "source": "07b8e003-7027-443f-88b0-24a5eb1cc68b",
- "is_active": true,
- "custom_data": null
}Response samples
- 201
- 403
{- "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": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "row": 2147483647,
- "col": 2147483647,
- "label": "string",
- "custom_data": null
}
], - "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "row": 2147483647,
- "col": 2147483647,
- "label": "string",
- "custom_data": null
}
]
}practice_imaging_template_slot_create
Manage slots within an exam template.
Authorizations:
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
- Payload
{- "row": 2147483647,
- "col": 2147483647,
- "label": "string",
- "custom_data": null
}Response samples
- 201
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| slot_uid required | string <uuid> |
| template_id required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| template_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "row": 2147483647,
- "col": 2147483647,
- "label": "string",
- "custom_data": null
}
], - "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:
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
- Payload
{- "name": "string",
- "description": "string",
- "grid_rows": 2147483647,
- "grid_cols": 2147483647,
- "source": "07b8e003-7027-443f-88b0-24a5eb1cc68b",
- "is_active": true,
- "custom_data": null
}Response samples
- 200
- 403
{- "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": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "row": 2147483647,
- "col": 2147483647,
- "label": "string",
- "custom_data": null
}
], - "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:
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
- Payload
{- "name": "string",
- "description": "string",
- "grid_rows": 2147483647,
- "grid_cols": 2147483647,
- "source": "07b8e003-7027-443f-88b0-24a5eb1cc68b",
- "is_active": true,
- "custom_data": null
}Response samples
- 200
- 403
{- "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": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "row": 2147483647,
- "col": 2147483647,
- "label": "string",
- "custom_data": null
}
], - "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:
path Parameters
| practice_uid required | string <uuid> |
| template_uid required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}practice_insurance_carrier_retrieve
Retrieve, update, or deactivate an insurance carrier.
Authorizations:
path Parameters
| carrier_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "phone": "string",
- "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:
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
- Payload
{- "name": "string",
- "phone": "string",
- "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
- 200
- 403
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "phone": "string",
- "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:
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
- Payload
{- "name": "string",
- "phone": "string",
- "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
- 200
- 403
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "phone": "string",
- "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:
path Parameters
| carrier_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "proc_code": "string",
- "allowed_amount": "string",
- "description": "string",
- "custom_data": null
}
]
}practice_insurance_fee_schedule_entry_destroy
Delete a single fee schedule entry.
Authorizations:
path Parameters
| entry_uid required | string <uuid> |
| fee_schedule_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| fee_schedule_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "proc_code": "string",
- "allowed_amount": "string",
- "description": "string",
- "custom_data": null
}
], - "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:
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
- Payload
{- "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
- 200
- 403
{- "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": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "proc_code": "string",
- "allowed_amount": "string",
- "description": "string",
- "custom_data": null
}
], - "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:
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
- Payload
{- "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
- 200
- 403
{- "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": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "proc_code": "string",
- "allowed_amount": "string",
- "description": "string",
- "custom_data": null
}
], - "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:
path Parameters
| fee_schedule_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| benefit_uid required | string <uuid> |
| plan_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "procedure_code": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| benefit_uid required | string <uuid> |
| plan_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}practice_insurance_plan_retrieve
Retrieve, update, or delete an insurance plan.
Authorizations:
path Parameters
| plan_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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": [
- {
- "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
}
], - "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:
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
- Payload
{- "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": [
- {
- "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
}
], - "custom_data": null
}Response samples
- 200
- 403
{- "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": [
- {
- "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
}
], - "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:
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
- Payload
{- "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": [
- {
- "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
}
], - "custom_data": null
}Response samples
- 200
- 403
{- "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": [
- {
- "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
}
], - "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:
path Parameters
| plan_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| verification_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "plan_name": "string",
- "group_number": "string",
- "carrier_name": "string"
}, - "patient_summary": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "initials": "string"
}, - "verified_by_summary": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "display_name": "string"
}, - "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:
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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| patient_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
path Parameters
| patient_id required | string <uuid> |
| plan_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "charges": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "charge_date": "2019-08-24",
- "principal": "string",
- "interest": "string",
- "note": "string",
- "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
- "modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f",
- "practice": "735297b8-a875-445a-9746-8588a75f65f2",
- "payment_plan": "f6fbe592-d05d-426b-90f5-7a7d5b227e98",
- "patient": "a7129932-7174-432d-a8dd-570510e145bb"
}
], - "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:
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
- Payload
{- "guarantor": "2dc581b4-936d-4ab3-8a7d-1fc8f857bc6f",
- "plan_date": "2019-08-24",
- "apr": "string",
- "completed_amt": "string",
- "is_closed": true,
- "charges": [
- {
- "charge_date": "2019-08-24",
- "principal": "string",
- "interest": "string",
- "note": "string",
- "custom_data": null
}
], - "custom_data": null
}Response samples
- 200
- 403
{- "guarantor": "2dc581b4-936d-4ab3-8a7d-1fc8f857bc6f",
- "plan_date": "2019-08-24",
- "apr": "string",
- "completed_amt": "string",
- "is_closed": true,
- "charges": [
- {
- "charge_date": "2019-08-24",
- "principal": "string",
- "interest": "string",
- "note": "string",
- "custom_data": null
}
], - "custom_data": null
}practice_patient_billing_payment_plan_partial_update
Retrieve or update a payment plan.
Authorizations:
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
- Payload
{- "guarantor": "2dc581b4-936d-4ab3-8a7d-1fc8f857bc6f",
- "plan_date": "2019-08-24",
- "apr": "string",
- "completed_amt": "string",
- "is_closed": true,
- "charges": [
- {
- "charge_date": "2019-08-24",
- "principal": "string",
- "interest": "string",
- "note": "string",
- "custom_data": null
}
], - "custom_data": null
}Response samples
- 200
- 403
{- "guarantor": "2dc581b4-936d-4ab3-8a7d-1fc8f857bc6f",
- "plan_date": "2019-08-24",
- "apr": "string",
- "completed_amt": "string",
- "is_closed": true,
- "charges": [
- {
- "charge_date": "2019-08-24",
- "principal": "string",
- "interest": "string",
- "note": "string",
- "custom_data": null
}
], - "custom_data": null
}practice_patient_billing_payment_retrieve
Retrieve or update a payment record.
Authorizations:
path Parameters
| patient_id required | string <uuid> |
| payment_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "splits": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "procedure_code": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "split_amount": "string",
- "proc_code": "string",
- "procedure_date": "2019-08-24",
- "note": "string",
- "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
- "modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f",
- "practice": "735297b8-a875-445a-9746-8588a75f65f2",
- "payment": "4f07e784-b611-49dd-affc-3320a4f95555",
- "patient": "a7129932-7174-432d-a8dd-570510e145bb"
}
], - "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:
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
- Payload
{- "pay_date": "2019-08-24",
- "pay_amount": "string",
- "pay_type": "string",
- "pay_note": "string",
- "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
- "custom_data": null,
- "splits": [
- {
- "split_amount": "string",
- "proc_code": "string",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "procedure_date": "2019-08-24",
- "note": "string",
- "custom_data": null
}
]
}Response samples
- 200
- 403
{- "pay_date": "2019-08-24",
- "pay_amount": "string",
- "pay_type": "string",
- "pay_note": "string",
- "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
- "custom_data": null,
- "splits": [
- {
- "split_amount": "string",
- "proc_code": "string",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "procedure_date": "2019-08-24",
- "note": "string",
- "custom_data": null
}
]
}practice_patient_billing_payment_partial_update
Retrieve or update a payment record.
Authorizations:
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
- Payload
{- "pay_date": "2019-08-24",
- "pay_amount": "string",
- "pay_type": "string",
- "pay_note": "string",
- "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
- "custom_data": null,
- "splits": [
- {
- "split_amount": "string",
- "proc_code": "string",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "procedure_date": "2019-08-24",
- "note": "string",
- "custom_data": null
}
]
}Response samples
- 200
- 403
{- "pay_date": "2019-08-24",
- "pay_amount": "string",
- "pay_type": "string",
- "pay_note": "string",
- "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
- "custom_data": null,
- "splits": [
- {
- "split_amount": "string",
- "proc_code": "string",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "procedure_date": "2019-08-24",
- "note": "string",
- "custom_data": null
}
]
}practice_patient_clinical_allergy_list
List and create allergies for a patient.
Authorizations:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_create
List and create allergies for a patient.
Authorizations:
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
- Payload
{- "allergy_name": "string",
- "reaction": "string",
- "is_active": true,
- "date_reaction": "2019-08-24",
- "custom_data": null
}Response samples
- 201
- 403
{- "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:
path Parameters
| allergy_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "allergy_name": "string",
- "reaction": "string",
- "is_active": true,
- "date_reaction": "2019-08-24",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
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
- Payload
{- "allergy_name": "string",
- "reaction": "string",
- "is_active": true,
- "date_reaction": "2019-08-24",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
path Parameters
| allergy_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}practice_patient_clinical_anesthesia_retrieve
Retrieve or update an anesthesia record.
Authorizations:
path Parameters
| anesthesia_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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"
|
| agent_other | string <= 100 characters If agent=other, specify here |
| route | string (RouteEnum) Enum: "infiltration" "block" "topical" "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
- Payload
{- "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
- 200
- 403
{- "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:
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"
|
| agent_other | string <= 100 characters If agent=other, specify here |
| route | string (RouteEnum) Enum: "infiltration" "block" "topical" "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
- Payload
{- "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
- 200
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_create
List and create medical conditions for a patient.
Authorizations:
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
- Payload
{- "condition_name": "string",
- "date_start": "2019-08-24",
- "date_stop": "2019-08-24",
- "note": "string",
- "custom_data": null
}Response samples
- 201
- 403
{- "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:
path Parameters
| condition_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "condition_name": "string",
- "date_start": "2019-08-24",
- "date_stop": "2019-08-24",
- "note": "string",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
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
- Payload
{- "condition_name": "string",
- "date_start": "2019-08-24",
- "date_stop": "2019-08-24",
- "note": "string",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
path Parameters
| condition_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| education_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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"
|
| 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
- Payload
{- "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
- 200
- 403
{- "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:
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"
|
| 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
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| education_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_create
List and create medications for a patient.
Authorizations:
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
- Payload
{- "medication_name": "string",
- "date_start": "2019-08-24",
- "date_stop": "2019-08-24",
- "note": "string",
- "rx_cui": "string",
- "custom_data": null
}Response samples
- 201
- 403
{- "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:
path Parameters
| medication_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "medication_name": "string",
- "date_start": "2019-08-24",
- "date_stop": "2019-08-24",
- "note": "string",
- "rx_cui": "string",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
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
- Payload
{- "medication_name": "string",
- "date_start": "2019-08-24",
- "date_stop": "2019-08-24",
- "note": "string",
- "rx_cui": "string",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
path Parameters
| medication_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| note_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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"
|
| 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
- Payload
{- "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
- 200
- 403
{- "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:
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"
|
| 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
- Payload
{- "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
- 200
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "tooth_num": "strin",
- "probe_1": 32767,
- "probe_2": 32767,
- "probe_3": 32767,
- "probe_4": 32767,
- "probe_5": 32767,
- "probe_6": 32767,
- "recession_1": -32768,
- "recession_2": -32768,
- "recession_3": -32768,
- "recession_4": -32768,
- "recession_5": -32768,
- "recession_6": -32768,
- "bleed_1": true,
- "bleed_2": true,
- "bleed_3": true,
- "bleed_4": true,
- "bleed_5": true,
- "bleed_6": true,
- "suppuration_1": true,
- "suppuration_2": true,
- "suppuration_3": true,
- "suppuration_4": true,
- "suppuration_5": true,
- "suppuration_6": true,
- "plaque_1": true,
- "plaque_2": true,
- "plaque_3": true,
- "plaque_4": true,
- "plaque_5": true,
- "plaque_6": true,
- "furcation": 32767,
- "mobility": 32767,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "custom_data": null
}
], - "reading_count": 0,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "custom_data": null
}
]
}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:
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
- Payload
{- "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
- 201
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| perio_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "tooth_num": "strin",
- "probe_1": 32767,
- "probe_2": 32767,
- "probe_3": 32767,
- "probe_4": 32767,
- "probe_5": 32767,
- "probe_6": 32767,
- "recession_1": -32768,
- "recession_2": -32768,
- "recession_3": -32768,
- "recession_4": -32768,
- "recession_5": -32768,
- "recession_6": -32768,
- "bleed_1": true,
- "bleed_2": true,
- "bleed_3": true,
- "bleed_4": true,
- "bleed_5": true,
- "bleed_6": true,
- "suppuration_1": true,
- "suppuration_2": true,
- "suppuration_3": true,
- "suppuration_4": true,
- "suppuration_5": true,
- "suppuration_6": true,
- "plaque_1": true,
- "plaque_2": true,
- "plaque_3": true,
- "plaque_4": true,
- "plaque_5": true,
- "plaque_6": true,
- "furcation": 32767,
- "mobility": 32767,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "custom_data": null
}
], - "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| perio_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}practice_patient_clinical_procedure_retrieve
Retrieve, update, or delete a procedure.
Authorizations:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
| procedure_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
| procedure_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
| tooth_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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"
|
| dentition | string (DentitionEnum) Enum: "permanent" "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
- Payload
{- "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
- 200
- 403
{- "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:
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"
|
| dentition | string (DentitionEnum) Enum: "permanent" "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
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
| tooth_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| plan_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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": [
- {
- "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
}
], - "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:
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"
|
| date_accepted | string or null <date> |
| custom_data | any |
Array of objects (TreatmentPlanItemWriteRequest) |
Responses
Request samples
- Payload
{- "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
- "name": "string",
- "note": "string",
- "status": "active",
- "date_accepted": "2019-08-24",
- "custom_data": null,
- "items": [
- {
- "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",
- "est_primary_ins": "string",
- "est_secondary_ins": "string",
- "plan_name": "string",
- "priority": 2147483647,
- "custom_data": null
}
]
}Response samples
- 200
- 403
{- "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
- "name": "string",
- "note": "string",
- "status": "active",
- "date_accepted": "2019-08-24",
- "custom_data": null,
- "items": [
- {
- "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",
- "est_primary_ins": "string",
- "est_secondary_ins": "string",
- "plan_name": "string",
- "priority": 2147483647,
- "custom_data": null
}
]
}practice_patient_clinical_treatment_plan_partial_update
Retrieve, update, or delete a treatment plan.
Authorizations:
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"
|
| date_accepted | string or null <date> |
| custom_data | any |
Array of objects (TreatmentPlanItemWriteRequest) |
Responses
Request samples
- Payload
{- "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
- "name": "string",
- "note": "string",
- "status": "active",
- "date_accepted": "2019-08-24",
- "custom_data": null,
- "items": [
- {
- "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",
- "est_primary_ins": "string",
- "est_secondary_ins": "string",
- "plan_name": "string",
- "priority": 2147483647,
- "custom_data": null
}
]
}Response samples
- 200
- 403
{- "provider": "017a51ba-65fb-4bca-a631-012d4d8d49b9",
- "name": "string",
- "note": "string",
- "status": "active",
- "date_accepted": "2019-08-24",
- "custom_data": null,
- "items": [
- {
- "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",
- "est_primary_ins": "string",
- "est_secondary_ins": "string",
- "plan_name": "string",
- "priority": 2147483647,
- "custom_data": null
}
]
}practice_patient_clinical_treatment_plan_destroy
Retrieve, update, or delete a treatment plan.
Authorizations:
path Parameters
| patient_id required | string <uuid> |
| plan_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_create
List and create items within a treatment plan.
Authorizations:
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
- Payload
{- "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
- 201
- 403
{- "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:
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
- 200
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
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
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
| vital_sign_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| commlog_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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"
|
| direction | string (Direction80cEnum) Enum: "sent" "received" "neither"
|
| outcome | string Enum: "success" "no_answer" "voicemail" "bounced" "bad_number" "other" What happened on the contact attempt. Only
|
| 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
- Payload
{- "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
- 200
- 403
{- "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:
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"
|
| direction | string (Direction80cEnum) Enum: "sent" "received" "neither"
|
| outcome | string Enum: "success" "no_answer" "voicemail" "bounced" "bad_number" "other" What happened on the contact attempt. Only
|
| 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
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| commlog_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}practice_patient_doccenter_retrieve
Retrieve or update document metadata.
Authorizations:
path Parameters
| doc_id required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "patient": "a7129932-7174-432d-a8dd-570510e145bb",
- "category": "86d23d13-9dbb-46f3-82d0-25253c7750c3",
- "title": "string",
- "description": "string",
- "caller_id": "string",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
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
- Payload
{- "patient": "a7129932-7174-432d-a8dd-570510e145bb",
- "category": "86d23d13-9dbb-46f3-82d0-25253c7750c3",
- "title": "string",
- "description": "string",
- "caller_id": "string",
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_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:
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
- Payload
{- "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
- 201
- 403
{- "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:
path Parameters
| exam_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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": [
- {
- "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_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:
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
- Payload
{- "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
- 200
- 403
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| exam_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_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:
path Parameters
| image_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| image_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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
- 201
- 403
{- "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/
Authorizations:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "claim": "7e60fd1d-575d-4043-a73d-5a2fe9049027",
- "from_status": "string",
- "to_status": "string",
- "changed_by": "3e89c7a5-3fa2-4d93-b1c0-5c0519bb2681",
- "changed_by_email": "string",
- "changed_at": "2019-08-24T14:15:22Z",
- "note": "string",
- "custom_data": null
}
]
}practice_patient_insurance_claim_retrieve
Retrieve a single insurance claim with full details.
GET /practice/
Authorizations:
path Parameters
| claim_uid required | string <uuid> |
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "procedures": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "procedure_code": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "proc_code": "string",
- "fee_billed": "string",
- "ins_pay_est": "string",
- "ins_pay_amt": "string",
- "ded_applied": "string",
- "write_off": "string",
- "status": "string",
- "proc_date": "2019-08-24",
- "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
- "modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f",
- "practice": "735297b8-a875-445a-9746-8588a75f65f2",
- "claim": "7e60fd1d-575d-4043-a73d-5a2fe9049027",
- "patient": "a7129932-7174-432d-a8dd-570510e145bb",
- "procedure": "d851bde4-b989-444b-aa77-4e67fb9f8d2c"
}
], - "status_log": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "claim": "7e60fd1d-575d-4043-a73d-5a2fe9049027",
- "from_status": "string",
- "to_status": "string",
- "changed_by": "3e89c7a5-3fa2-4d93-b1c0-5c0519bb2681",
- "changed_by_email": "string",
- "changed_at": "2019-08-24T14:15:22Z",
- "note": "string",
- "custom_data": null
}
], - "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/
Authorizations:
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
- Payload
{- "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": [
- {
- "procedure": "d851bde4-b989-444b-aa77-4e67fb9f8d2c",
- "proc_code": "string",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "fee_billed": "string",
- "ins_pay_est": "string",
- "ded_applied": "string",
- "write_off": "string",
- "custom_data": null
}
], - "custom_data": null
}Response samples
- 200
- 403
{- "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": [
- {
- "procedure": "d851bde4-b989-444b-aa77-4e67fb9f8d2c",
- "proc_code": "string",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "fee_billed": "string",
- "ins_pay_est": "string",
- "ded_applied": "string",
- "write_off": "string",
- "custom_data": null
}
], - "custom_data": null
}practice_patient_insurance_plan_benefit_retrieve
Update or delete a benefit.
Authorizations:
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
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "procedure_code": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
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
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| plan_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "benefits": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "custom_data": null,
- "procedure_code": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "abbreviation": "string"
}, - "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"
}
], - "carrier_detail": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "phone": "string",
- "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
}, - "plan_detail": {
- "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",
- "is_active": true,
- "enrollment_count": 0,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "custom_data": null
}, - "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| patient_id required | string <uuid> |
| plan_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_patient_retrieve
Retrieve or update a single patient. Staff-only.
Authorizations:
path Parameters
| patient_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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 |
string <email> <= 254 characters | |
| date_of_birth | string or null <date> |
| gender | string (GenderEnum) Enum: "male" "female" "other" "unknown"
|
| status | string (PatientStatusEnum) Enum: "active" "inactive" "archived" "deceased" "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
- Payload
{- "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
- 200
- 403
{- "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:
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 |
string <email> <= 254 characters | |
| date_of_birth | string or null <date> |
| gender | string (GenderEnum) Enum: "male" "female" "other" "unknown"
|
| status | string (PatientStatusEnum) Enum: "active" "inactive" "archived" "deceased" "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
- Payload
{- "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
- 200
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_create
List and create referral sources for a practice.
Bulk create is supported by POSTing an array.
Authorizations:
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 |
string <email> <= 254 characters | |
| npi | string <= 20 characters |
| is_doctor | boolean |
| custom_data | any |
Responses
Request samples
- Payload
{- "first_name": "string",
- "last_name": "string",
- "specialty": "string",
- "phone": "string",
- "email": "user@example.com",
- "npi": "string",
- "is_doctor": true,
- "custom_data": null
}Response samples
- 201
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| referral_source_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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 |
string <email> <= 254 characters | |
| npi | string <= 20 characters |
| is_doctor | boolean |
| custom_data | any |
Responses
Request samples
- Payload
{- "first_name": "string",
- "last_name": "string",
- "specialty": "string",
- "phone": "string",
- "email": "user@example.com",
- "npi": "string",
- "is_doctor": true,
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
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 |
string <email> <= 254 characters | |
| npi | string <= 20 characters |
| is_doctor | boolean |
| custom_data | any |
Responses
Request samples
- Payload
{- "first_name": "string",
- "last_name": "string",
- "specialty": "string",
- "phone": "string",
- "email": "user@example.com",
- "npi": "string",
- "is_doctor": true,
- "custom_data": null
}Response samples
- 200
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| referral_source_uid required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}practice_provider_retrieve
Retrieve or update a single provider.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
| provider_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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"
|
| 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
- Payload
{- "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
- 200
- 403
{- "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:
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"
|
| 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
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| operatory_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| operatory_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| appointment_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "proc_code": "string",
- "description": "string",
- "fee": "string",
- "tooth_num": "string",
- "surface": "string",
- "status": "planned",
- "custom_data": null
}
], - "custom_data": null
}practice_scheduling_appointment_update
Retrieve or update a single appointment. Status changes must go through /transition/.
Authorizations:
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
- Payload
{- "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": [
- {
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "proc_code": "string",
- "description": "string",
- "fee": "string",
- "tooth_num": "string",
- "surface": "string",
- "status": "planned",
- "custom_data": null
}
], - "custom_data": null,
- "allow_overbooking": false,
- "skip_validation": false
}Response samples
- 200
- 403
{- "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": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "proc_code": "string",
- "description": "string",
- "fee": "string",
- "tooth_num": "string",
- "surface": "string",
- "status": "planned",
- "custom_data": null
}
], - "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:
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
- Payload
{- "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": [
- {
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "proc_code": "string",
- "description": "string",
- "fee": "string",
- "tooth_num": "string",
- "surface": "string",
- "status": "planned",
- "custom_data": null
}
], - "custom_data": null,
- "allow_overbooking": false,
- "skip_validation": false
}Response samples
- 200
- 403
{- "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": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "procedure_code": "d6cd26fd-67f7-4760-9d46-9e3d886de650",
- "proc_code": "string",
- "description": "string",
- "fee": "string",
- "tooth_num": "string",
- "surface": "string",
- "status": "planned",
- "custom_data": null
}
], - "custom_data": null,
- "allow_overbooking": false,
- "skip_validation": false
}practice_scheduling_recall_retrieve
Retrieve, update, or delete a single recall record.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
| recall_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
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
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| recall_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| override_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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"
|
| blockout_type | string <= 50 characters e.g. lunch, meeting, holiday, time_off |
| operatory | string or null <uuid> |
| status | string (ScheduleOverrideStatusEnum) Enum: "open" "closed" "holiday"
|
| note | string |
| custom_data | any |
Responses
Request samples
- Payload
{- "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
- 200
- 403
{- "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:
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"
|
| blockout_type | string <= 50 characters e.g. lunch, meeting, holiday, time_off |
| operatory | string or null <uuid> |
| status | string (ScheduleOverrideStatusEnum) Enum: "open" "closed" "holiday"
|
| note | string |
| custom_data | any |
Responses
Request samples
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| override_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| template_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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"
|
| blockout_type | string <= 50 characters e.g. lunch, meeting, admin |
| operatory | string or null <uuid> |
| is_active | boolean |
| custom_data | any |
Responses
Request samples
- Payload
{- "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
- 200
- 403
{- "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:
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"
|
| blockout_type | string <= 50 characters e.g. lunch, meeting, admin |
| operatory | string or null <uuid> |
| is_active | boolean |
| custom_data | any |
Responses
Request samples
- Payload
{- "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
- 200
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| template_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| message_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
path Parameters
| member_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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"
|
| is_active | boolean |
Responses
Request samples
- Payload
{- "role": "ADMIN",
- "is_active": true
}Response samples
- 200
- 403
{- "role": "ADMIN",
- "is_active": true
}practice_staff_members_partial_update
Retrieve or update a single practice membership.
Authorizations:
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"
|
| is_active | boolean |
Responses
Request samples
- Payload
{- "role": "ADMIN",
- "is_active": true
}Response samples
- 200
- 403
{- "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:
Responses
Response samples
- 200
[- {
- "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_retrieve
Retrieve or update the user's default practice (first practice under their client).
Authorizations:
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "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
- 200
{- "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:
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
- Payload
{- "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
- 200
{- "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"
}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):
- The OAuth application has an
OAuthAppProfilewithapproval_status == APPROVEDandis_first_party == False(escape-web itself must never show up as a launcher tile). - The profile publishes a non-empty
navbar_label— apps that haven't registered for the navbar stay invisible even if otherwise fully onboarded. - There is at least one active
OAuthPracticeGranttying this application to this practice — only apps the practice has actually consented to appear in its launcher. - No
PracticeAppVisibilityrow hides the app for this practice. Absence of a row = default-visible.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
[- {
- "id": "string",
- "name": "string",
- "label": "string",
- "category": "string",
- "icon_url": "string",
- "is_visible": true
}
]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:
path Parameters
| client_id required | string |
| practice_uid required | string <uuid> |
Request Body schema:
| is_visible | boolean |
Responses
Request samples
- Payload
{- "is_visible": true
}Response samples
- 200
- 403
{- "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:
path Parameters
| client_id required | string |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
- Verify the Bearer token is authenticated (
IsAuthenticated). - Directly look up the practice by URL UID and confirm the
requesting user has a
PracticeMembershipin it. - Create / reactivate the grant.
Security
- Requires a valid Bearer token (
IsAuthenticated). - User must have an active
PracticeMembershipfor 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_idmust be an approved, non-first-party application with a non-emptynavbar_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:
path Parameters
| client_id required | string |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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 withrel=noopener,noreferrerand window.open's 3rd-arg equivalent. - Emits an
oauth_app.launchaudit event only on the success path — failed or unauthorized launches are not logged as launches.
Failure contract:
404for every navbar-ineligibility reason (unapproved, first-party, missing grant, hidden by visibility row, missingnavbar_labelornavbar_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.401for unauthenticated callers (DRF default).403for users with no access to the scoped practice (raised byPracticeScopedMixin).
Authorizations:
path Parameters
| client_id required | string |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
- 403
{
}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:
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"
|
Responses
Request samples
- Payload
{- "patient_uid": "2e193f60-014a-4901-af70-2d4676096d5e",
- "date_from": "2019-08-24",
- "date_to": "2019-08-24",
- "format": "both"
}Response samples
- 202
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| report_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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": {
- "property1": "string",
- "property2": "string"
}, - "error_message": "string"
}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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| date_from | string <date> Inclusive lower bound on |
| date_to | string <date> Inclusive upper bound on |
| 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 ( |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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_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:
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"
|
| direction | string (Direction80cEnum) Enum: "sent" "received" "neither"
|
| outcome | string Enum: "success" "no_answer" "voicemail" "bounced" "bad_number" "other" What happened on the contact attempt. Only
|
| 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 |
| custom_data | any |
Responses
Request samples
- Payload
{- "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
- 201
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
- 404
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Request Body schema:
| area_code | string <= 3 characters US area code (3 digits, e.g. |
| preferred_locality | string <= 64 characters Free-form locality hint (e.g. |
Responses
Request samples
- Payload
{- "area_code": "str",
- "preferred_locality": "string"
}Response samples
- 201
- 400
- 403
- 409
- 502
{- "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:
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 |
| 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. |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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_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:
path Parameters
| practice_uid required | string <uuid> |
Request Body schema: multipart/form-datarequired
| 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
- 201
- 403
{- "to_number": "string",
}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:
path Parameters
| fax_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
- 403
- 404
{- "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:
path Parameters
| fax_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 400
- 403
- 404
{- "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:
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 |
Responses
Request samples
- Payload
{- "patient": "a7129932-7174-432d-a8dd-570510e145bb"
}Response samples
- 200
- 400
- 403
- 404
{- "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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
query Parameters
| date_from | string <date> Inclusive lower bound on |
| date_to | string <date> Inclusive upper bound on |
| page | integer A page number within the paginated result set. |
| page_size | integer Number of results to return per page. |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "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_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:
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"
|
| direction | string (Direction80cEnum) Enum: "sent" "received" "neither"
|
| outcome | string Enum: "success" "no_answer" "voicemail" "bounced" "bad_number" "other" What happened on the contact attempt. Only
|
| 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
- Payload
{- "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
- 201
- 403
{- "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:
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"
|
| direction | string (Direction80cEnum) Enum: "sent" "received" "neither"
|
| outcome | string Enum: "success" "no_answer" "voicemail" "bounced" "bad_number" "other" What happened on the contact attempt. Only
|
| 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
- Payload
{- "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
- 200
- 403
{- "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"
}Get the SMS consent row for a single patient
Convenience single-resource view for the patient's consent row.
Returns 404 when no row exists yet. The frontend (web#485) treats
a 404 as "default opted_in, no row yet" -- this matches the lazy-
create semantics of :class:SMSConsent (the row only materialises
once a STOP / START / first outbound hits the consent gate).
No GET-side row creation: a stray check from the staff UI should not leave an audit-noise OPTED_IN row behind on every patient profile the user happens to visit.
Authorizations:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "patient": "a7129932-7174-432d-a8dd-570510e145bb",
- "practice": "735297b8-a875-445a-9746-8588a75f65f2",
- "state": "opted_in",
- "opted_out_at": "2019-08-24T14:15:22Z",
- "opted_out_reason": "patient_request_stop",
- "last_help_replied_at": "2019-08-24T14:15:22Z",
- "first_disclosure_sent_at": "2019-08-24T14:15:22Z",
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "last_change_at": "2019-08-24T14:15:22Z",
- "last_change_by_id": "d4950a0a-bb95-4f49-9aa4-bcdeca1b4ba1",
- "review_notes": "string"
}Staff force-opt-in override for a patient's SMS consent
Staff-initiated SMS re-opt-in for a single (practice, patient) row.
CTIA / 10DLC permits manual re-opt-in only when the patient asks
for it, so this endpoint records review_notes from the staff
operator alongside the standard actor capture in the audit
document. Idempotent on an already-opted-in row -- the staff UI
can call it without first checking state and the audit trail still
captures the request (so a misclick is reviewable).
Behaviour:
- If no consent row exists, creates one in OPTED_IN.
- If OPTED_OUT, flips to OPTED_IN and clears opt-out audit columns.
- If already OPTED_IN, updates
review_notes+last_change_byand re-emits the audit event so the override is on record.
Emits sms.opted_in with metadata={"source": "staff_force_opt_in"}
on every call.
Authorizations:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
Request Body schema: required
| notes required | string [ 1 .. 1000 ] characters Why the override is warranted -- typically a paraphrase of the patient's verbal request. Required; stored on the consent row's |
Responses
Request samples
- Payload
{- "notes": "string"
}Response samples
- 200
- 403
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "patient": "a7129932-7174-432d-a8dd-570510e145bb",
- "practice": "735297b8-a875-445a-9746-8588a75f65f2",
- "state": "opted_in",
- "opted_out_at": "2019-08-24T14:15:22Z",
- "opted_out_reason": "patient_request_stop",
- "last_help_replied_at": "2019-08-24T14:15:22Z",
- "first_disclosure_sent_at": "2019-08-24T14:15:22Z",
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "last_change_at": "2019-08-24T14:15:22Z",
- "last_change_by_id": "d4950a0a-bb95-4f49-9aa4-bcdeca1b4ba1",
- "review_notes": "string"
}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:
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
- 200
[- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "patient": "a7129932-7174-432d-a8dd-570510e145bb",
- "practice": "735297b8-a875-445a-9746-8588a75f65f2",
- "state": "opted_in",
- "opted_out_at": "2019-08-24T14:15:22Z",
- "opted_out_reason": "patient_request_stop",
- "last_help_replied_at": "2019-08-24T14:15:22Z",
- "first_disclosure_sent_at": "2019-08-24T14:15:22Z",
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z",
- "last_change_at": "2019-08-24T14:15:22Z",
- "last_change_by_id": "d4950a0a-bb95-4f49-9aa4-bcdeca1b4ba1",
- "review_notes": "string"
}
]practice_sms_messages_list
List and create SMS messages for the practice.
Authorizations:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_sms_messages_create
List and create SMS messages for the practice.
Authorizations:
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 | string <= 32 characters E.164 destination override. Required when |
| 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
- Payload
{- "patient": "a7129932-7174-432d-a8dd-570510e145bb",
- "to_number": "string",
- "body": "string"
}Response samples
- 201
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
[- {
- "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"
}
]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:
path Parameters
| practice_uid required | string <uuid> |
query Parameters
| user | string Sentinel filter -- only |
Responses
Response samples
- 200
{- "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:
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
- Payload
{- "patient_id": "3854866a-5476-48be-8313-77029ccdd7a7",
- "last_read_at": "2019-08-24T14:15:22Z"
}Response samples
- 200
- 403
{- "patient_id": "3854866a-5476-48be-8313-77029ccdd7a7",
- "last_read_at": "2019-08-24T14:15:22Z"
}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:
path Parameters
| practice_uid required | string <uuid> |
Request Body schema:
| submitted_via | string Default: "kiosk" Enum: "kiosk" "portal" "staff_form" Source channel; defaults to
|
| 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
- Payload
{- "submitted_via": "kiosk",
- "personal_info": null,
- "insurance_info": null,
- "medical_history": null,
- "signature_b64": ""
}Response samples
- 403
{- "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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "submitted_via": "string",
- "submitted_at": "2019-08-24T14:15:22Z",
- "status": "string",
- "first_name": "string",
- "last_name": "string",
- "date_of_birth": "string",
- "approved_patient": "57687379-a30a-4785-a564-991cdb98b023",
- "merged_into_patient": "eae1c63b-a395-425f-a8d7-ec1627ff32ae"
}
]
}practice_intake_new_patient_drafts_retrieve
Full draft including JSON buckets.
Logs intake.draft_viewed on every GET because the body is PHI.
Authorizations:
path Parameters
| draft_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
path Parameters
| draft_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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
- Payload
{- "target_patient_uid": "e93aa6ec-2ecf-4b23-b671-922d08049e1d"
}Response samples
- 403
{- "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:
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
- Payload
{- "reason": "string"
}Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
[- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "string",
- "conversation_type": "direct",
- "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
- "participants": [
- {
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "first_name": "string",
- "last_name": "string",
- "last_read_at": "2019-08-24T14:15:22Z"
}
], - "last_message": {
- "property1": null,
- "property2": null
}, - "unread_count": 0,
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z"
}
]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:
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"
|
| title | string <= 255 characters Default: "" |
| operatory | string or null <uuid> |
| body | string Default: "" Optional first message body. |
Responses
Request samples
- Payload
{- "participant_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "conversation_type": "direct",
- "title": "",
- "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
- "body": ""
}Response samples
- 201
- 403
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "string",
- "conversation_type": "direct",
- "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
- "participants": [
- {
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "first_name": "string",
- "last_name": "string",
- "last_read_at": "2019-08-24T14:15:22Z"
}
], - "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:
path Parameters
| conversation_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "title": "string",
- "conversation_type": "direct",
- "operatory": "72ef68e1-2b4e-4e3b-9284-54c2c1c89045",
- "participants": [
- {
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "first_name": "string",
- "last_name": "string",
- "last_read_at": "2019-08-24T14:15:22Z"
}
], - "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:
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:
path Parameters
| conversation_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| conversation_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
[- {
- "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"
}
]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:
path Parameters
| practice_uid required | string <uuid> |
Request Body schema: required
| operatory_id required | string <uuid> |
Responses
Request samples
- Payload
{- "operatory_id": "700062e2-3e2d-40d4-aa03-805aad7e7b9e"
}Response samples
- 200
- 201
- 403
{- "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:
path Parameters
| operatory_uid required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Request Body schema: required
| operatory_id required | string <uuid> |
Responses
Request samples
- Payload
{- "operatory_id": "700062e2-3e2d-40d4-aa03-805aad7e7b9e"
}Response samples
- 403
{- "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:
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:
path Parameters
| operatory_id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
Responses
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:
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 ( |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "submitted_via": "string",
- "submitted_at": "2019-08-24T14:15:22Z",
- "status": "string",
- "first_name": "string",
- "last_name": "string",
- "date_of_birth": "string",
- "converted_to_patient": "9bc32040-0306-4132-bc06-10e779b712a9",
- "merged_into_patient": "eae1c63b-a395-425f-a8d7-ec1627ff32ae",
- "dedup_candidates": "string"
}
]
}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:
path Parameters
| id required | string |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
path Parameters
| id required | string |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
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
- Payload
{- "reason": ""
}Response samples
- 403
{- "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:
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
- Payload
{- "patient_id": "3854866a-5476-48be-8313-77029ccdd7a7"
}Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}practice_patient_prescription_list
List and create prescriptions.
GET /v1/practice/POST /v1/practice/
Query params
patient — filter by patient UUID
status — filter by status (draft/final/cancelled)
search — case-insensitive drug name search
Authorizations:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_create
List and create prescriptions.
GET /v1/practice/POST /v1/practice/
Query params
patient — filter by patient UUID
status — filter by status (draft/final/cancelled)
search — case-insensitive drug name search
Authorizations:
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.
|
| diagnosis_description | string <= 255 characters Brief clinical indication e.g. 'Post-extraction infection'. |
| appointment | string or null <uuid> |
| notes | string |
Responses
Request samples
- Payload
{- "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
- 201
- 403
{- "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/PATCH /v1/practice/
Only draft prescriptions may be edited. Use the /finalise/
action to advance to final.
Authorizations:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
| prescription_id required | string <uuid> |
Responses
Response samples
- 200
{- "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/PATCH /v1/practice/
Only draft prescriptions may be edited. Use the /finalise/
action to advance to final.
Authorizations:
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.
|
| diagnosis_description | string <= 255 characters Brief clinical indication e.g. 'Post-extraction infection'. |
| appointment | string or null <uuid> |
| notes | string |
Responses
Request samples
- Payload
{- "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
- 200
- 403
{- "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/PATCH /v1/practice/
Only draft prescriptions may be edited. Use the /finalise/
action to advance to final.
Authorizations:
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.
|
| diagnosis_description | string <= 255 characters Brief clinical indication e.g. 'Post-extraction infection'. |
| appointment | string or null <uuid> |
| notes | string |
Responses
Request samples
- Payload
{- "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
- 200
- 403
{- "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/
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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
| prescription_id required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}practice_patient_prescription_finalise_create
Finalise a draft prescription.
POST /v1/practice/
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:
path Parameters
| patient_id required | string <uuid> |
| practice_uid required | string <uuid> |
| prescription_id required | string <uuid> |
Responses
Response samples
- 403
{- "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/
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:
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/POST /v1/practice/
Query params
patient — filter by patient UUID
status — filter by status (draft/final/cancelled)
search — case-insensitive drug name search
Authorizations:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_create
List and create prescriptions.
GET /v1/practice/POST /v1/practice/
Query params
patient — filter by patient UUID
status — filter by status (draft/final/cancelled)
search — case-insensitive drug name search
Authorizations:
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.
|
| diagnosis_description | string <= 255 characters Brief clinical indication e.g. 'Post-extraction infection'. |
| appointment | string or null <uuid> |
| notes | string |
Responses
Request samples
- Payload
{- "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
- 201
- 403
{- "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/PATCH /v1/practice/
Only draft prescriptions may be edited. Use the /finalise/
action to advance to final.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
| prescription_id required | string <uuid> |
Responses
Response samples
- 200
{- "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/PATCH /v1/practice/
Only draft prescriptions may be edited. Use the /finalise/
action to advance to final.
Authorizations:
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.
|
| diagnosis_description | string <= 255 characters Brief clinical indication e.g. 'Post-extraction infection'. |
| appointment | string or null <uuid> |
| notes | string |
Responses
Request samples
- Payload
{- "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
- 200
- 403
{- "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/PATCH /v1/practice/
Only draft prescriptions may be edited. Use the /finalise/
action to advance to final.
Authorizations:
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.
|
| diagnosis_description | string <= 255 characters Brief clinical indication e.g. 'Post-extraction infection'. |
| appointment | string or null <uuid> |
| notes | string |
Responses
Request samples
- Payload
{- "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
- 200
- 403
{- "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/
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:
path Parameters
| practice_uid required | string <uuid> |
| prescription_id required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}practice_prescription_finalise_create
Finalise a draft prescription.
POST /v1/practice/
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:
path Parameters
| practice_uid required | string <uuid> |
| prescription_id required | string <uuid> |
Responses
Response samples
- 403
{- "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/
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:
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/POST /v1/practice/
Authorizations:
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
- 200
{- "count": 123,
- "results": [
- {
- "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_create
List and create practice prescription templates.
GET /v1/practice/POST /v1/practice/
Authorizations:
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"
|
| is_active | boolean |
Responses
Request samples
- Payload
{- "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
- 201
- 403
{- "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/PATCH /v1/practice/DELETE /v1/practice/
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
| template_id required | string <uuid> |
Responses
Response samples
- 200
{- "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/PATCH /v1/practice/DELETE /v1/practice/
Authorizations:
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"
|
| is_active | boolean |
Responses
Request samples
- Payload
{- "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
- 200
- 403
{- "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/PATCH /v1/practice/DELETE /v1/practice/
Authorizations:
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"
|
| is_active | boolean |
Responses
Request samples
- Payload
{- "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
- 200
- 403
{- "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/PATCH /v1/practice/DELETE /v1/practice/
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
| template_id required | string <uuid> |
Responses
Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}practice_portal_patient_submissions_list
List patient submissions for a practice.
GET /api/v1/practice/
Defaults to pending submissions. Use ?status=approved or
?status=rejected to filter.
Authorizations:
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
- 200
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": [
- {
- "count": 3,
- "next": null,
- "previous": null,
- "results": [
- {
- "id": "eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee",
- "practice": "99999999-9999-4999-8999-999999999999",
- "invite_token": "example-synthetic-token-DO-NOT-USE-0123456789",
- "invite_expires_at": "2026-05-20T00:00:00Z",
- "status": "pending",
- "submitted_at": null,
- "reviewed_at": null,
- "reviewed_by": null,
- "patient": null,
- "created": "2026-05-13T12:00:00Z"
}, - {
- "id": "ffffffff-ffff-4fff-8fff-ffffffffffff",
- "practice": "99999999-9999-4999-8999-999999999999",
- "invite_token": "example-synthetic-token-DO-NOT-USE-0123456789",
- "invite_expires_at": "2026-05-20T00:00:00Z",
- "status": "pending",
- "submitted_at": "2026-05-14T10:15:00Z",
- "reviewed_at": null,
- "reviewed_by": null,
- "patient": null,
- "created": "2026-05-13T12:00:00Z"
}, - {
- "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"
}
]
}
]
}practice_portal_patient_submissions_retrieve
Retrieve a single patient submission with full detail.
GET /api/v1/practice/
Authorizations:
path Parameters
| id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
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": {
- "first_name": "John",
- "last_name": "Doe",
- "email": "john.doe@example.com",
- "date_of_birth": "1990-04-12",
- "gender": "M",
- "phone_home": "+15555550100",
- "phone_mobile": "+15555550101",
- "phone_work": "",
- "address": "123 Example St",
- "address2": "",
- "city": "Springfield",
- "state": "IL",
- "zip_code": "62701",
- "insurance": {
- "carrier": "Synthetic Dental PPO",
- "subscriber_id": "SYN-000-0001",
- "group_number": "GRP-9999"
}, - "medical_history": {
- "allergies": [ ],
- "medications": [ ],
- "conditions": [ ]
}
}, - "rejection_reason": ""
}practice_portal_patient_submissions_approve_create
Approve a patient submission — creates a Patient record.
POST /api/v1/practice/
Extracts demographics from submitted_data to create the
Patient record, links it to the submission, and sets
status=approved.
Authorizations:
path Parameters
| id required | string <uuid> |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
- 403
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": {
- "first_name": "John",
- "last_name": "Doe",
- "email": "john.doe@example.com",
- "date_of_birth": "1990-04-12",
- "gender": "M",
- "phone_home": "+15555550100",
- "phone_mobile": "+15555550101",
- "phone_work": "",
- "address": "123 Example St",
- "address2": "",
- "city": "Springfield",
- "state": "IL",
- "zip_code": "62701",
- "insurance": {
- "carrier": "Synthetic Dental PPO",
- "subscriber_id": "SYN-000-0001",
- "group_number": "GRP-9999"
}, - "medical_history": {
- "allergies": [ ],
- "medications": [ ],
- "conditions": [ ]
}
}, - "rejection_reason": ""
}practice_portal_patient_submissions_reject_create
Reject a patient submission with a reason.
POST /api/v1/practice/
Authorizations:
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
- Payload
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
- 200
- 403
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": {
- "first_name": "John",
- "last_name": "Doe",
- "email": "john.doe@example.com",
- "date_of_birth": "1990-04-12",
- "gender": "M",
- "phone_home": "+15555550100",
- "phone_mobile": "+15555550101",
- "phone_work": "",
- "address": "123 Example St",
- "address2": "",
- "city": "Springfield",
- "state": "IL",
- "zip_code": "62701",
- "insurance": {
- "carrier": "Synthetic Dental PPO",
- "subscriber_id": "SYN-000-0001",
- "group_number": "GRP-9999"
}, - "medical_history": {
- "allergies": [ ],
- "medications": [ ],
- "conditions": [ ]
}
}, - "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/
Only Office Manager or above may generate invites. Creates a
PatientSubmission with a unique token and 7-day expiry.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 201
- 403
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"
}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:
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 |
| 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: |
Responses
Response samples
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "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_mime_type": "string",
- "attached_content_type": "string",
- "object_id": "string",
- "signed_at": "2019-08-24T14:15:22Z",
- "created": "2019-08-24T14:15:22Z"
}
]
}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:
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.
|
| 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
- Payload
Response samples
- 201
- 403
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| signature_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
path Parameters
| practice_uid required | string <uuid> |
| signature_uid required | string <uuid> |
Responses
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/withoption_id. - results: GET
/poll/{id}/results/(403 if poll not yet expired). - active_count: GET
/poll/active-count/for badge display.
Authorizations:
path Parameters
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
[- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "question": "string",
- "is_anonymous": true,
- "expires_at": "2019-08-24T14:15:22Z",
- "is_expired": true,
- "option_count": "string",
- "has_voted": "string",
- "created_by_name": "string",
- "created": "2019-08-24T14:15:22Z"
}
]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/withoption_id. - results: GET
/poll/{id}/results/(403 if poll not yet expired). - active_count: GET
/poll/active-count/for badge display.
Authorizations:
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
- Payload
{- "question": "string",
- "is_anonymous": true,
- "expires_at": "2019-08-24T14:15:22Z",
- "options": [
- {
- "text": "string",
- "sort_order": 0
}
]
}Response samples
- 201
- 403
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "question": "string",
- "is_anonymous": true,
- "expires_at": "2019-08-24T14:15:22Z",
- "options": [
- {
- "text": "string",
- "sort_order": 0
}
]
}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/withoption_id. - results: GET
/poll/{id}/results/(403 if poll not yet expired). - active_count: GET
/poll/active-count/for badge display.
Authorizations:
path Parameters
| id required | string |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "question": "string",
- "is_anonymous": true,
- "expires_at": "2019-08-24T14:15:22Z",
- "is_expired": true,
- "options": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "text": "string",
- "sort_order": 0
}
], - "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/withoption_id. - results: GET
/poll/{id}/results/(403 if poll not yet expired). - active_count: GET
/poll/active-count/for badge display.
Authorizations:
path Parameters
| id required | string |
| practice_uid required | string <uuid> |
Responses
Response samples
- 403
{- "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:
path Parameters
| id required | string |
| practice_uid required | string <uuid> |
Responses
Response samples
- 200
{- "poll_id": "712230da-d683-493a-8a4d-ca41e4ceb233",
- "question": "string",
- "is_anonymous": true,
- "total_votes": 0,
- "options": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "text": "string",
- "vote_count": 0,
- "voters": [
- "string"
]
}
]
}practice_voting_poll_vote_create
Cast a vote on this poll. Returns 409 if the user already voted.
Authorizations:
path Parameters
| id required | string |
| practice_uid required | string <uuid> |
Request Body schema: required
| option_id required | string <uuid> |
Responses
Request samples
- Payload
{- "option_id": "ab22e710-5ce4-4e7e-a3db-bd6fdad8fe36"
}Response samples
- 403
{- "detail": "This practice or its parent organization is disabled.",
- "code": "inactive_practice"
}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:
Responses
Response samples
- 200
[- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "slug": "string",
- "display_name": "string",
- "description": "string",
- "monthly_price_cents": 0,
- "max_practices": 0,
- "max_users_per_practice": 0,
- "includes_fax": true,
- "includes_sms": true,
- "api_rate_limit_per_minute": 0
}
]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:
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
- 200
{- "count": 123,
- "results": [
- {
- "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",
- "status": "new",
- "assigned_to": "b9f52997-ff03-4166-bbff-22fd35e12939",
- "assigned_to_email": "user@example.com",
- "created": "2019-08-24T14:15:22Z",
- "modified": "2019-08-24T14:15:22Z"
}
]
}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:
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).
|
| 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
- Payload
{- "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
- 201
{- "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:
path Parameters
| issue_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
path Parameters
| issue_uid required | string <uuid> |
Request Body schema:
| status | string Enum: "new" "triaged" "resolved" "wontfix" Triage state.
|
| 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
- Payload
{- "status": "new",
- "assigned_to": "b9f52997-ff03-4166-bbff-22fd35e12939",
- "resolution_note": "string"
}Response samples
- 200
{- "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"
}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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "tech_email": "string",
- "user_email": "string",
- "practice_id": "ab8b92c6-fdd4-4c27-ab69-c61896d976bd",
- "status": "pending",
- "code_expires_at": "2019-08-24T14:15:22Z",
- "redeemed_at": "2019-08-24T14:15:22Z",
- "ended_at": "2019-08-24T14:15:22Z",
- "livekit_room_id": "string",
- "created": "2019-08-24T14:15:22Z"
}
]
}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:
Responses
Response samples
- 201
{- "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:
path Parameters
| session_id required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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.A "redeem-or-bust" atomic block that flips the row to ACTIVE, mints the publisher token, and emits the REDEEMED audit event. On :class:
LiveKitNotConfiguredthe block rolls back so the user does not end up associated with a session it cannot connect to.
Authorizations:
Request Body schema: required
| code required | string [ 1 .. 32 ] characters |
Responses
Request samples
- Payload
{- "code": "string"
}Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "status": "string",
- "livekit_url": "string",
- "livekit_token": "string",
- "livekit_room": "string",
- "token_expires_at": 0
}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:
Responses
Response samples
- 200
[- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "application": 0,
- "application_name": "string",
- "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
- "client_name": "string",
- "events": null,
- "all_practices": true,
- "practices": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "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_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:
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
- Payload
{- "application": 0,
- "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
- "events": null,
- "all_practices": true,
- "practices": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "custom_data": null
}Response samples
- 201
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "application": 0,
- "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
- "events": null,
- "all_practices": true,
- "practices": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "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:
path Parameters
| subscription_uid required | string <uuid> |
Responses
Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "application": 0,
- "application_name": "string",
- "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
- "client_name": "string",
- "events": null,
- "all_practices": true,
- "practices": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "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:
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
- Payload
{- "application": 0,
- "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
- "events": null,
- "all_practices": true,
- "practices": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "custom_data": null
}Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "application": 0,
- "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
- "events": null,
- "all_practices": true,
- "practices": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "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:
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
- Payload
{- "application": 0,
- "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
- "events": null,
- "all_practices": true,
- "practices": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "custom_data": null
}Response samples
- 200
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "application": 0,
- "client": "95b7f642-4812-4c19-ba03-689f2fdf42f8",
- "events": null,
- "all_practices": true,
- "practices": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "custom_data": null
}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:
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
- 200
{- "count": 123,
- "results": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "event_type": "string",
- "payload": null,
- "response_status": 0,
- "response_body": "string",
- "attempts": 0,
- "next_retry_at": "2019-08-24T14:15:22Z",
- "status": "pending",
- "created": "2019-08-24T14:15:22Z"
}
]
}xrays_sessions_retrieve
Get capture session status for crash recovery.
Returns session state, image count, and template info.
Authorizations:
path Parameters
| session_uid required | string <uuid> |
Responses
Response samples
- 200
{- "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:
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
- 201
{- "template_slot": "a8f6b7f7-6b3b-48c7-a4e4-e20bd837e2e6",
- "image_type": "pa",
- "capture_device": "string",
- "tooth_numbers": null,
- "description": "string",
- "notes": "string"
}