@rinse-dental/open-dental
v4.1.0
Published
A TypeScript library for easily accessing Open Dental APIs.
Downloads
309
Readme
@rinse-dental/open-dental
An unofficial TypeScript/Node.js SDK for the Open Dental REST API.
Open Dental version coverage: This release is synchronized with Open Dental v26.1.12 (beta) and covers every API endpoint documented as of that version.
Installation
npm install @rinse-dental/open-dentalQuick Start
import { OpenDental } from '@rinse-dental/open-dental';
// Initialize once at application startup (the SDK appends /api/v1 automatically)
OpenDental.initialize(
'https://your-open-dental-server.example.com', // base URL — no trailing slash
'YOUR_API_TOKEN', // Base64 "ODFHIR {DeveloperKey}/{CustomerKey}" token
);
// Use any resource
const patients = OpenDental.Patients();
const results = await patients.getPatients({ LName: 'Smith' });
console.log(results);Initialization
OpenDental.initialize(baseURL, authToken, options?) must be called once before any other method. All subsequent calls reuse the same HTTP client.
| Parameter | Type | Required | Description |
|--------------------|---------|----------|----------------------------------------------------------|
| baseURL | string | Yes | Root URL of your Open Dental server (no trailing slash). |
| authToken | string | Yes | Base64-encoded ODFHIR {DeveloperKey}/{CustomerKey} API token. |
| options.timeout | number | No | Request timeout in milliseconds. Default: 30000. |
| options.debug | boolean | No | Log HTTP errors to console (strips PHI). Default: false. |
// Minimal
OpenDental.initialize(
process.env.OPEN_DENTAL_BASEURL!,
process.env.OPEN_DENTAL_API_KEY!
);
// With options
OpenDental.initialize(
process.env.OPEN_DENTAL_BASEURL!,
process.env.OPEN_DENTAL_API_KEY!,
{
timeout: 15_000, // 15 seconds
debug: process.env.NODE_ENV !== 'production',
}
);Error Handling
All API errors throw a standard JavaScript Error with the message:
API Error (Status <code>): <message>Wrap calls in try/catch:
try {
const appt = await OpenDental.Appointments().getAppointment(12345);
} catch (err) {
console.error(err.message); // "API Error (Status 404): Not found"
}Available Resources
Every resource is accessed via a factory method on OpenDental. Each factory returns a class instance pre-configured with the shared HTTP client.
| Factory Method | API Endpoint | Description |
|---|---|---|
| OpenDental.AccountModules() | /accountmodules | Account sub-resource data for a patient |
| OpenDental.Adjustments() | /adjustments | Ledger adjustments |
| OpenDental.Allergies() | /allergies | Patient allergy records |
| OpenDental.AllergyDefs() | /allergydefs | Allergy definition master list |
| OpenDental.AppointmentTypes() | /appointmenttypes | Appointment type definitions |
| OpenDental.Appointments() | /appointments | Patient appointments |
| OpenDental.ApptFieldDefs() | /apptfielddefs | Custom appointment field definitions |
| OpenDental.ApptFields() | /apptfields | Custom appointment field values |
| OpenDental.AsapComms() | /asapcomm | ASAP list communications |
| OpenDental.AutoNoteControls() | /autonotecontrols | Auto note control definitions |
| OpenDental.AutoNotes() | /autonotes | Auto note templates |
| OpenDental.Benefits() | /benefits | Insurance plan benefits |
| OpenDental.Carriers() | /carriers | Insurance carriers |
| OpenDental.ChartModules() | /chartmodules | Chart module data for a patient |
| OpenDental.ClaimPayments() | /claimpayments | Insurance claim payments (EOBs) |
| OpenDental.ClaimProcs() | /claimprocs | Claim procedure line items |
| OpenDental.ClaimTrackings() | /claimtrackings | Claim tracking history |
| OpenDental.Claims() | /claims | Insurance claims |
| OpenDental.Clinics() | /clinics | Clinic locations |
| OpenDental.ClockEvents() | /clockevents | Employee time clock punches |
| OpenDental.CodeGroups() | /codegroups | Procedure code groups |
| OpenDental.CommLogs() | /commlogs | Patient communication logs |
| OpenDental.Computers() | /computers | Registered workstations |
| OpenDental.CovCats() | /covcats | Insurance coverage categories |
| OpenDental.CovSpans() | /covspans | Insurance coverage spans |
| OpenDental.Definitions() | /definitions | Definition list items (dropdowns) |
| OpenDental.DiseaseDefs() | /diseasedefs | Disease/problem definition master list |
| OpenDental.DiscountPlanSubs() | /discountplansubs | Patient discount plan subscriptions |
| OpenDental.DiscountPlans() | /discountplans | In-house discount plan definitions |
| OpenDental.Diseases() | /diseases | Patient problem/disease records |
| OpenDental.Documents() | /documents | Patient document/image records |
| OpenDental.ETrans() | /etrans | Electronic transaction records |
| OpenDental.ETransMessageTexts() | /etransmessagetexts | Raw electronic transaction message text |
| OpenDental.ETranss() | /etranss | Bulk electronic transaction listing |
| OpenDental.EhrPatients() | /ehrpatients | EHR/Meaningful Use patient data |
| OpenDental.Employees() | /employees | Employee records |
| OpenDental.Employers() | /employers | Employer records |
| OpenDental.EobAttaches() | /eobattaches | EOB attachment images |
| OpenDental.Events() | /events | Server audit-trail events |
| OpenDental.FamilyModules() | /familymodules | Family module data |
| OpenDental.FeeScheds() | /feescheds | Fee schedule records |
| OpenDental.Fees() | /fees | Individual fee records |
| OpenDental.HistAppointments() | /histappointments | Appointment change history |
| OpenDental.InsPlans() | /insplans | Insurance plan records |
| OpenDental.InsSubs() | /inssubs | Insurance subscriber records |
| OpenDental.InsVerifies() | /insverifies | Insurance verification records |
| OpenDental.LabCases() | /labcases | Dental lab case records |
| OpenDental.LabTurnarounds() | /labturnarounds | Lab turnaround time records |
| OpenDental.Laboratories() | /laboratories | Dental laboratory records |
| OpenDental.MedicationPats() | /medicationpats | Patient medication records |
| OpenDental.Medications() | /medications | Medication definition master list |
| OpenDental.Operatories() | /operatories | Operatory (treatment room) records |
| OpenDental.PatFieldDefs() | /patfielddefs | Custom patient field definitions |
| OpenDental.PatFields() | /patfields | Custom patient field values |
| OpenDental.PatPlans() | /patplans | Patient insurance plan enrollments |
| OpenDental.PatientNotes() | /patientnotes | Patient note fields (financial, medical, etc.) |
| OpenDental.PatientRaces() | /patientraces | Patient race/ethnicity records |
| OpenDental.Patients() | /patients | Patient records |
| OpenDental.PayPlanCharges() | /payplancharges | Payment plan charge records |
| OpenDental.PayPlans() | /payplans | Payment plan records |
| OpenDental.PaySplits() | /paysplits | Payment allocation splits |
| OpenDental.Payments() | /payments | Patient payments |
| OpenDental.PerioExams() | /perioexams | Periodontal exam records |
| OpenDental.PerioMeasures() | /periomeasures | Periodontal measurement records |
| OpenDental.Pharmacies() | /pharmacies | Pharmacy records |
| OpenDental.Popups() | /popups | Patient chart popup messages |
| OpenDental.Preferences() | /preferences | Global practice preferences |
| OpenDental.ProcNotes() | /procnotes | Procedure notes |
| OpenDental.ProcTPs() | /proctps | Treatment plan procedures |
| OpenDental.ProcedureCodes() | /procedurecodes | ADA CDT procedure code definitions |
| OpenDental.ProcedureLogs() | /procedurelogs | Procedure log records |
| OpenDental.Providers() | /providers | Provider records |
| OpenDental.Queries() | /queries | Arbitrary read-only SQL queries |
| OpenDental.QuickPasteCats() | /quickpastecats | Quick-paste category records |
| OpenDental.QuickPasteNotes() | /quickpastenotes | Quick-paste note templates |
| OpenDental.RecallTypes() | /recalltypes | Recall type definitions |
| OpenDental.Recalls() | /recalls | Patient recall records |
| OpenDental.RefAttaches() | /refattaches | Referral attachment records |
| OpenDental.Referrals() | /referrals | Referral source/destination records |
| OpenDental.Reports() | /reports | Built-in Open Dental reports |
| OpenDental.RxPats() | /rxpats | Prescription records |
| OpenDental.ScheduleOps() | /scheduleops | Schedule-to-operatory links |
| OpenDental.Schedules() | /schedules | Provider/blockout schedule blocks |
| OpenDental.Security() | /security | User security settings |
| OpenDental.SecurityLogs() | /securitylogs | Security audit log entries |
| OpenDental.SheetDefs() | /sheetdefs | Sheet template definitions |
| OpenDental.SheetFields() | /sheetfields | Sheet template field definitions |
| OpenDental.Sheets() | /sheets | Filled-out sheet instances |
| OpenDental.SignalODs() | /signalods | Real-time server signal records |
| OpenDental.Statements() | /statements | Patient billing statements |
| OpenDental.Subscriptions() | /subscriptions | Webhook event subscriptions |
| OpenDental.SubstitutionLinks() | /substitutionlinks | Tooth material substitution rules |
| OpenDental.TaskLists() | /tasklists | Task list folders |
| OpenDental.TaskNotes() | /tasknotes | Task comments/notes |
| OpenDental.Tasks() | /tasks | Task records |
| OpenDental.ToothInitials() | /toothInitials | Existing tooth chart conditions |
| OpenDental.TreatmentPlanAttaches() | /treatplanattaches | Procedure-to-treatment-plan links |
| OpenDental.TreatmentPlans() | /treatplans | Treatment plan records |
| OpenDental.UserGroupAttaches() | /usergroupattaches | User-to-group memberships |
| OpenDental.UserGroups() | /usergroups | User security groups |
| OpenDental.UserODs() | /userods | Open Dental user accounts |
| OpenDental.Transformers() | — | Stateless data transformation utilities |
Usage Examples
Patients
const patients = OpenDental.Patients();
// Search patients
const results = await patients.getPatients({ LName: 'Smith', FName: 'John' });
// Get a single patient
const patient = await patients.getPatient(1234);
// Create a patient
const newPatient = await patients.createPatient({
LName: 'Smith',
FName: 'Jane',
Birthdate: '1985-06-15',
});
// Update a patient
const updated = await patients.updatePatient({ PatNum: 1234, WirelessPhone: '555-867-5309' });Appointments
const appts = OpenDental.Appointments();
// Fetch appointments for a date range
const list = await appts.getAppointments({
dateStart: '2026-01-01',
dateEnd: '2026-01-31',
});
// Create an appointment
const newAppt = await appts.createAppointment({
PatNum: 1234,
AptDateTime: '2026-03-15 09:00:00',
Op: 3,
ProvNum: 2,
});
// Break an appointment
await appts.breakAppointment(apptNum, { sendToUnscheduledList: 'true' });Payments
const payments = OpenDental.Payments();
// Create a payment
const payment = await payments.createPayment({
PatNum: 1234,
PayAmt: '150.00',
PayNote: 'Visa ending in 4242',
});
// Refund a payment
const refund = await payments.refundPayment({
PayNum: 567,
RefundAmt: 75.00,
PayNote: 'Partial refund',
});Queries (read-only SQL)
const queries = OpenDental.Queries();
// Short query (up to 100 rows)
const rows = await queries.shortQuery<{ PatNum: number; LName: string }>({
SqlCommand: "SELECT PatNum, LName FROM patient WHERE LName = 'Smith' LIMIT 10",
});
// Larger query — results exported to SFTP
await queries.runQuery({ SqlCommand: 'SELECT * FROM procedurelog' });Insurance Benefits
const benefits = OpenDental.Benefits();
// List benefits for a plan
const list = await benefits.getBenefits({ PlanNum: 42 });
// Create a benefit
const benefit = await benefits.createBenefit({
PlanNum: 42,
BenefitType: 'Percentage',
Percent: 80,
CovCatNum: 3,
});
// Delete a benefit (note: method renamed from v3.4.x — see Breaking Changes)
await benefits.deleteBenefit(benefitNum);Date Utilities
Open Dental returns dates and datetimes without timezone information — they reflect the local clock of the Open Dental server. Use toISO to convert these to ISO 8601 UTC strings before storing or comparing them in your application.
import { toISO } from '@rinse-dental/open-dental';
// Datetime string — "yyyy-MM-dd HH:mm:ss"
toISO("2021-08-05 02:00:00", "America/Los_Angeles");
// => "2021-08-05T09:00:00.000Z" (PDT, UTC-7)
// Date-only string — interpreted as midnight in the given timezone
toISO("2021-08-05", "America/Los_Angeles");
// => "2021-08-05T07:00:00.000Z" (PDT, UTC-7)Pass an IANA timezone name matching your Open Dental server's configured timezone. DST transitions are handled automatically. Strings that don't match either format are returned unchanged.
Typical usage after an API call:
const appt = await OpenDental.Appointments().getAppointment(12345);
const TZ = "America/Los_Angeles";
const startISO = toISO(appt.AptDateTime, TZ);
const endISO = toISO(appt.AptDateTimeEnd, TZ);API Documentation (Docs/)
This package includes the full Open Dental API reference documentation in the Docs/ folder, enriched with database schema mappings and field-level notes for every endpoint. These markdown files are optimized for AI-assisted development.
Docs/
└── Open Dental 2026-04-22/
├── api-url-list.md — Master list of all API URLs
├── apiappointments.md
├── apipatients.md
├── apibenefits.md — Enriched with X12 mappings and DB schema
└── ... — One file per API resourceBreaking Changes
v4.0.0
The following changes are breaking relative to v3.x.
ChartModules.PatientInfo() → ChartModules.getPatientInfo()
The method was renamed to follow the SDK's getX() naming convention.
// Before (v3.x)
const info = await OpenDental.ChartModules().PatientInfo(patNum);
// After (v4.0.1)
const info = await OpenDental.ChartModules().getPatientInfo(patNum);Benefits.deletePatPlan() → Benefits.deleteBenefit()
The method was renamed to correctly reflect that it deletes a benefit record, not a patient plan.
// Before (v3.x)
await OpenDental.Benefits().deletePatPlan(benefitNum);
// After (v4.0.0)
await OpenDental.Benefits().deleteBenefit(benefitNum);RefAttaches.deleteInsSub() → RefAttaches.deleteRefAttach()
The method was incorrectly named after a different resource. It has been corrected.
// Before (v3.x)
await OpenDental.RefAttaches().deleteInsSub(refAttachNum);
// After (v4.0.0)
await OpenDental.RefAttaches().deleteRefAttach(refAttachNum);InsVerifies.createInsVerifies() now correctly uses POST
Previously this method called PUT /insverifies instead of POST /insverifies. Any consumers relying on the incorrect behavior should verify their integration.
API errors now throw Error instances
Previously, API errors threw the raw Axios response object. They now throw a standard Error with a descriptive message string. Update any catch blocks that inspected err.status or err.data directly:
// Before (v3.x) — err was an AxiosResponse
catch (err: any) {
console.log(err.status);
}
// After (v4.0.1) — err is an Error
catch (err: unknown) {
if (err instanceof Error) console.log(err.message);
}All GET list endpoints now accept Limit, DateFormatString, and DateTimeFormatString
These are additive and non-breaking for existing callers, but consumers relying on receiving all results in a single call should be aware of the 1000-item hard limit per request.
// Paginate through results
const page1 = await OpenDental.Appointments().getAppointments({ Offset: 0, Limit: 1000 });
const page2 = await OpenDental.Appointments().getAppointments({ Offset: 1000, Limit: 1000 });
// Custom date format
const patients = await OpenDental.Patients().getPatients({ DateFormatString: "MM/dd/yyyy" });TypeScript Support
The SDK ships with full TypeScript definitions. All request parameters and response shapes are typed. Import types directly from the package:
import type { Patient } from '@rinse-dental/open-dental/dist/types/patientTypes';
import type { Appointment } from '@rinse-dental/open-dental/dist/types/appointmentTypes';License
MIT © Rinse Dental Inc.
