API Implementation

See API Specification

Style

Resources in the URL are lowercase plural. Example: /patients

Resource identifiers are the database primary keys and are specified in the URL instead of as a parameter for individual resources. Example: /patients/421

When creating a resource (PUT) or retrieving a list, no identifier is used. Example: /patients

All fields and parameters use Pascal casing, where the first letter is capitalized, and optional other letters are capitalized. This is different than the style of most other REST implementations, but it is far more consistent with our existing codebase and db schema.

Fields can start with lower case whenever they are not standard database fields. See details below, in the Data Types section.

Parameters are listed in this documentation in order of importance instead of db order. Fields returned in JSON files are generally in the same order as in the database.

Some methods do not fall under the normal CRUD paradigm. Here are some examples:
/claimprocs/InsAdjust
/appointments/123/Confirm
/queries

Pagination

For any method that returns a list of items, you will need to use pagination to get chunks of up to 100 items at a time. Use Limit and Offset. Limit is usually not specified, and it defaults to the hard limit of 100 items for any request. With no Limit or Offset specified, results will include items 0 through 99. Here's a typical example:
GET /items?Offset=400
This will return items 400 through 499. The risk of page drift, where another record is added to the database in the middle of a series of requests, is miniscule.

The general strategy you should use is to first perform an ordinary GET without any offset or limit. If your result is exactly 100 rows, then perform sequential GETs with offsets until your result is less than 100 rows.

The local API has an increased limit of 1000 items per request.

URL

The current version of the API has the following endpoint:
https://api.opendental.com/api/v1

Example usage:
GET https://api.opendental.com/api/v1/patients

Our intent is to never change this URL, but if there is an important breaking change in the future, then we may create v2, etc. These version numbers do not correspond to versions of Open Dental. This API is intended to work smoothly with multiple versions of Open Dental. But the version of the customer database must be at least as high as the version that the method was added.

URL Parameter Encoding

Use percent encoding for all reserved characters in the URL query parameters. Quotes are not used in URL parameters. For example, De Angelo would be encoded as De%20Angelo.

Headers

All API requests require a Content-Type header of "application/json".

Body

In PUT and POST requests, the JSON body can have a maximum content length of 16.8M characters.

Data Types

This API documentation does not generally repeat information which can be found in the Schema.
So we frequently just list out the fields available for a resource without further explanation.

Enumerations: These are stored in the database as numbers, but this API uses the text equivalent.
Example: "Male" instead of 0. Fields are still capitalized, just like the original.

Booleans: Fields that are boolean in the database are string in the API, either "true" or "false".

Dates: String with this format: yyyy-MM-dd.

DateTime: String with this format: yyyy-MM-dd HH:mm:ss, which is a 24hr format.

Foreign Keys: These are stored in the database as numbers, but we frequently use a string version for parameters and fields. The string version field will start with a lower case letter to indicate that it's not a standard database field. The lower case letter versions are usually read-only and are not used to set values.
Examples:
ClinicNum=23
clinicAbbr="Monroe"
appointment.Confirmed=145 (FK to definition.DefNum)
appointment.confirmed="Called"

Strings: The JSON serializer currently outputs carriage returns (\r\n) as spaces. There may be other issues with complex text as well.

Behavior

The behavior of actions in the API are similar to when using the UI in Open Dental, but not identical. There tends to be a bit less automation. There are also no prompts for back and forth logic with user interaction. The advantage of the API is that it will not allow you to make changes that would corrupt the database, so it's safe. If you were to use similar direct queries to try to change the database, you would quickly corrupt it. The API also makes the appropriate security log entries and performs some housekeeping duties such as archival, synchronization, and hashing in certain tables. In contrast, direct queries that change the database are strictly forbidden and we use our Database Integrity feature to actively block such queries.

Throttling

API users who only have the ApiReadAll permission have their requests throttled to one request per five seconds. This time includes the execution of the request itself. Throttling is relaxed to one request per one second if the API user possesses any other API permission (such as ApiComm, etc). This reduced throttle will apply to all API requests, even those falling under the ApiReadAll permission.

Most API requests take less than a second to complete. The exact time will vary with the complexity of the specific endpoint used. The API request data flow chain has several links. The request is sent to api.opendental.com, is routed to servers at Open Dental, its credentials validated, and sent to the dental office via their eConnector. After executing the API method on the dental office's server, the response travels back through the chain to the Developer who made the request. This full chain contains 10 hops start to finish.

Requests made using the local API are not throttled at all. All requests are made locally at the dental office workstations and communicate with the running Open Dental Program. They do not need to travel through Open Dental servers, reducing execution time considerably. API key credentials are still verified via web call to HQ, but are valid for 6 hours. This allows the local API to continue functioning during periods of internet downtime.