Skip to main content
POST
Create an appointment

Provider and Location IDs

When creating appointments, use the ehr_id values from your providers and locations:
  • provider: Use the ehr_id from GET /v1/providers (not the id)
  • location: Use the ehr_id from GET /v1/locations (not the id)
  • secondary_provider: Use the ehr_id from GET /v1/providers (not the id)
These values represent the identifiers your EMR system uses. Cobalt passes them directly to your EMR when creating the appointment.
Don’t use the Cobalt id here. The id field from GET responses is Cobalt’s internal UUID, used only for updating provider/location settings via PATCH endpoints.

Date and Time Formats

You have two options for specifying the appointment date and time: Use the datetime parameter with full ISO 8601 timestamp including timezone:
Format: YYYY-MM-DDTHH:mm:ss±HH:MM (24-hour time with timezone offset)

Option 2: Separate Date and Time

Use date and time parameters separately. Important: When using this option, the time must be in 12-hour format with am or pm.
Date Format: YYYY-MM-DD Time Format: h:mm am/pm or hh:mm am/pm (12-hour format, must include am/pm)
Common mistake: Using "time": "10:00" without am or pm will result in an error. Always include am or pm when using separate date and time parameters.

Booking Timezone

By default the appointment time is interpreted in the account’s timezone. For EHR instances whose facilities span multiple timezones, pass an optional timezone (IANA name) to book the appointment at that facility’s local wall-clock time. The time you send (via datetime or date and time) is then treated as local to that zone.

Preventing Double Bookings

Set prevent_double_booking to "true" to have Cobalt check the provider’s schedule for conflicts before submitting the appointment to your EHR. If the requested time slot overlaps with an existing patient visit or a schedule block, the appointment fails immediately with a descriptive error rather than being submitted.
When a conflict is detected, you will receive an appointment.failed webhook with the conflict_type and conflict_details fields populated (see Failure Examples below). The check reads the provider’s schedule from your EHR when the appointment is created, not from Cobalt’s synced copy. A visit overlaps if any part of it falls between the requested start and end. Cancelled and rescheduled visits do not count. To allow more than one visit in a slot, set max_overlapping_appointments to the number of overlapping visits that should reject the appointment. For example, "2" books into a slot that holds one visit and rejects a slot that holds two. It defaults to 1 and requires prevent_double_booking to be "true". Schedule blocks always reject, whatever the limit.
If Cobalt cannot check the provider’s schedule, the appointment is not created. Cobalt retries when the EHR is temporarily unavailable, and otherwise fails the appointment with an error explaining that scheduling conflicts could not be verified.

Request Expiration

Cobalt retries failed appointment creates in the background, so an appointment can be created after your own timeout. If you handle the request another way once you time out, set expires_at to an ISO 8601 timestamp with a timezone offset:
After this time, Cobalt does not start any new attempt, including retries. A request that expires before its next attempt receives an appointment.failed webhook with reason code EXPIRED (see Failure Examples below). This is an attempt deadline, not cancellation of an operation already in progress. A save or its reconciliation can complete after it, and webhook delivery also takes time. If you receive appointment.created after your timeout, the appointment exists in your EHR. The same optional field is available on other asynchronous operations; see Request Expiration.

Complete Example Request

Example Response

Webhook Notifications

When the appointment processing is complete, we will send a webhook to your registered endpoint. Here are examples of what those webhook payloads will look like:

Success

Failure Examples

The appointment.failed webhook event includes a failure_reason and can contain additional fields in the data object depending on the cause of the failure. Patient Not Found:
Visit Type Not Found:
If the visit type is bookable in your EHR but not part of the resource’s configured visit type list (for example, visit types offered through availability slots), re-create the appointment with skip_visit_type_validation set to "true" and an explicit duration. Confidential Chart (when skip_confidential_charts is "true"):
Request Expired (when the expires_at time passed before the appointment could be saved):
Provider Not Found:
Schedule Block Conflict:
Appointment Conflict (Permission Denied):
Double Booking Conflict — Existing Patient Visit:
Double Booking Conflict — Schedule Block:
Generic Failure (Max Retries):

Authorizations

client_id
string
header
required
client_secret
string
header
required
access_token
string
header
required

