What the two broken-appointment codes cover and how OpenDental posts them, so the no-show and cancellation rates mean the same thing at every desk.
D9986 is the CDT code for a missed appointment and D9987 the code for a cancelled one. CDT does not say how much notice separates them, so the office decides where the line falls. OpenDental's manual uses D9987 for a cancellation with less than 24 hours' notice; OpenDental's blog files that late call under D9986 and keeps D9987 for cancellations with more notice. When every broken appointment gets one of the two codes by the same written rule, the no-show and cancellation rates become numbers you can compare over time and office to office.
The CDT codes glossary entry covers how the American Dental Association's code set is organized, and the current CDT manual is its authority; the dental no-show rate definition covers what counts as a no-show and the formula. This page sets one house convention, built on OpenDental's manual; the convention matters less than using it at every desk.
Both codes sit in the adjunctive general services category, the D9000 range. The ADA added them to that section in CDT 2015 (Dental Products Report covered it at the time). They record something that happened to the schedule, not in the mouth.
Neither code describes a service, and payers typically do not reimburse missed or cancelled appointments, as a Dental Economics article on nonclinical codes notes. So the fee can be zero: the chart line is the record, and with both codes set not to bill insurance, nothing should go on a claim. A missed-appointment fee, if your policy charges one, is the patient's, within limits. Payer contracts can restrict what you may charge a covered patient, and the ADA's resource for Medicaid providers on missed appointments notes that federal statutes and regulations exclude Medicaid beneficiaries from such charges, and advises one appointment policy for every patient. Record the miss for everyone, and let any fee follow your dental cancellation policy and your contracts.
The numbers only hold if the same event gets the same code at every desk. The rows follow the glossary, adding the OpenDental step and the code: a call on the visit day is a short-notice cancellation, an earlier call inside the policy window a late one. Match the window to your policy and hold every office to it.
| What happened | In OpenDental | Code | Feeds |
|---|---|---|---|
| Did not arrive, did not call | Break, Missed | D9986 | No-show rate |
| Called on the day of the visit | Break, Cancelled | D9987 | D9987 rate and short-notice rate |
| Called before the day, with less notice than your policy requires | Break, Cancelled | D9987 | D9987 rate and late cancellation rate |
| Called with the notice your policy asks for | Reschedule, or send to the Unscheduled List without breaking | None | Nothing: ordinary scheduling |
| The office moved the visit | Reschedule, do not break | None | Nothing: track it apart |
| Arrived too late to be seen | Your call, made once | D9986 or none | No-show rate, if coded |
Four rows are house decisions CDT does not settle. Both D9987 rows follow OpenDental's manual; an office following its blog codes those calls D9986, and a 48-hour policy makes D9987 cover 48 hours. A visit the office moves because a provider is out is not the patient's miss; coding it hides a staffing problem inside a patient number. Code the late arrival or rebook it quietly, but do not switch week to week.
A break comes from the toolbar, the right-click menu, or the Edit Appointment window, and the appointment then shows crossed out. The Break Appointment manual page has the steps; what the numbers show depends on one report and a few preferences.
OpenDental's Broken Appointments report, in Standard Reports under Lists, counts three ways: by procedures (a completed D9986 or D9987), by adjustments, or by appointment status. The third, the manual warns, only includes appointments still on the book, so a break sent to the Unscheduled List, rescheduled, or deleted drops out, and the office that rebooks every break the same day looks like it has almost no breaks. D9986 and D9987 post as completed procedures, so they stay on the report after the appointment moves, and they carry the no-show versus cancellation split.
The preference is Broken appointment procedure type: None, Missed, Cancelled, or Both. At None, a break posts no code and, unless adjustments are on, the report defaults to appointment status. At Both, one menu asks for Missed (D9986) or Cancelled (D9987) and where the appointment goes: deleted, the Unscheduled List, the Pinboard, or left crossed out. At Missed or Cancelled alone, the split is gone.
The report by procedures gives two counts directly: D9986 lines for the no-show rate, and D9987 lines for a D9987 cancellation rate holding the glossary's short-notice and late cancellations together. Each rate is its count divided by scheduled appointments, times 100, where scheduled means the period's completed appointments plus its D9986 and D9987 lines. Full-notice cancellations carry no code and stay out, as the glossary permits.
| Number | Counts | Where it comes from | Owner | Review |
|---|---|---|---|---|
| No-show rate | D9986 lines | Broken Appointments report, by procedures, missed | Scheduling coordinator | Weekly, per provider and office |
| D9987 cancellation rate | All D9987 lines, same-day and late | Same report, by procedures, cancelled | Scheduling coordinator | Monthly, per office |
| Short-notice cancellation rate | D9987 lines broken on the visit day | No stock report splits it: a chart review of each D9987 note, or a query | Office manager | Monthly, per office |
| Late cancellation rate | The remaining D9987 lines | The same review or query | Office manager | Monthly, beside the policy |
| Scheduled appointments (the denominator) | Completed appointments plus all D9986 and D9987 lines | A User Query for the completed count; the report for the codes | Office manager | With each rate |
The split lives in the procedure note, which the report's columns (date, provider, code, patient, fee) leave out. OpenDental writes the original appointment date into each note by default, but staff can edit the note and the procedure date, so a same-day count means opening each D9987 in the chart or querying the notes.
Build the denominator from a completed count and the codes, not the book: a rescheduled break sits on a new date, one on the Unscheduled List has left the book, and counting only completed appointments keeps a crossed-out break from counting twice. The stock Appointments report lists a period's appointments with no status column and no total, so pull the completed count with a User Query, OpenDental's tool for data beyond the standard reports. The report dates each code by the day of the break, so read cancellations monthly or count by the appointment date in the note. Each code's provider and clinic default to the appointment's; leave them, so every count covers the same providers and clinics.
An illustrative month at one office: 24 D9986 lines and 36 D9987 lines, 16 of them on the visit day. That is three jobs: 24 no-shows to call, 16 same-day gaps for the fill list, and 20 late cancellations that show whether the policy works. One blended rate hides all three.
The codes also decide when the policy applies. A second-miss clause needs a count per patient over twelve months, and the patient's chart already lists their D9986 and D9987 lines; the report stays the office total. Without the codes, telling a first miss from a fourth means digging through commlogs one patient at a time.
Skip D9986 and the report by procedures reads zero while the misses hide in commlogs. The code is how the miss survives the rebooking.
In a single office, the comparison is this month against last, and the rule has to survive turnover, or the trend line measures the new hire. A group also compares offices, and the setup decides how.
If the offices share one OpenDental database with Clinics on, the Broken Appointments report groups lines by clinic but totals the count only across all clinics, so count each clinic's rows or run it per clinic. The risk there is at the desk: one office picks Missed for a same-day call, another Cancelled. If each office runs its own database, check the preferences in each, because settings drift: one office runs Both and codes every break; another left the preference at None, so its rebooked breaks drop off the status count, and it looks better by counting less.
Put the recording rule on one page and use the same preferences everywhere. Once a month, spot check each office: five appointments moved to a new date, for a cancellation never coded, and five broken ones, for the right code. The dental KPIs post gives eleven numbers a formula, an owner, and a cadence; count its no-show row by procedures, as above.
A missed visit that never gets rebooked turns into overdue recall or unscheduled treatment, and that is the list we built. MyDentalForce Patient Outreach builds one ranked daily call list per office from that office's own OpenDental, covering due and overdue hygiene recall, unscheduled treatment, and lapsed patients, rebuilt every morning. Every call outcome is logged and written back to the practice management system, and managers see each office's activity and results without asking. The list is per office, so a single practice gets the same thing a group does. MyDentalForce runs the daily operations of a 19-office Houston group.
D9986 is a missed appointment and D9987 a cancelled one; where the line falls is your call, so write the rule down. In OpenDental, set Broken appointment procedure type to Both, force a break before rescheduling, and count by procedures. Report a no-show rate and a D9987 cancellation rate over completed appointments plus both codes; split out the short-notice rate by chart review or query. If the first count looks suspiciously low, check the preferences before celebrating.

Book a 30-minute walkthrough and we will run it on your own offices.
or email us at info@mydentalforce.com