curl --request PATCH \
--url https://api.usecobalt.com/v1/appointments/{id} \
--header 'Content-Type: application/json' \
--header 'access_token: <api-key>' \
--header 'client_id: <api-key>' \
--header 'client_secret: <api-key>' \
--data '
{
"status": "cancelled",
"note": "Purpose of visit: Annual checkup",
"cancellation_reason": "Patient Illness",
"type": "NP",
"duration": "30",
"provider": "provider-123",
"secondary_provider": "provider-456",
"practice_id": "practice-1",
"mrn": "12345",
"datetime": "2026-06-15T14:30:00-07:00",
"callback_urls": [
"https://example.com/webhooks/cobalt"
]
}
'import requests
url = "https://api.usecobalt.com/v1/appointments/{id}"
payload = {
"status": "cancelled",
"note": "Purpose of visit: Annual checkup",
"cancellation_reason": "Patient Illness",
"type": "NP",
"duration": "30",
"provider": "provider-123",
"secondary_provider": "provider-456",
"practice_id": "practice-1",
"mrn": "12345",
"datetime": "2026-06-15T14:30:00-07:00",
"callback_urls": ["https://example.com/webhooks/cobalt"]
}
headers = {
"client_id": "<api-key>",
"client_secret": "<api-key>",
"access_token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {
client_id: '<api-key>',
client_secret: '<api-key>',
access_token: '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
status: 'cancelled',
note: 'Purpose of visit: Annual checkup',
cancellation_reason: 'Patient Illness',
type: 'NP',
duration: '30',
provider: 'provider-123',
secondary_provider: 'provider-456',
practice_id: 'practice-1',
mrn: '12345',
datetime: '2026-06-15T14:30:00-07:00',
callback_urls: ['https://example.com/webhooks/cobalt']
})
};
fetch('https://api.usecobalt.com/v1/appointments/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.usecobalt.com/v1/appointments/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'status' => 'cancelled',
'note' => 'Purpose of visit: Annual checkup',
'cancellation_reason' => 'Patient Illness',
'type' => 'NP',
'duration' => '30',
'provider' => 'provider-123',
'secondary_provider' => 'provider-456',
'practice_id' => 'practice-1',
'mrn' => '12345',
'datetime' => '2026-06-15T14:30:00-07:00',
'callback_urls' => [
'https://example.com/webhooks/cobalt'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"access_token: <api-key>",
"client_id: <api-key>",
"client_secret: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.usecobalt.com/v1/appointments/{id}"
payload := strings.NewReader("{\n \"status\": \"cancelled\",\n \"note\": \"Purpose of visit: Annual checkup\",\n \"cancellation_reason\": \"Patient Illness\",\n \"type\": \"NP\",\n \"duration\": \"30\",\n \"provider\": \"provider-123\",\n \"secondary_provider\": \"provider-456\",\n \"practice_id\": \"practice-1\",\n \"mrn\": \"12345\",\n \"datetime\": \"2026-06-15T14:30:00-07:00\",\n \"callback_urls\": [\n \"https://example.com/webhooks/cobalt\"\n ]\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("client_id", "<api-key>")
req.Header.Add("client_secret", "<api-key>")
req.Header.Add("access_token", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.usecobalt.com/v1/appointments/{id}")
.header("client_id", "<api-key>")
.header("client_secret", "<api-key>")
.header("access_token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"status\": \"cancelled\",\n \"note\": \"Purpose of visit: Annual checkup\",\n \"cancellation_reason\": \"Patient Illness\",\n \"type\": \"NP\",\n \"duration\": \"30\",\n \"provider\": \"provider-123\",\n \"secondary_provider\": \"provider-456\",\n \"practice_id\": \"practice-1\",\n \"mrn\": \"12345\",\n \"datetime\": \"2026-06-15T14:30:00-07:00\",\n \"callback_urls\": [\n \"https://example.com/webhooks/cobalt\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.usecobalt.com/v1/appointments/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["client_id"] = '<api-key>'
request["client_secret"] = '<api-key>'
request["access_token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"status\": \"cancelled\",\n \"note\": \"Purpose of visit: Annual checkup\",\n \"cancellation_reason\": \"Patient Illness\",\n \"type\": \"NP\",\n \"duration\": \"30\",\n \"provider\": \"provider-123\",\n \"secondary_provider\": \"provider-456\",\n \"practice_id\": \"practice-1\",\n \"mrn\": \"12345\",\n \"datetime\": \"2026-06-15T14:30:00-07:00\",\n \"callback_urls\": [\n \"https://example.com/webhooks/cobalt\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": "<string>",
"appointment_id": "<string>",
"job_id": 123
}{
"success": false,
"message": "<string>"
}{
"success": false,
"message": "<string>"
}{
"success": false,
"message": "<string>"
}{
"success": false,
"message": "<string>"
}Update Appointment
Updates an existing appointment. The update process differs based on the current status of the appointment.
curl --request PATCH \
--url https://api.usecobalt.com/v1/appointments/{id} \
--header 'Content-Type: application/json' \
--header 'access_token: <api-key>' \
--header 'client_id: <api-key>' \
--header 'client_secret: <api-key>' \
--data '
{
"status": "cancelled",
"note": "Purpose of visit: Annual checkup",
"cancellation_reason": "Patient Illness",
"type": "NP",
"duration": "30",
"provider": "provider-123",
"secondary_provider": "provider-456",
"practice_id": "practice-1",
"mrn": "12345",
"datetime": "2026-06-15T14:30:00-07:00",
"callback_urls": [
"https://example.com/webhooks/cobalt"
]
}
'import requests
url = "https://api.usecobalt.com/v1/appointments/{id}"
payload = {
"status": "cancelled",
"note": "Purpose of visit: Annual checkup",
"cancellation_reason": "Patient Illness",
"type": "NP",
"duration": "30",
"provider": "provider-123",
"secondary_provider": "provider-456",
"practice_id": "practice-1",
"mrn": "12345",
"datetime": "2026-06-15T14:30:00-07:00",
"callback_urls": ["https://example.com/webhooks/cobalt"]
}
headers = {
"client_id": "<api-key>",
"client_secret": "<api-key>",
"access_token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {
client_id: '<api-key>',
client_secret: '<api-key>',
access_token: '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
status: 'cancelled',
note: 'Purpose of visit: Annual checkup',
cancellation_reason: 'Patient Illness',
type: 'NP',
duration: '30',
provider: 'provider-123',
secondary_provider: 'provider-456',
practice_id: 'practice-1',
mrn: '12345',
datetime: '2026-06-15T14:30:00-07:00',
callback_urls: ['https://example.com/webhooks/cobalt']
})
};
fetch('https://api.usecobalt.com/v1/appointments/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.usecobalt.com/v1/appointments/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'status' => 'cancelled',
'note' => 'Purpose of visit: Annual checkup',
'cancellation_reason' => 'Patient Illness',
'type' => 'NP',
'duration' => '30',
'provider' => 'provider-123',
'secondary_provider' => 'provider-456',
'practice_id' => 'practice-1',
'mrn' => '12345',
'datetime' => '2026-06-15T14:30:00-07:00',
'callback_urls' => [
'https://example.com/webhooks/cobalt'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"access_token: <api-key>",
"client_id: <api-key>",
"client_secret: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.usecobalt.com/v1/appointments/{id}"
payload := strings.NewReader("{\n \"status\": \"cancelled\",\n \"note\": \"Purpose of visit: Annual checkup\",\n \"cancellation_reason\": \"Patient Illness\",\n \"type\": \"NP\",\n \"duration\": \"30\",\n \"provider\": \"provider-123\",\n \"secondary_provider\": \"provider-456\",\n \"practice_id\": \"practice-1\",\n \"mrn\": \"12345\",\n \"datetime\": \"2026-06-15T14:30:00-07:00\",\n \"callback_urls\": [\n \"https://example.com/webhooks/cobalt\"\n ]\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("client_id", "<api-key>")
req.Header.Add("client_secret", "<api-key>")
req.Header.Add("access_token", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.usecobalt.com/v1/appointments/{id}")
.header("client_id", "<api-key>")
.header("client_secret", "<api-key>")
.header("access_token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"status\": \"cancelled\",\n \"note\": \"Purpose of visit: Annual checkup\",\n \"cancellation_reason\": \"Patient Illness\",\n \"type\": \"NP\",\n \"duration\": \"30\",\n \"provider\": \"provider-123\",\n \"secondary_provider\": \"provider-456\",\n \"practice_id\": \"practice-1\",\n \"mrn\": \"12345\",\n \"datetime\": \"2026-06-15T14:30:00-07:00\",\n \"callback_urls\": [\n \"https://example.com/webhooks/cobalt\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.usecobalt.com/v1/appointments/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["client_id"] = '<api-key>'
request["client_secret"] = '<api-key>'
request["access_token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"status\": \"cancelled\",\n \"note\": \"Purpose of visit: Annual checkup\",\n \"cancellation_reason\": \"Patient Illness\",\n \"type\": \"NP\",\n \"duration\": \"30\",\n \"provider\": \"provider-123\",\n \"secondary_provider\": \"provider-456\",\n \"practice_id\": \"practice-1\",\n \"mrn\": \"12345\",\n \"datetime\": \"2026-06-15T14:30:00-07:00\",\n \"callback_urls\": [\n \"https://example.com/webhooks/cobalt\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"message": "<string>",
"appointment_id": "<string>",
"job_id": 123
}{
"success": false,
"message": "<string>"
}{
"success": false,
"message": "<string>"
}{
"success": false,
"message": "<string>"
}{
"success": false,
"message": "<string>"
}id in the URL path. The {id} parameter should be the Cobalt appointment ID returned from API responses or GET endpoints, not the EHR ID.1. Updating Pending or Failed Appointments
For appointments with a status of ‘pending’ or ‘failed’, you can update any attribute of the appointment.| Parameter | Type | Required | Description |
|---|---|---|---|
| Any appointment attribute | varies | No | Any attribute of the appointment can be updated. All fields are optional. |
2. Updating Scheduled Appointments
For appointments with a status of ‘scheduled’, you can update the status, note, or visit type.status to a cancelled status (from GET /visit-statuses), then create a new appointment at the new time with POST /v1/appointments.| Parameter | Type | Required | Description |
|---|---|---|---|
| status | string | No | Must be one of the available statuses associated with the linked account. You can find the available statuses by using our GET /visit-statuses endpoint |
| note | string | No | A note associated with the appointment. This is not a progress note or addition to the patient chart. This is primarily used for admin (eg. “patient might be 5 minutes late”). |
| type | string | No | The new visit type for the appointment. Must be one of the visit types from GET /v1/visit-types, and must be available for the appointment’s provider/resource in the EHR (skippable via skip_visit_type_validation). The appointment’s duration is updated to the new visit type’s configured duration unless duration is provided. |
| duration | string | No | Only valid together with type. The new appointment duration in minutes, as a positive integer string. Overrides the new visit type’s configured duration. Required when skip_visit_type_validation is "true". |
| skip_visit_type_validation | string | No | Only valid together with type. When "true", skips the check that the visit type is configured for the appointment’s provider/resource in the EHR. Use this for visit types that are bookable in the EHR (for example via availability slots) but not part of the resource’s configured visit type list. Requires duration. |
Example Request for Updating a Pending/Failed Appointment
curl -X PATCH https://api.usecobalt.com/v1/appointments/23456789 \
-H 'Content-Type: application/json' \
-H 'client_id: ci_live_198908HJDKJSH98789OHKJL' \
-H 'client_secret: cs_live_9827hofdsklOYYHJLJh' \
-H 'access_token: 493JKLHIU98789hLKH9HHJH' \
-d '{
"appointment_datetime": "2024-01-15T14:00:00-07:00",
"location": "New Clinic",
"type": "f/u"
}'
Example Response
{
"success": true,
"message": "Appointment updated successfully"
}
Authorizations
Path Parameters
Cobalt appointment ID (UUID, with or without dashes).
Body
New appointment status. Validated against the account's visit statuses.
"cancelled"
Replacement appointment note.
"Purpose of visit: Annual checkup"
Reason for a cancel / no-show / reschedule. Must accompany a status change to Cancelled, Rescheduled, or No Show, and must match one of the practice's configured reasons (eClinicalWorks only).
"Patient Illness"
New visit type code (eClinicalWorks only).
"NP"
New duration in minutes, updatable only together with type (eClinicalWorks only).
"30"
Skip visit-type validation on a type update (eClinicalWorks only).
true, false New rendering provider EMR ID (eClinicalWorks only).
"provider-123"
New secondary provider / resource EMR ID (eClinicalWorks only).
"provider-456"
eClinicalWorks practice ID.
"practice-1"
Patient MRN (retry of a failed appointment only).
"12345"
New appointment datetime, ISO 8601 (retry of a failed appointment only).
"2026-06-15T14:30:00-07:00"
URL(s) to receive the completion webhook for this update.
["https://example.com/webhooks/cobalt"]