Users
Map each patient to one Doctronic user, store the ID on your backend, and collect the demographics each workflow needs.
A Doctronic user is the record for one patient in your organization. Create it once, store its ID
with the patient record in your system, and send that ID as X-Doctronic-User-ID on every later
request for the patient.
# Reuse the same key and body if you retry this request.
IDEMPOTENCY_KEY="$(uuidgen)"
# Email and phone number are unique per user, so this uses a fresh email and no phone number.
EMAIL="avery+$(uuidgen)@example.com"
curl --fail-with-body --request POST "$DOCTRONIC_API_URL/users/" \
--header "Authorization: Bearer $DOCTRONIC_API_TOKEN" \
--header "Idempotency-Key: $IDEMPOTENCY_KEY" \
--header "Content-Type: application/json" \
--data '{
"firstName": "Avery",
"lastName": "Chen",
"dateOfBirth": "1990-06-15",
"email": "'"$EMAIL"'",
"sex": "female"
}'import { randomUUID } from 'node:crypto';
const baseUrl = process.env.DOCTRONIC_API_URL ?? 'https://staging-partners.doctronic.ai/api/v1';
const response = await fetch(`${baseUrl}/users/`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.DOCTRONIC_API_TOKEN}`,
'Idempotency-Key': randomUUID(),
'Content-Type': 'application/json',
},
// Email and phone number are unique per user, so this uses a fresh email and no phone number.
body: JSON.stringify({
firstName: 'Avery',
lastName: 'Chen',
dateOfBirth: '1990-06-15',
email: `avery+${randomUUID()}@example.com`,
sex: 'female',
}),
});
if (!response.ok) throw new Error(`Doctronic ${response.status}: ${await response.text()}`);
const { data: user } = await response.json();
// Save user.id on the patient record in your system.{
"code": "success",
"message": "Request successful",
"data": {
"id": "mem_01K6JGGM2G2DB4Y9KB9H9MJJ6Q",
"createdAt": "2026-08-31T14:30:00Z",
"firstName": "Avery",
"lastName": "Chen",
"dateOfBirth": "1990-06-15",
"email": "avery+0f8fad5b-d9cb-469f-a165-70867728950e@example.com",
"phoneNumber": null,
"sex": "female",
"appointmentDemographicsComplete": false,
"missingAppointmentFields": ["phoneNumber"]
}
}Creating a user takes the token alone; see request headers.
Store the mapping
Patient record in your system -> Doctronic user ID (mem_…) -> chats, appointments, consultation documentsYour backend owns this mapping, and it is the only link between the two records.
- Look up the stored mapping first, and create a user only for a patient who has none.
- Derive the user ID on your backend from the patient your system authenticated. Treat an ID sent by a browser, mobile app, or agent as untrusted until it matches your mapping.
- Keep staging and production mappings apart. User IDs belong to one environment.
A timed-out create is safe to retry with the same Idempotency-Key and body; see
idempotent requests. If the email or phone number already
belongs to another user, the API returns 400 error.user.conflict and never merges or transfers
users. Reconcile the patient against your mapping before you try again.
Collect demographics for each workflow
Every field on POST /users/ is optional, so you
can create the user as soon as the patient starts a consultation. Later workflows return 400 when
a field they need is missing:
| Workflow | Required on the user | Also required | Error when a field is missing |
|---|---|---|---|
| Consultation | Nothing | None | None |
| Appointment booking | firstName, lastName, dateOfBirth, phoneNumber | A complete address and a completed chat | error.appointments.missing_patient_demographics |
| Pharmacy selection | firstName, lastName, dateOfBirth, sex | None | error.pharmacy.missing_patient_demographics |
| Insurance coverage | firstName, lastName, dateOfBirth, sex | None | error.coverage.missing_patient_demographics |
| Field | Format |
|---|---|
firstName, lastName | Up to 50 characters |
dateOfBirth | ISO 8601 date |
email | An email address |
phoneNumber | E.164, such as +15555550100. When carrier lookup is enabled, the default policy accepts mobile and VoIP numbers and rejects landlines. |
sex | male or female: sex assigned at birth, not gender |
Check appointment readiness
Every user response includes appointmentDemographicsComplete, which is true when the four
booking fields are present, and missingAppointmentFields, which lists the ones still missing.
Collect them before you offer a visit. Both fields describe the user record only and don't
authorize a booking; booking also checks the address and the chat.
Read and update a user
GET /users/ returns the profile for the user in
X-Doctronic-User-ID, in the same shape as the create response.
PATCH /users/ corrects or completes it. Send
only the fields you want to change. Email and phone number are unique per user, so send the
patient's own values:
# Reuse the same key if you retry this request.
IDEMPOTENCY_KEY="$(uuidgen)"
curl --fail-with-body --request PATCH "$DOCTRONIC_API_URL/users/" \
--header "Authorization: Bearer $DOCTRONIC_API_TOKEN" \
--header "X-Doctronic-User-ID: $DOCTRONIC_USER_ID" \
--header "Idempotency-Key: $IDEMPOTENCY_KEY" \
--header "Content-Type: application/json" \
--data '{
"dateOfBirth": "1990-06-15",
"email": null
}'| You send | Result |
|---|---|
| A field with a value | The field changes. |
A field set to null | The field is cleared. |
| No entry for a field | The field keeps its current value. |
| A blank name or phone number | 400. Send null to clear the field. |
Any field other than firstName, lastName, dateOfBirth, email, phoneNumber, or sex | 400 |
The SDKs follow the same rules. In Python, pass None to clear a field and leave the argument out
to keep it. In TypeScript, pass null to clear a field and leave the key out, or set it to
undefined, to keep it.
The user ID and existing chats stay the same. Changes apply to the profile and to future bookings,
not to visits already booked or to past clinical content, so book from the same completed chat once
the missing fields are filled in. A replayed update returns the original response; call
GET /users/ for the current profile.
Handle stale mappings
| Response | Meaning | Action |
|---|---|---|
404 error.member.not_found | The user ID doesn't exist, isn't active, or doesn't belong to the organization that owns the token. | Check that the mapping and the token come from the same environment and organization. |
404 on a user-scoped resource | The resource is missing or belongs to a different user. | Confirm the stored user ID for the patient before you retry. |
| No mapping for a returning patient | Your system lost the link. | Reconcile identity in your system before you create another user. |
Limits
- The API stores no external patient identifier and has no user search.
dateOfBirthaccepts ages 18 through 120 only.- The API has no operation to delete a user. Plan retention and deletion with Doctronic during your security and privacy review.
- The API doesn't verify that the patient owns the email address or phone number.