Body

application/json
mrn
string

Patient MRN. One of mrn or patient_name is required (bespoke check).

Example:

"12345"

patient_name
string

Patient name, used when the MRN is not known.

Example:

"Jane Doe"

location
string

EMR location ID. Validated against the account's locations.

Example:

"location-1"

datetime
string<date-time>

Appointment start as an ISO 8601 datetime. Provide either datetime, or date and time.

Example:

"2026-06-15T14:30:00-07:00"

date
string<date>

Appointment date (YYYY-MM-DD). Used together with time.

Example:

"2026-06-15"

time
string

Appointment time (h:mm am/pm). Used together with date.

Example:

"2:30 pm"

timezone
string

IANA time zone name (e.g. "America/Chicago") to book the appointment in, overriding the account timezone. Use for eClinicalWorks instances whose facilities span multiple time zones: the datetime (or date and time) is interpreted in this zone and booked at that exact facility-local wall-clock time. Omit to use the account timezone.

Example:

"America/Chicago"

provider
string

Rendering provider EMR ID. Validated against the account's providers.

Example:

"provider-123"

secondary_provider
string

Secondary provider / resource EMR ID. Sent to the EMR by eClinicalWorks and PTPracticePro only; for every EMR it is stored and counts toward that provider's availability.

Example:

"provider-456"

type
string

Visit type code. Validated against the account's visit types.

Example:

"NP"

note
string

Appointment note as a plain string.

Example:

"Purpose of visit: Annual checkup"

duration

Appointment duration in minutes, as a positive integer.

Example:

"30"

reason
string

Reason for the visit.

Example:

"Annual checkup"

billing_note
string

Billing note to set on the appointment. Read it back with the appointment_notes include on the fetch endpoints.

Example:

"Copay collected at check-in"

check_eligibility
enum<string>

Whether to run an eligibility check on creation. Accepted, but no EMR uses it, so it has no effect.

Available options:
true,
false
Example:

"false"

complaint_type
string

Complaint type ID. Validated against the account's complaint types.

Example:

"complaint-123"

prevent_double_booking
enum<string>

Whether to reject the appointment if the slot is already booked.

Available options:
true,
false
Example:

"true"

max_overlapping_appointments

With prevent_double_booking, reject only when the requested time already overlaps this many patient visits for the provider. A visit counts if any part of it falls inside the requested start to end; cancelled and rescheduled visits do not count. Schedule blocks always reject. Defaults to 1.

Example:

"2"

skip_visit_type_validation
enum<string>

Skip visit-type validation. Requires duration, since the visit type is not read.

Available options:
true,
false
Example:

"false"

skip_confidential_charts
enum<string>

Fail the appointment instead of creating it when the patient chart is confidential (restricted) for the connected user.

Available options:
true,
false
Example:

"false"

include_inactive_patients
enum<string>

Also match a patient chart that is inactive in the EMR when looking up the patient. By default only active charts are matched.

Available options:
true,
false
Example:

"false"

new_patient
enum<string>

Whether the patient is new.

Available options:
true,
false
Example:

"true"

practice_id

eClinicalWorks practice ID (for multi-practice provider/location pairs).

Example:

"practice-1"

department_id

eClinicalWorks department ID, validated against the synced departments.

Example:

"department-1"

non_billable
enum<string>

Whether the appointment is non-billable.

Available options:
true,
false
Example:

"false"

recall_id
string

Cobalt recall ID to link the new appointment to (from GET /v1/recalls).

Example:

"recall-abc-123"

callback_urls

URL(s) to receive the completion webhook for this appointment, in addition to the account webhook.

Example:
expires_at
string<date-time> | null

Optional ISO 8601 timestamp with an explicit timezone offset, in the future when submitted. Cobalt starts no new operation attempt after this deadline and reports reasons[].code EXPIRED. An attempt already in progress, including write reconciliation, may finish after it.

Example:

"2027-06-15T14:30:00Z"

Response

Appointment queued for creation

success
boolean
required
Example:

true

message
string
required
Example:

"Appointment queued for creation"

appointment_id
string
required
Example:

"a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4"

job_id
integer
Example:

12345