curl --request GET \
--url https://api.maxcare.ai/v1/patients \
--header 'Authorization: Bearer <token>' \
--header 'X-Organization-Id: <x-organization-id>'import requests
url = "https://api.maxcare.ai/v1/patients"
headers = {
"X-Organization-Id": "<x-organization-id>",
"Authorization": "Bearer <token>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {'X-Organization-Id': '<x-organization-id>', Authorization: 'Bearer <token>'}
};
fetch('https://api.maxcare.ai/v1/patients', 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.maxcare.ai/v1/patients",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"X-Organization-Id: <x-organization-id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.maxcare.ai/v1/patients"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-Organization-Id", "<x-organization-id>")
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.maxcare.ai/v1/patients")
.header("X-Organization-Id", "<x-organization-id>")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.maxcare.ai/v1/patients")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-Organization-Id"] = '<x-organization-id>'
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"code": "success",
"data": {
"patients": [
{
"id": "c56103bc-d39c-46d3-9f31-38dd2b5e05f6",
"mrn": "MRN-10042",
"firstName": "Sarah",
"lastName": "Johnson",
"middleName": "Marie",
"gender": "Female",
"dateOfBirth": "1985-03-15",
"email": "sarah.johnson@email.com",
"phone": "(555) 123-4567",
"createdAt": "2024-08-15T09:30:00.000Z",
"updatedAt": "2025-01-20T14:22:00.000Z",
"ehrType": "modmed",
"ehrActive": true,
"ehrPatientId": "112513",
"deepLinkUrl": "https://practice.ema.md/ema/web/practice/staff/#/practice/staff/patient/112513/edit-patient",
"address": {
"line1": "742 Evergreen Terrace",
"line2": "Apt 4B",
"city": "Southfield",
"state": "MI",
"zipcode": "48075",
"country": "US"
},
"phoneNumbers": [
{
"number": "(555) 123-4567",
"type": "mobile"
}
],
"preferredLanguage": "en",
"emergencyContact": {
"name": "Marie Bayless",
"relationship": "Spouse",
"phone": "(555) 987-6543"
},
"masterPatientId": "3f1c8a2e-0a5b-4c3d-9e7f-1a2b3c4d5e6f",
"duplicatePatientIds": []
}
],
"pagination": {
"page": 1,
"pageSize": 100,
"totalCount": 250,
"totalPages": 3
}
}
}{
"code": "bad_request",
"message": "'id' must be a valid UUID",
"trace_id": "550e8400-e29b-41d4-a716-446655440000"
}{
"code": "unauthorized",
"message": "Invalid or missing API key",
"trace_id": "550e8400-e29b-41d4-a716-446655440000"
}{
"code": "forbidden",
"message": "Insufficient scope",
"trace_id": "550e8400-e29b-41d4-a716-446655440000"
}{
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Maximum 1000 requests per 60 seconds.",
"trace_id": "550e8400-e29b-41d4-a716-446655440000"
}List patients
Returns a paginated list of patients. Requires read:patients scope.
curl --request GET \
--url https://api.maxcare.ai/v1/patients \
--header 'Authorization: Bearer <token>' \
--header 'X-Organization-Id: <x-organization-id>'import requests
url = "https://api.maxcare.ai/v1/patients"
headers = {
"X-Organization-Id": "<x-organization-id>",
"Authorization": "Bearer <token>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {'X-Organization-Id': '<x-organization-id>', Authorization: 'Bearer <token>'}
};
fetch('https://api.maxcare.ai/v1/patients', 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.maxcare.ai/v1/patients",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"X-Organization-Id: <x-organization-id>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.maxcare.ai/v1/patients"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-Organization-Id", "<x-organization-id>")
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.maxcare.ai/v1/patients")
.header("X-Organization-Id", "<x-organization-id>")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.maxcare.ai/v1/patients")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-Organization-Id"] = '<x-organization-id>'
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"code": "success",
"data": {
"patients": [
{
"id": "c56103bc-d39c-46d3-9f31-38dd2b5e05f6",
"mrn": "MRN-10042",
"firstName": "Sarah",
"lastName": "Johnson",
"middleName": "Marie",
"gender": "Female",
"dateOfBirth": "1985-03-15",
"email": "sarah.johnson@email.com",
"phone": "(555) 123-4567",
"createdAt": "2024-08-15T09:30:00.000Z",
"updatedAt": "2025-01-20T14:22:00.000Z",
"ehrType": "modmed",
"ehrActive": true,
"ehrPatientId": "112513",
"deepLinkUrl": "https://practice.ema.md/ema/web/practice/staff/#/practice/staff/patient/112513/edit-patient",
"address": {
"line1": "742 Evergreen Terrace",
"line2": "Apt 4B",
"city": "Southfield",
"state": "MI",
"zipcode": "48075",
"country": "US"
},
"phoneNumbers": [
{
"number": "(555) 123-4567",
"type": "mobile"
}
],
"preferredLanguage": "en",
"emergencyContact": {
"name": "Marie Bayless",
"relationship": "Spouse",
"phone": "(555) 987-6543"
},
"masterPatientId": "3f1c8a2e-0a5b-4c3d-9e7f-1a2b3c4d5e6f",
"duplicatePatientIds": []
}
],
"pagination": {
"page": 1,
"pageSize": 100,
"totalCount": 250,
"totalPages": 3
}
}
}{
"code": "bad_request",
"message": "'id' must be a valid UUID",
"trace_id": "550e8400-e29b-41d4-a716-446655440000"
}{
"code": "unauthorized",
"message": "Invalid or missing API key",
"trace_id": "550e8400-e29b-41d4-a716-446655440000"
}{
"code": "forbidden",
"message": "Insufficient scope",
"trace_id": "550e8400-e29b-41d4-a716-446655440000"
}{
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Maximum 1000 requests per 60 seconds.",
"trace_id": "550e8400-e29b-41d4-a716-446655440000"
}Authorizations
Marketplace API key
Headers
Target clinic organization ID
Query Parameters
Search by patient name or MRN
Only return patients whose record was created or modified at/after this timestamp (ISO 8601). When set, results are ordered by updatedAt ascending with id as tiebreaker. Must carry an explicit UTC offset (...Z or ...+02:00) — a zone-less instant would be resolved against the database session timezone on some resources and the API process timezone on others, so the same string would mean two different moments. Pair with cursorId to walk safely — see that parameter; page/offset paging of this feed can drop rows. The bound is inclusive without cursorId, so boundary rows re-deliver — dedupe on id. This tracks the patient row's own columns only: include=contact and include=identity data live in other tables and changing them does not move updatedAt. A change feed also cannot report a deletion, so a consumer that prunes still needs a full walk.
"2026-08-01T00:00:00.000Z"
Only return patients whose record was last modified at/before this timestamp (ISO 8601). Pin this to the instant the walk started to freeze the window. Must carry an explicit UTC offset.
"2026-08-31T23:59:59.999Z"
Id of the last row you already consumed, for a keyset walk. Pass it together with updatedSince set to that same row's updatedAt, always requesting page 1; the next page is everything ordered after (updatedAt, id). Use this rather than page/offset for any walk that must not drop rows. Paging a delta feed with page/offset is unsafe because the sort column is exactly what the sync workers rewrite: a row on an earlier page that changes mid-walk moves to the tail, every later row shifts one position toward the front, and the offset for the next page steps over whichever row moved into that slot. That row is never returned and its stamp is below the cursor the walk finishes on, so it is missed permanently while the walk still looks successful. On a cursor page pagination.totalCount counts the window starting at your cursor, so it shrinks as you walk — stop on a short page rather than on the count.
"pat_8de030393a9e417ab2b3a8b8df183631"
Comma-separated expansions. address adds the patient's mailing address; contact adds preferredLanguage, typed phoneNumbers and the emergency contact; identity adds masterPatientId and duplicatePatientIds. address and contact additionally require the read:patient_pii scope and 403 without it; identity needs only read:patients.
address, contact, identity "address"
