How to Manage Patients via the API
Use the Dentare REST API to create, update, list, and view patients programmatically. This guide covers creating an API token, authenticating requests, and using the patient endpoints β all without opening the Dentare web interface.
How to Manage Patients via the API
Use the Dentare REST API to create, update, list, and view patients programmatically. This guide covers creating an API token, authenticating requests, and using the patient endpoints β all without opening the Dentare web interface.
In this article:
What You'll Need
An active Dentare account with admin access
A tool for making HTTP requests (e.g.,
curl, Postman, or your own code)
Step 1 β Create an API Token
Before you can call the API, you need an API token. This token authenticates your requests and links them to your Dentare account.
Log in to Dentare as an account admin
Go to API Tokens from the account navigation (or navigate directly to API Tokens)
Click Create an API Token
Enter a descriptive name (e.g., "Patient Integration" or "Migration Script")
Click Create
After creation, Dentare shows your token. Copy it immediately β for security, the full token is only visible at this point.
Important: Treat your API token like a password. Do not share it publicly or commit it to source control. Anyone with the token can access your account's data.
To revoke a token:
Go to API Tokens
Click the token name
Click Revoke
The token is deleted immediately and can no longer be used.
Step 2 β Authenticate API Requests
Every API request must include your token in the Authorization header using the Bearer scheme:
Authorization: Bearer YOUR_TOKEN_HERE
Example with curl:
curl https://dentare.io/api/v1/me.json -H "Authorization: Bearer YOUR_TOKEN_HERE" -H "Accept: application/json"
A successful response returns your user profile, confirming the token works.
If you receive a 401 Unauthorized response, check that:
The token is copied correctly (no extra spaces)
The token has not been revoked
The
Authorizationheader uses theBearerprefix
Create a Patient
Request:
POST https://dentare.io/api/v1/patients
Headers:
Authorization: Bearer YOUR_TOKEN_HEREContent-Type: application/json
Body (JSON):
{"first_name": "John", "last_name": "Doe", "email": "john@example.com", "phone": "+38970123456", "birthdate": "1990-05-15", "gender": "male"}
Example with curl:
curl -X POST https://dentare.io/api/v1/patients -H "Authorization: Bearer YOUR_TOKEN_HERE" -H "Content-Type: application/json" -d '{"first_name": "John", "last_name": "Doe", "email": "john@example.com", "phone": "+38970123456"}'
Successful response (201 Created):
Returns the full patient record in {data: {...}} format including the assigned id, display_name, phone_e164 (normalized phone), created_at, and all other fields.
Error response (422 Unprocessable Entity):
Returns {error: "...", errors: {...}} with validation messages (e.g., "First name can't be blank").
Note: Only
first_nameandlast_nameare required. All other fields are optional.
Update a Patient
Request:
PATCH https://dentare.io/api/v1/patients/PATIENT_ID
Headers:
Authorization: Bearer YOUR_TOKEN_HEREContent-Type: application/json
Body (JSON) β include only the fields you want to change:
{"email": "newemail@example.com", "phone": "+38971999888"}
Example with curl:
curl -X PATCH https://dentare.io/api/v1/patients/123 -H "Authorization: Bearer YOUR_TOKEN_HERE" -H "Content-Type: application/json" -d '{"email": "newemail@example.com"}'
Successful response (200 OK):
Returns the updated full patient record in {data: {...}} format.
Error responses:
404 Not Found β patient does not exist or belongs to a different account
422 Unprocessable Entity β validation error
List Patients
Request:
GET https://dentare.io/api/v1/patients
Headers:
Authorization: Bearer YOUR_TOKEN_HERE
Query parameters (all optional):
q β search query (searches name, email, phone, personal number)
page β page number (default: 1)
per_page β items per page (default: 20, max: 100)
lang β locale for display names:
en,sq, ormkemail β filter by exact email
phone β filter by phone number (partial match)
personal_no β filter by personal number (EMBG)
external_id β filter by external ID
legacy_id β filter by legacy ID
is_active β filter by active status (
trueorfalse; defaults to active only)
Example with curl:
curl "https://dentare.io/api/v1/patients?q=John&per_page=50" -H "Authorization: Bearer YOUR_TOKEN_HERE"
Successful response (200 OK):
The response contains a data array and a meta object:
data β array of patient records, each with:
id,first_name,last_name,display_name,email,phone,phone_e164,locale,is_active,created_atmeta β pagination info with
page,per_page,total
Note: By default, only active patients are returned. Pass
is_active=falseto include inactive patients.
Get Patient Details
Request:
GET https://dentare.io/api/v1/patients/PATIENT_ID
Headers:
Authorization: Bearer YOUR_TOKEN_HERE
Query parameters (optional):
lang β locale for display names:
en,sq, ormkfields β comma-separated list of expansion fields (see Expansion Fields section below)
Example with curl:
curl "https://dentare.io/api/v1/patients/123?fields=allergies,medical_conditions,insurance_provider" -H "Authorization: Bearer YOUR_TOKEN_HERE"
Successful response (200 OK):
Returns the full patient record in {data: {...}} format including: id, first_name, last_name, display_name, display_first_name, display_last_name, email, phone, phone_e164, phone_country, birthdate, gender, personal_no, external_id, legacy_id, locale, is_active, created_at, updated_at, plus any requested expansion fields.
Error response:
404 Not Found β patient does not exist or belongs to a different account
Available Fields
The following fields can be used when creating or updating a patient. Only first_name and last_name are required.
Required:
first_name β patient's first name
last_name β patient's last name
Optional:
email β email address
phone β phone number (automatically normalized to E.164 international format)
phone_country β two-letter country code for phone normalization (e.g., "MK", "XK", "AL")
birthdate β date of birth in ISO 8601 format (YYYY-MM-DD)
gender β
male,female, orotherpersonal_no β national ID / EMBG
locale β preferred language for messages:
en,sq, ormkexternal_id β ID from another system (for reference)
blood_type β blood type
allergies β known allergies (free text)
medical_conditions β known medical conditions (free text)
emergency_contact_name β name of emergency contact
emergency_contact_relationship β relationship to patient
emergency_contact_phone β phone number of emergency contact
insurance_provider β name of insurance company
insurance_id β insurance policy number
is_active β whether the patient is active (
trueorfalse)preferred_doctor_id β ID of the preferred doctor
Expansion Fields
By default, the patient detail response includes core fields only. To include additional fields, pass them as a comma-separated fields parameter on the GET request.
Available expansion fields:
allergies β known allergies
medical_conditions β known medical conditions
blood_type β blood type
emergency_contact_name β emergency contact name
emergency_contact_relationship β emergency contact relationship
emergency_contact_phone β emergency contact phone
insurance_provider β insurance company name
insurance_id β insurance policy number
vip β VIP status
vip_start_date β VIP start date
vip_expiration_date β VIP expiration date
vip_notes β VIP notes
preferences β patient preferences
medical_issues β medical issues
Example:
GET /api/v1/patients/123?fields=allergies,insurance_provider,emergency_contact_name
API Reference Summary
Authentication:
Header:
Authorization: Bearer YOUR_TOKEN_HEREContent type:
application/json
Endpoints:
POST /api/v1/patients β create a patient
PATCH /api/v1/patients/:id β update a patient
GET /api/v1/patients β list patients (paginated, searchable, filterable)
GET /api/v1/patients/:id β get patient details (with optional expansion fields)
Common HTTP status codes:
200 β success
201 β created successfully
401 β unauthorized (invalid or missing token)
404 β not found
422 β validation error (missing required fields, bad format)
Troubleshooting
401 Unauthorized on every request Check that your Authorization header uses the correct format: Bearer YOUR_TOKEN_HERE. Make sure the token has not been revoked.
404 Not Found when accessing a patient The patient either does not exist or belongs to a different account. API requests are scoped to your account β you cannot access patients from other accounts.
422 Validation error on create At minimum, first_name and last_name are required. Check the errors object in the response for specific field errors.
Phone number appears different after create/update Dentare automatically normalizes phone numbers to E.164 international format (e.g., +38970123456). The normalized number is returned in the phone_e164 field. Pass phone_country to help with normalization if your phone numbers don't include a country code.
Search returns no results The q parameter searches across name, email, phone, and personal number. Make sure the search term matches at least one of these fields. By default, only active patients are returned β pass is_active=false to include inactive ones.
Special characters appear garbled Ensure your request uses UTF-8 encoding. Set the Content-Type: application/json; charset=utf-8 header.
Need help? Contact Support.