API Reference
Clinic setup
For workspaces that schedule with NuTalk clinic scheduling: set up the clinic the agents and reception book into. Locations and their opening hours, rooms and their spots, doctors with their weekly hours and days off, services, and the clinic-wide settings.
Keys need clinic_setup:read to read the setup and clinic_setup:write to change it. Every change runs through the dashboard's own clinic scheduling rules (overlapping hours refused, day changes rebuilt when a week changes, blocked time joined and checked against the appointments inside), acting as the member who created the key: their role must allow the change in the dashboard, and the change is recorded as the key's. A key made by a member who has since left the workspace can still read, but not change. Booking and managing appointments is the Agenda API.
Clinic scheduling is switched on per workspace
Every endpoint answers 403 for a workspace without clinic scheduling. NuTalk turns it on for clinics.
Endpoints
/v1/clinic/locationsList locationsPOST/v1/clinic/locationsCreate a locationGET/v1/clinic/locations/:idGet a locationPATCH/v1/clinic/locations/:idUpdate a locationDELETE/v1/clinic/locations/:idArchive a locationPOST/v1/clinic/locations/:id/hoursAdd opening hoursPATCH/v1/clinic/location-hours/:idUpdate opening hoursDELETE/v1/clinic/location-hours/:idRemove opening hoursGET/v1/clinic/roomsList roomsPOST/v1/clinic/roomsCreate a roomGET/v1/clinic/rooms/:idGet a roomPATCH/v1/clinic/rooms/:idUpdate a roomDELETE/v1/clinic/rooms/:idArchive a roomPOST/v1/clinic/rooms/:id/spotsAdd a spotPATCH/v1/clinic/spots/:idUpdate a spotDELETE/v1/clinic/spots/:idArchive a spotGET/v1/clinic/doctorsList doctorsPOST/v1/clinic/doctorsAdd a doctorGET/v1/clinic/doctors/:idGet a doctorPATCH/v1/clinic/doctors/:idUpdate a doctorDELETE/v1/clinic/doctors/:idRemove a doctorGET/v1/clinic/doctors/:id/weekly-hoursGet a doctor's weekly hoursPUT/v1/clinic/doctors/:id/weekly-hoursSet a doctor's weekly hoursGET/v1/clinic/doctors/:id/days-offList a doctor's days offPOST/v1/clinic/doctors/:id/days-offBlock a doctor's timeDELETE/v1/clinic/days-off/:idRemove a day offGET/v1/clinic/servicesList servicesPOST/v1/clinic/servicesCreate a serviceGET/v1/clinic/services/:idGet a servicePATCH/v1/clinic/services/:idUpdate a serviceDELETE/v1/clinic/services/:idArchive a serviceGET/v1/clinic/settingsGet clinic settingsPATCH/v1/clinic/settingsUpdate clinic settingsHow the pieces fit
- A doctor is anyone who takes appointments: doctors, nurses, therapists, technicians and other staff (their
role). They are bookable during their weekly hours, minus their days off. - A service is what patients book: its length, buffers, notice, which doctors (role, list) and which rooms or spots it needs, its price, and the facts the agents answer from.
- A room holds one or more spots (a chair, a bed): each spot holds one appointment at a time. A location's opening hours bound the services nobody staffs.
- Weekly hours are replaced as a whole week:
PUT /v1/clinic/doctors/:id/weekly-hourslists the appointments the new week leaves outside its hours (they stay booked; usedry_runto see them first).
# 1. A location (its clock is the clinic's)curl -X POST "https://www.nutalk.ai/v1/clinic/locations" \ -H "Authorization: Bearer $NUTALK_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"name": "Clínica Centro", "timezone": "America/Monterrey"}' # 2. A doctor working therecurl -X POST "https://www.nutalk.ai/v1/clinic/doctors" \ -H "Authorization: Bearer $NUTALK_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"name": "Dra. Ana López", "specialty": "Dermatología", "default_location_id": "'$LOCATION_ID'"}' # 3. Their week: Monday and Wednesday mornings, Monday afternooncurl -X PUT "https://www.nutalk.ai/v1/clinic/doctors/$DOCTOR_ID/weekly-hours" \ -H "Authorization: Bearer $NUTALK_API_KEY" \ -H "Content-Type: application/json" \ -d '{"hours": [ {"day_of_week": 1, "start": "09:00", "end": "14:00"}, {"day_of_week": 1, "start": "16:00", "end": "19:00"}, {"day_of_week": 3, "start": "09:00", "end": "14:00"} ]}' # 4. A service they takecurl -X POST "https://www.nutalk.ai/v1/clinic/services" \ -H "Authorization: Bearer $NUTALK_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"name": "Consulta dermatológica", "duration_minutes": 30, "allowed_doctor_ids": ["'$DOCTOR_ID'"], "price": 900}'List locations
/v1/clinic/locationsLists the clinic's locations with their opening hours, by name.
clinic_setup:readQuery parameters
| Name | Type | Description |
|---|---|---|
limit | integer | Results per page. 1–100. Default: |
offset | integer | Results to skip. At least 0. Default: |
status | string | Only locations in this status. Without it, every location but the archived ones. One of: active, inactive, archived. |
Example request
curl -X GET "https://www.nutalk.ai/v1/clinic/locations" \ -H "Authorization: Bearer YOUR_API_KEY"A page of locations.
{
"success": true,
"data": [
{
"id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70",
"name": "Clínica Centro",
"timezone": "America/Monterrey",
"address": "Av. Constitución 100, Monterrey, N.L.",
"phone_number": "+528112345678",
"status": "active",
"hours": [
{
"id": "9d3f5b7c-1e2a-4b4d-8f6c-8e0a2c4d6f81",
"day_of_week": 1,
"open_time": "09:00",
"close_time": "18:00",
"is_active": true
}
],
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
],
"pagination": {
"total": 1,
"limit": 20,
"offset": 0,
"has_more": false
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | A query parameter is invalid (details.errors lists each one). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Create a location
/v1/clinic/locationsCreates a location. A workspace's first location adopts the rooms that have none; warnings says when that could not be done.
clinic_setup:writeSupports Idempotency-KeyWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Request body (JSON)
| Name | Type | Description |
|---|---|---|
nameRequired | string | The location's name. 1–200 characters. |
timezone | string | IANA time zone of the location's clock (default America/Monterrey). Up to 64 characters. |
address | string | null | Street address; null clears it. Up to 500 characters. |
phone_number | string | null | The location's phone; null clears it. Up to 40 characters. |
Example request
curl -X POST "https://www.nutalk.ai/v1/clinic/locations" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Idempotency-Key: 11111111-2222-4333-8444-555555555555" \ -H "Content-Type: application/json" \ -d '{ "name": "Clínica Centro", "timezone": "America/Monterrey", "address": "Av. Constitución 100, Monterrey, N.L.", "phone_number": "+528112345678"}'The location.
{
"success": true,
"data": {
"id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70",
"name": "Clínica Centro",
"timezone": "America/Monterrey",
"address": "Av. Constitución 100, Monterrey, N.L.",
"phone_number": "+528112345678",
"status": "active",
"hours": [],
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | The body is not JSON, or a field is missing or invalid (details.errors lists each field). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Get a location
/v1/clinic/locations/:idReturns one location (archived ones too) with its opening hours.
clinic_setup:readPath parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The location id. |
Example request
curl -X GET "https://www.nutalk.ai/v1/clinic/locations/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY"The location.
{
"success": true,
"data": {
"id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70",
"name": "Clínica Centro",
"timezone": "America/Monterrey",
"address": "Av. Constitución 100, Monterrey, N.L.",
"phone_number": "+528112345678",
"status": "active",
"hours": [
{
"id": "9d3f5b7c-1e2a-4b4d-8f6c-8e0a2c4d6f81",
"day_of_week": 1,
"open_time": "09:00",
"close_time": "18:00",
"is_active": true
}
],
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
}Errors
| Status | Code | When |
|---|---|---|
| 404 | not_found | No location with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Update a location
/v1/clinic/locations/:idChanges the fields you send.
clinic_setup:writeCan wait for approvalWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The location id. |
Request body (JSON)
| Name | Type | Description |
|---|---|---|
name | string | The location's name. 1–200 characters. |
timezone | string | IANA time zone of the location's clock. Up to 64 characters. |
address | string | null | Street address; null clears it. Up to 500 characters. |
phone_number | string | null | The location's phone; null clears it. Up to 40 characters. |
status | string |
|
Example request
curl -X PATCH "https://www.nutalk.ai/v1/clinic/locations/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone_number": "+528187654321"}'The updated location.
{
"success": true,
"data": {
"id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70",
"name": "Clínica Centro",
"timezone": "America/Monterrey",
"address": "Av. Constitución 100, Monterrey, N.L.",
"phone_number": "+528187654321",
"status": "active",
"hours": [
{
"id": "9d3f5b7c-1e2a-4b4d-8f6c-8e0a2c4d6f81",
"day_of_week": 1,
"open_time": "09:00",
"close_time": "18:00",
"is_active": true
}
],
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | The body is not JSON, or a field is missing or invalid (details.errors lists each field). |
| 404 | not_found | No location with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
| 409 | validation_error | The location is archived (removed). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Archive a location
/v1/clinic/locations/:idArchives the location (the dashboard's Remove): it leaves every flow and its history stays. Archiving an archived location changes nothing.
clinic_setup:writeCan wait for approvalWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The location id. |
Example request
curl -X DELETE "https://www.nutalk.ai/v1/clinic/locations/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY"The location is archived.
{
"success": true,
"data": {
"id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70",
"archived": true
}
}Errors
| Status | Code | When |
|---|---|---|
| 404 | not_found | No location with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Add opening hours
/v1/clinic/locations/:id/hoursAdds one opening-hours range to a location. Opening hours bound the services nobody staffs (staff_involvement: none); a location without any is open whenever its doctors work. Add one range per weekday (or several, for a break).
clinic_setup:writeSupports Idempotency-KeyWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The location id. |
Request body (JSON)
| Name | Type | Description |
|---|---|---|
day_of_weekRequired | integer | 0 = Sunday … 6 = Saturday. 0–6. |
open_timeRequired | string | HH:MM (24-hour) on the location's clock. |
close_timeRequired | string | HH:MM after open_time (23:59 at the latest). |
Example request
curl -X POST "https://www.nutalk.ai/v1/clinic/locations/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7/hours" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Idempotency-Key: 11111111-2222-4333-8444-555555555555" \ -H "Content-Type: application/json" \ -d '{ "day_of_week": 1, "open_time": "09:00", "close_time": "18:00"}'The range.
{
"success": true,
"data": {
"id": "9d3f5b7c-1e2a-4b4d-8f6c-8e0a2c4d6f81",
"day_of_week": 1,
"open_time": "09:00",
"close_time": "18:00",
"is_active": true
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | The body is not JSON, or a field is missing or invalid (details.errors lists each field). |
| 404 | not_found | No location with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
| 409 | validation_error | The location is archived (removed). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Update opening hours
/v1/clinic/location-hours/:idChanges one opening-hours range of a location (an id from the location's hours).
clinic_setup:writeCan wait for approvalWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The opening-hours range id. |
Request body (JSON)
| Name | Type | Description |
|---|---|---|
day_of_week | integer | 0 = Sunday … 6 = Saturday. 0–6. |
open_time | string | HH:MM (24-hour) on the location's clock. |
close_time | string | HH:MM after open_time (23:59 at the latest). |
is_active | boolean | false keeps the range but stops applying it. |
Example request
curl -X PATCH "https://www.nutalk.ai/v1/clinic/location-hours/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "close_time": "19:00"}'The updated range.
{
"success": true,
"data": {
"id": "9d3f5b7c-1e2a-4b4d-8f6c-8e0a2c4d6f81",
"day_of_week": 1,
"open_time": "09:00",
"close_time": "19:00",
"is_active": true
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | The body is not JSON, or a field is missing or invalid (details.errors lists each field). |
| 400 | validation_error | The closing time would not be after the opening time. |
| 404 | not_found | No opening-hours range with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Remove opening hours
/v1/clinic/location-hours/:idDeletes one opening-hours range of a location.
clinic_setup:writeCan wait for approvalWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The opening-hours range id. |
Example request
curl -X DELETE "https://www.nutalk.ai/v1/clinic/location-hours/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY"The range was deleted.
{
"success": true,
"data": {
"id": "9d3f5b7c-1e2a-4b4d-8f6c-8e0a2c4d6f81",
"deleted": true
}
}Errors
| Status | Code | When |
|---|---|---|
| 404 | not_found | No opening-hours range with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
Plus the errors every request can return (401, 403, 429, 500): Errors.
List rooms
/v1/clinic/roomsLists the clinic's rooms, by name, each with its spots: the places inside a room that hold one appointment at a time (a chair, a bed, a station).
clinic_setup:readQuery parameters
| Name | Type | Description |
|---|---|---|
limit | integer | Results per page. 1–100. Default: |
offset | integer | Results to skip. At least 0. Default: |
location_id | uuid | Only rooms of this location. |
status | string | Only rooms in this status. Without it, every room but the archived ones. One of: active, inactive, archived. |
Example request
curl -X GET "https://www.nutalk.ai/v1/clinic/rooms" \ -H "Authorization: Bearer YOUR_API_KEY"A page of rooms.
{
"success": true,
"data": [
{
"id": "ae4a6c8d-2f3b-4c5e-9a7d-9f1b3d5e7a92",
"name": "Sala de sueros",
"location_id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70",
"room_type": "iv",
"capacity": 4,
"status": "active",
"spots": [
{
"id": "bf5b7d9e-3a4c-4d6f-8b8e-0a2c4e6f8ba3",
"name": "Sillón 1",
"position": 1,
"status": "active"
}
],
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
],
"pagination": {
"total": 1,
"limit": 20,
"offset": 0,
"has_more": false
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | A query parameter is invalid (details.errors lists each one). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Create a room
/v1/clinic/roomsCreates a room with its first spot, named as the room: appointments are booked into spots. Add more spots for a room that holds several patients at once. A room in an inactive location takes no bookings until its location is active.
clinic_setup:writeSupports Idempotency-KeyWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Request body (JSON)
| Name | Type | Description |
|---|---|---|
nameRequired | string | The room's name (its first spot takes it too). 1–200 characters. |
location_id | uuid | null | The location the room is in (an active location of yours); null unlinks it. |
room_type | string | null | A label services can require ( |
capacity | integer | How many people fit (default 1). 1–100. |
Example request
curl -X POST "https://www.nutalk.ai/v1/clinic/rooms" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Idempotency-Key: 11111111-2222-4333-8444-555555555555" \ -H "Content-Type: application/json" \ -d '{ "name": "Sala de sueros", "location_id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70", "room_type": "iv", "capacity": 4}'The room, with its first spot.
{
"success": true,
"data": {
"id": "ae4a6c8d-2f3b-4c5e-9a7d-9f1b3d5e7a92",
"name": "Sala de sueros",
"location_id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70",
"room_type": "iv",
"capacity": 4,
"status": "active",
"spots": [
{
"id": "bf5b7d9e-3a4c-4d6f-8b8e-0a2c4e6f8ba3",
"name": "Sala de sueros",
"position": 1,
"status": "active"
}
],
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | The body is not JSON, or a field is missing or invalid (details.errors lists each field). |
| 400 | validation_error | location_id is not a location of yours, or it is archived (details.ids). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Get a room
/v1/clinic/rooms/:idReturns one room (archived ones too) with its spots.
clinic_setup:readPath parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The room id. |
Example request
curl -X GET "https://www.nutalk.ai/v1/clinic/rooms/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY"The room.
{
"success": true,
"data": {
"id": "ae4a6c8d-2f3b-4c5e-9a7d-9f1b3d5e7a92",
"name": "Sala de sueros",
"location_id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70",
"room_type": "iv",
"capacity": 4,
"status": "active",
"spots": [
{
"id": "bf5b7d9e-3a4c-4d6f-8b8e-0a2c4e6f8ba3",
"name": "Sillón 1",
"position": 1,
"status": "active"
}
],
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
}Errors
| Status | Code | When |
|---|---|---|
| 404 | not_found | No room with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Update a room
/v1/clinic/rooms/:idChanges the fields you send.
clinic_setup:writeCan wait for approvalWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The room id. |
Request body (JSON)
| Name | Type | Description |
|---|---|---|
name | string | The room's name. 1–200 characters. |
location_id | uuid | null | The location the room is in (an active location of yours); null unlinks it. |
room_type | string | null | A label services can require ( |
capacity | integer | How many people fit (default 1). 1–100. |
status | string |
|
Example request
curl -X PATCH "https://www.nutalk.ai/v1/clinic/rooms/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "capacity": 6}'The updated room.
{
"success": true,
"data": {
"id": "ae4a6c8d-2f3b-4c5e-9a7d-9f1b3d5e7a92",
"name": "Sala de sueros",
"location_id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70",
"room_type": "iv",
"capacity": 6,
"status": "active",
"spots": [
{
"id": "bf5b7d9e-3a4c-4d6f-8b8e-0a2c4e6f8ba3",
"name": "Sillón 1",
"position": 1,
"status": "active"
}
],
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | The body is not JSON, or a field is missing or invalid (details.errors lists each field). |
| 400 | validation_error | location_id is not a location of yours, or it is archived (details.ids). |
| 404 | not_found | No room with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
| 409 | validation_error | The room is archived (removed). |
| 409 | validation_error | The change would make the room active in a location that isn't active, or move an active room into one (details.reason location_closed). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Archive a room
/v1/clinic/rooms/:idArchives the room (the dashboard's Remove). Archiving an archived room changes nothing.
clinic_setup:writeCan wait for approvalWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The room id. |
Example request
curl -X DELETE "https://www.nutalk.ai/v1/clinic/rooms/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY"The room is archived.
{
"success": true,
"data": {
"id": "ae4a6c8d-2f3b-4c5e-9a7d-9f1b3d5e7a92",
"archived": true
}
}Errors
| Status | Code | When |
|---|---|---|
| 404 | not_found | No room with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Add a spot
/v1/clinic/rooms/:id/spotsAdds a spot to a room: one more place that holds one appointment at a time.
clinic_setup:writeSupports Idempotency-KeyWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The room id. |
Request body (JSON)
| Name | Type | Description |
|---|---|---|
nameRequired | string | The spot's name, e.g. |
position | integer | Its order in the room (default 1). 1–200. |
Example request
curl -X POST "https://www.nutalk.ai/v1/clinic/rooms/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7/spots" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Idempotency-Key: 11111111-2222-4333-8444-555555555555" \ -H "Content-Type: application/json" \ -d '{ "name": "Sillón 2", "position": 2}'The spot.
{
"success": true,
"data": {
"id": "bf5b7d9e-3a4c-4d6f-8b8e-0a2c4e6f8ba3",
"room_id": "ae4a6c8d-2f3b-4c5e-9a7d-9f1b3d5e7a92",
"name": "Sillón 2",
"position": 2,
"status": "active",
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | The body is not JSON, or a field is missing or invalid (details.errors lists each field). |
| 404 | not_found | No room with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
| 409 | validation_error | The room is archived (removed). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Update a spot
/v1/clinic/spots/:idRenames, reorders or switches off one spot (an id from its room's spots).
clinic_setup:writeCan wait for approvalWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The spot id. |
Request body (JSON)
| Name | Type | Description |
|---|---|---|
name | string | The spot's name, e.g. |
position | integer | Its order in the room (default 1). 1–200. |
status | string |
|
Example request
curl -X PATCH "https://www.nutalk.ai/v1/clinic/spots/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "status": "inactive"}'The updated spot.
{
"success": true,
"data": {
"id": "bf5b7d9e-3a4c-4d6f-8b8e-0a2c4e6f8ba3",
"room_id": "ae4a6c8d-2f3b-4c5e-9a7d-9f1b3d5e7a92",
"name": "Sillón 2",
"position": 2,
"status": "inactive",
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | The body is not JSON, or a field is missing or invalid (details.errors lists each field). |
| 404 | not_found | No spot with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
| 409 | validation_error | The spot is archived (removed). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Archive a spot
/v1/clinic/spots/:idArchives one spot. Archiving an archived spot changes nothing.
clinic_setup:writeCan wait for approvalWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The spot id. |
Example request
curl -X DELETE "https://www.nutalk.ai/v1/clinic/spots/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY"The spot is archived.
{
"success": true,
"data": {
"id": "bf5b7d9e-3a4c-4d6f-8b8e-0a2c4e6f8ba3",
"archived": true
}
}Errors
| Status | Code | When |
|---|---|---|
| 404 | not_found | No spot with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
Plus the errors every request can return (401, 403, 429, 500): Errors.
List doctors
/v1/clinic/doctorsLists the people who take clinic appointments, by name: doctors, nurses, therapists, technicians and other staff (their role).
clinic_setup:readA removed doctor reads status: "archived": listed only with that filter, kept so past appointments keep the name.
Query parameters
| Name | Type | Description |
|---|---|---|
limit | integer | Results per page. 1–100. Default: |
offset | integer | Results to skip. At least 0. Default: |
status | string | Only doctors in this status. Without it, every doctor but the archived ones. One of: active, inactive, archived. |
role | string | Only this role. One of: doctor, nurse, therapist, technician, staff. |
location_id | uuid | Only doctors whose default location is this one. |
Example request
curl -X GET "https://www.nutalk.ai/v1/clinic/doctors" \ -H "Authorization: Bearer YOUR_API_KEY"A page of doctors.
{
"success": true,
"data": [
{
"id": "3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7",
"name": "Dra. Ana López",
"role": "doctor",
"specialty": "Dermatología",
"email": "ana.lopez@clinica.mx",
"phone_number": "+528112345679",
"timezone": "America/Monterrey",
"status": "active",
"default_location_id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70",
"default_room_id": null,
"max_concurrent_supervised": 3,
"user_id": null,
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
],
"pagination": {
"total": 1,
"limit": 20,
"offset": 0,
"has_more": false
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | A query parameter is invalid (details.errors lists each one). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Add a doctor
/v1/clinic/doctorsAdds a doctor (or nurse, therapist…) to Clinic Scheduling. They take appointments once they have weekly hours (PUT /clinic/doctors/{id}/weekly-hours) and a service allows them.
clinic_setup:writeSupports Idempotency-KeyWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Request body (JSON)
| Name | Type | Description |
|---|---|---|
nameRequired | string | How patients and the agents name them. 1–200 characters. |
role | string | What they do (default |
specialty | string | null | Shown to patients and the agents. Up to 200 characters. |
email | string | null | Contact email. Up to 320 characters. |
phone_number | string | null | Contact phone. Up to 40 characters. |
timezone | string | IANA time zone of their clock. Without it, their clinic's (their location's, else the workspace's). Up to 64 characters. |
default_location_id | uuid | null | Where they usually work (an active location of yours). |
default_room_id | uuid | null | The room they usually use (an active room of yours). |
max_concurrent_supervised | integer | How many |
user_id | uuid | null | The workspace member who is this doctor (their My Schedule shows these appointments); null unlinks. |
Example request
curl -X POST "https://www.nutalk.ai/v1/clinic/doctors" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Idempotency-Key: 11111111-2222-4333-8444-555555555555" \ -H "Content-Type: application/json" \ -d '{ "name": "Dra. Ana López", "role": "doctor", "specialty": "Dermatología", "email": "ana.lopez@clinica.mx", "default_location_id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70"}'The doctor.
{
"success": true,
"data": {
"id": "3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7",
"name": "Dra. Ana López",
"role": "doctor",
"specialty": "Dermatología",
"email": "ana.lopez@clinica.mx",
"phone_number": "+528112345679",
"timezone": "America/Monterrey",
"status": "active",
"default_location_id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70",
"default_room_id": null,
"max_concurrent_supervised": 3,
"user_id": null,
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | The body is not JSON, or a field is missing or invalid (details.errors lists each field). |
| 400 | validation_error | default_location_id or default_room_id is not an active location or room of yours, or user_id is not a member of the workspace. |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Get a doctor
/v1/clinic/doctors/:idReturns one doctor (removed ones too).
clinic_setup:readPath parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The doctor id. |
Example request
curl -X GET "https://www.nutalk.ai/v1/clinic/doctors/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY"The doctor.
{
"success": true,
"data": {
"id": "3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7",
"name": "Dra. Ana López",
"role": "doctor",
"specialty": "Dermatología",
"email": "ana.lopez@clinica.mx",
"phone_number": "+528112345679",
"timezone": "America/Monterrey",
"status": "active",
"default_location_id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70",
"default_room_id": null,
"max_concurrent_supervised": 3,
"user_id": null,
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
}Errors
| Status | Code | When |
|---|---|---|
| 404 | not_found | No doctor with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Update a doctor
/v1/clinic/doctors/:idChanges the fields you send. inactive stops new bookings and keeps their appointments; removing them is the DELETE. warnings lists the dates whose day changes a new time zone could not rebuild.
clinic_setup:writeCan wait for approvalWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The doctor id. |
Request body (JSON)
| Name | Type | Description |
|---|---|---|
name | string | How patients and the agents name them. 1–200 characters. |
role | string | What they do: services can require a role. One of: doctor, nurse, therapist, technician, staff. |
specialty | string | null | Shown to patients and the agents. Up to 200 characters. |
email | string | null | Contact email. Up to 320 characters. |
phone_number | string | null | Contact phone. Up to 40 characters. |
timezone | string | IANA time zone of their clock. A new zone moves their weekly hours with it (same wall times) and rebuilds their day changes. Up to 64 characters. |
default_location_id | uuid | null | Where they usually work (an active location of yours). |
default_room_id | uuid | null | The room they usually use (an active room of yours). |
max_concurrent_supervised | integer | How many |
user_id | uuid | null | The workspace member who is this doctor (their My Schedule shows these appointments); null unlinks. |
status | string |
|
Example request
curl -X PATCH "https://www.nutalk.ai/v1/clinic/doctors/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "specialty": "Dermatología pediátrica"}'The updated doctor.
{
"success": true,
"data": {
"id": "3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7",
"name": "Dra. Ana López",
"role": "doctor",
"specialty": "Dermatología pediátrica",
"email": "ana.lopez@clinica.mx",
"phone_number": "+528112345679",
"timezone": "America/Monterrey",
"status": "active",
"default_location_id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70",
"default_room_id": null,
"max_concurrent_supervised": 3,
"user_id": null,
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | The body is not JSON, or a field is missing or invalid (details.errors lists each field). |
| 400 | validation_error | A location, room or member named is not yours, or timezone is not an IANA time zone. |
| 404 | not_found | No doctor with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
| 409 | validation_error | The doctor was removed, or a new user_id while their calendar accounts are connected (disconnect them first). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Remove a doctor
/v1/clinic/doctors/:idRemoves the doctor (the dashboard's Remove): refused while they have an upcoming appointment (move or cancel it, or set them inactive instead). Their calendar links, calendar subscriptions and round-robin places go; the record stays archived so past appointments keep the name.
clinic_setup:writeCan wait for approvalWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The doctor id. |
Example request
curl -X DELETE "https://www.nutalk.ai/v1/clinic/doctors/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY"The doctor is removed (already_removed when they were).
{
"success": true,
"data": {
"id": "3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7",
"removed": true,
"already_removed": false,
"past_appointments_kept": 12
}
}Errors
| Status | Code | When |
|---|---|---|
| 404 | not_found | No doctor with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
| 409 | validation_error | They have upcoming appointments (details.reason is PROVIDER_HAS_UPCOMING_APPOINTMENTS, details.upcoming_appointments the count). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Get a doctor's weekly hours
/v1/clinic/doctors/:id/weekly-hoursReturns the doctor's recurring week: hours, the every-week ranges on their own clock that PUT replaces, and other_hours, the rows a PUT keeps as they are (alternate weeks, hours bounded to dates, hours on another clock; edited in the dashboard).
clinic_setup:readother_hours rows also carry timezone, every_weeks with anchor_date (every other week, …) and effective_start/effective_end (dates the row applies between).
Days off and day changes are not part of the week: see the doctor's days off.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The doctor id. |
Example request
curl -X GET "https://www.nutalk.ai/v1/clinic/doctors/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7/weekly-hours" \ -H "Authorization: Bearer YOUR_API_KEY"The doctor's week. Times are HH:MM on timezone; day_of_week 0 is Sunday.
{
"success": true,
"data": {
"doctor_id": "3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7",
"timezone": "America/Monterrey",
"hours": [
{
"id": "e28ea0c1-6d7f-4a9c-9ebc-3d5f7b9cbed6",
"day_of_week": 1,
"start": "09:00",
"end": "14:00",
"location_id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70",
"room_id": null,
"slot_interval_minutes": 15
}
],
"other_hours": []
}
}Errors
| Status | Code | When |
|---|---|---|
| 404 | not_found | No doctor with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Set a doctor's weekly hours
/v1/clinic/doctors/:id/weekly-hoursReplaces the doctor's every-week hours with hours: the whole week, so a weekday left out has no hours and [] clears the week. It runs through the dashboard's weekly-hours writer: ranges of one day can't overlap, other_hours are kept, the day changes of the weekdays that change are rebuilt, and the appointments the new week leaves outside its hours are listed (never cancelled: reception gives them a new time).
clinic_setup:writeCan wait for approvalWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
The hours are saved on the doctor's clock: a later time zone change moves them with it.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The doctor id. |
Request body (JSON)
| Name | Type | Description |
|---|---|---|
hoursRequired | object[] | The week's ranges. 0–56 items. |
hours[].day_of_weekRequired | integer | 0 = Sunday … 6 = Saturday. 0–6. |
hours[].startRequired | string | HH:MM (24-hour) on the doctor's clock. |
hours[].endRequired | string | HH:MM after start (23:59 at the latest). |
hours[].id | uuid | The range of GET it replaces: it keeps that range's location, room and slot step. A new range takes its weekday's first range's, else the doctor's default location. |
dry_run | boolean | true: saves nothing and lists the appointments the new week would leave outside. Default: |
Example request
curl -X PUT "https://www.nutalk.ai/v1/clinic/doctors/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7/weekly-hours" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "hours": [ { "day_of_week": 1, "start": "09:00", "end": "14:00" }, { "day_of_week": 1, "start": "16:00", "end": "19:00" }, { "day_of_week": 3, "start": "09:00", "end": "14:00" } ]}'The outcome: conflicts (the first 200) and conflict_count count the appointments left outside the new hours (patient_name and service are null unless the key holds appointments:read); recompile_warnings names the dates whose day changes could not be rebuilt (recompile_failed when the rebuild failed altogether: open those days in the dashboard); weekly_hours is the saved week (null on a dry run).
{
"success": true,
"data": {
"dry_run": false,
"conflicts": [
{
"id": "6b1d2c3e-4f5a-4b6c-8d7e-9f0a1b2c3d4e",
"starts_at": "2026-10-19T22:00:00.000Z",
"ends_at": "2026-10-19T22:30:00.000Z",
"timezone": "America/Monterrey",
"patient_name": "María Pérez",
"service": "Consulta dermatológica"
}
],
"conflict_count": 1,
"recompile_warnings": [],
"recompile_failed": false,
"weekly_hours": {
"doctor_id": "3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7",
"timezone": "America/Monterrey",
"hours": [
{
"id": "e28ea0c1-6d7f-4a9c-9ebc-3d5f7b9cbed6",
"day_of_week": 1,
"start": "09:00",
"end": "14:00",
"location_id": "8c2e4a6b-0d1f-4a3c-9e5b-7d9f1b3c5e70",
"room_id": null,
"slot_interval_minutes": 15
}
],
"other_hours": []
}
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | The body is not JSON, or a field is missing or invalid (details.errors lists each field). |
| 400 | validation_error | Two ranges of a day overlap (details.reason WEEKLY_OVERLAP, details.day_of_week), or a day mixes two time zones (WEEKLY_TIMEZONE_MIX). |
| 404 | not_found | No doctor with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
| 409 | validation_error | The doctor was removed, has too many schedule rows, or the weekdays changed have more than 25 day changes ahead (WEEKLY_TOO_MANY_DAY_CHANGES: change fewer weekdays at a time). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
List a doctor's days off
/v1/clinic/doctors/:id/days-offLists the doctor's blocked time (days off, time off), soonest first: by default what has not ended yet.
clinic_setup:readDay changes the clinic made to the doctor's hours for one date are not days off and are left out.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The doctor id. |
Query parameters
| Name | Type | Description |
|---|---|---|
limit | integer | Results per page. 1–100. Default: |
offset | integer | Results to skip. At least 0. Default: |
from | datetime | Only blocks that end after this time (default: now). |
to | datetime | Only blocks that start before this time. |
Example request
curl -X GET "https://www.nutalk.ai/v1/clinic/doctors/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7/days-off?from=2026-12-01T00:00:00Z" \ -H "Authorization: Bearer YOUR_API_KEY"A page of blocked times.
{
"success": true,
"data": [
{
"id": "f39fb1d2-7e8a-4bad-8fcd-4e6a8cadcfe7",
"doctor_id": "3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7",
"starts_at": "2026-12-24T06:00:00+00:00",
"ends_at": "2026-12-26T06:00:00+00:00",
"reason": "Vacaciones",
"created_at": "2026-10-12T16:02:11.402+00:00"
}
],
"pagination": {
"total": 1,
"limit": 20,
"offset": 0,
"has_more": false
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | A query parameter is invalid (details.errors lists each one). |
| 404 | not_found | No doctor with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Block a doctor's time
/v1/clinic/doctors/:id/days-offBlocks the doctor's time (a day off, a vacation, an afternoon) through the database's one write path for it: it joins the blocks it touches, refuses time that already ended, and lists the appointments inside. Those stay booked: reception moves them. Send the time as instants (starts_at, ends_at), as part of one day on the doctor's clock (date, from, to), or as whole days on the doctor's clock (first_date, last_date).
clinic_setup:writeSupports Idempotency-KeyWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The doctor id. |
Request body (JSON)
| Name | Type | Description |
|---|---|---|
starts_at | datetime | With ends_at: the block's start. |
ends_at | datetime | With starts_at: the block's end. |
date | string | With from and to: the day (YYYY-MM-DD) on the doctor's clock. |
from | string | HH:MM the block starts that day. |
to | string | HH:MM the block ends that day. |
first_date | string | With last_date: the first whole day off (YYYY-MM-DD). |
last_date | string | The last whole day off, included. |
reason | string | null | Why (shown to the team). Up to 500 characters. |
dry_run | boolean | true: saves nothing; lists what the block would cover. Default: |
conflicts_key | string | The |
Example request
curl -X POST "https://www.nutalk.ai/v1/clinic/doctors/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7/days-off" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Idempotency-Key: 11111111-2222-4333-8444-555555555555" \ -H "Content-Type: application/json" \ -d '{ "first_date": "2026-12-24", "last_date": "2026-12-25", "reason": "Vacaciones"}'The block was made (200 for a dry run). day_off is the stored block (null on a dry run), starts_at/ends_at its range after joining, joined the blocks it absorbed, conflicts (the first 200) and conflict_count the appointments inside (patient_name and service are null unless the key holds appointments:read), conflicts_key names that set.
{
"success": true,
"data": {
"dry_run": false,
"day_off": {
"id": "f39fb1d2-7e8a-4bad-8fcd-4e6a8cadcfe7",
"doctor_id": "3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7",
"starts_at": "2026-12-24T06:00:00+00:00",
"ends_at": "2026-12-26T06:00:00+00:00",
"reason": "Vacaciones",
"created_at": "2026-10-12T16:02:11.402+00:00"
},
"starts_at": "2026-12-24T06:00:00+00:00",
"ends_at": "2026-12-26T06:00:00+00:00",
"joined": [],
"conflicts": [],
"conflict_count": 0,
"conflicts_key": "00000000000000000000000000000abc"
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | The body is not JSON, or a field is missing or invalid (details.errors lists each field). |
| 400 | validation_error | The time already ended (details.reason CLINIC_BLOCK_IN_PAST) or is too long (CLINIC_BLOCK_TOO_LONG). |
| 404 | not_found | No doctor with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
| 409 | validation_error | The doctor was removed, or the appointments inside changed since the dry run whose conflicts_key was sent (CLINIC_BLOCK_APPOINTMENTS_CHANGED). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Remove a day off
/v1/clinic/days-off/:idRemoves a doctor's blocked time (an id from their days off): the time is open for booking again at once.
clinic_setup:writeCan wait for approvalWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The day off id. |
Example request
curl -X DELETE "https://www.nutalk.ai/v1/clinic/days-off/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY"The block was removed.
{
"success": true,
"data": {
"id": "f39fb1d2-7e8a-4bad-8fcd-4e6a8cadcfe7",
"deleted": true
}
}Errors
| Status | Code | When |
|---|---|---|
| 404 | not_found | No day off with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
| 409 | validation_error | Another block joined into it meanwhile (details.reason CLINIC_BLOCK_CHANGED): read the doctor's days off again. |
Plus the errors every request can return (401, 403, 429, 500): Errors.
List services
/v1/clinic/servicesLists the services patients book (appointment types) in the clinic's display order, with the rules the scheduling engine applies and the facts the agents answer from.
clinic_setup:readQuery parameters
| Name | Type | Description |
|---|---|---|
limit | integer | Results per page. 1–100. Default: |
offset | integer | Results to skip. At least 0. Default: |
status | string | Only services in this status. Without it, every service but the archived ones. One of: active, inactive, archived. |
category | string | Only services of this category (exact). |
Example request
curl -X GET "https://www.nutalk.ai/v1/clinic/services" \ -H "Authorization: Bearer YOUR_API_KEY"A page of services.
{
"success": true,
"data": [
{
"id": "c06c8eaf-4b5d-4e7a-9c9f-1b3d5f7a9cb4",
"name": "Consulta dermatológica",
"description": "Valoración de piel, cabello y uñas.",
"category": "Dermatología",
"status": "active",
"duration_minutes": 30,
"buffer_before_minutes": 0,
"buffer_after_minutes": 10,
"color": "#0EA5E9",
"default_room_id": null,
"required_room_type": null,
"eligible_spot_ids": [],
"staff_involvement": "exclusive",
"required_staff_role": "doctor",
"allowed_doctor_ids": [
"3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7"
],
"min_notice_minutes": 60,
"max_advance_days": 90,
"full_hour_start": false,
"requires_human_confirmation": false,
"currency": "MXN",
"price": 900,
"price_note": null,
"search_aliases": [
"consulta de piel",
"dermatólogo"
],
"benefits": [],
"indications": [],
"contraindications": [],
"preparation_instructions": "Llegar sin maquillaje.",
"aftercare_instructions": null,
"patient_arrival_offset_minutes": 10,
"intake_form_required": false,
"intake_form_url": null,
"intake_form_instructions": null,
"handoff_summary": null,
"modality": null,
"mechanism_summary": null,
"ideal_candidate": null,
"operational_notes": null,
"service_details": [],
"information_sources": [],
"content_review_status": "tenant_confirmed",
"display_order": 100,
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
],
"pagination": {
"total": 1,
"limit": 20,
"offset": 0,
"has_more": false
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | A query parameter is invalid (details.errors lists each one). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Create a service
/v1/clinic/servicesCreates a service. Every field but name is optional.
clinic_setup:writeSupports Idempotency-KeyWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Request body (JSON)
| Name | Type | Description |
|---|---|---|
nameRequired | string | What patients book, e.g. |
description | string | null | What it is; the agents read it. Up to 5000 characters. |
category | string | null | A label to group services. Up to 200 characters. |
duration_minutes | integer | How long it takes (default 30). 5–480. |
buffer_before_minutes | integer | Time kept free before it. 0–240. |
buffer_after_minutes | integer | Time kept free after it. 0–240. |
color | string | null | Calendar color, |
default_room_id | uuid | null | The room it is usually booked in. |
required_room_type | string | null | Only rooms with this |
eligible_spot_ids | uuid[] | The spots it can be booked in, the main one first (active spots of yours). Replaces the stored list; [] removes the restriction. 0–100 items. |
staff_involvement | string |
|
required_staff_role | string | null | Only doctors with this role can take it. One of: doctor, nurse, therapist, technician, staff. |
allowed_doctor_ids | uuid[] | Only these doctors can take it (doctors of yours). Replaces the stored list; [] lets every qualified doctor take it. 0–200 items. |
min_notice_minutes | integer | How far ahead it must be booked (default 60). 0–20160. |
max_advance_days | integer | How far into the future it can be booked (default 90). 1–365. |
full_hour_start | boolean | Starts only on the hour. |
requires_human_confirmation | boolean | The agents don't book it on their own: reception or an outside provider confirms first. |
currency | string | ISO 4217 code of the price (default MXN). 3–3 characters. |
price | number | null | The regular price, in |
price_note | string | null | What the price includes or depends on. Up to 1000 characters. |
search_aliases | string[] | Other names patients use for it (the agents match them). Replaces the stored list. 0–50 items. |
benefits | string[] | Benefits the agents can mention. Replaces the stored list. 0–50 items. |
indications | string[] | Who it is for. Replaces the stored list. 0–50 items. |
contraindications | string[] | Who should not take it. Replaces the stored list. 0–50 items. |
preparation_instructions | string | null | What the patient does before coming. Up to 5000 characters. |
aftercare_instructions | string | null | What the patient does afterwards. Up to 5000 characters. |
patient_arrival_offset_minutes | integer | null | How many minutes early the patient should arrive. 0–240. |
intake_form_required | boolean | The patient fills a form before the visit. |
intake_form_url | string | null | The form's link. Up to 2000 characters. |
intake_form_instructions | string | null | How to fill it. Up to 5000 characters. |
handoff_summary | string | null | What the agents tell reception when they hand a patient over. Up to 5000 characters. |
modality | string | null | How it is given (e.g. in person, IV). Up to 200 characters. |
mechanism_summary | string | null | How it works, in plain words. Up to 5000 characters. |
ideal_candidate | string | null | Who benefits most. Up to 5000 characters. |
operational_notes | string | null | Notes for the team. Up to 5000 characters. |
service_details | string[] | Further facts the agents can share. Replaces the stored list. 0–50 items. |
information_sources | string[] | Where the facts above come from. Replaces the stored list. 0–50 items. |
content_review_status | string | How far the patient-facing content was reviewed (default |
display_order | integer | Lower comes first in lists (default 100). 0–10000. |
Example request
curl -X POST "https://www.nutalk.ai/v1/clinic/services" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Idempotency-Key: 11111111-2222-4333-8444-555555555555" \ -H "Content-Type: application/json" \ -d '{ "name": "Consulta dermatológica", "duration_minutes": 30, "buffer_after_minutes": 10, "required_staff_role": "doctor", "allowed_doctor_ids": [ "3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" ], "currency": "MXN", "price": 900, "search_aliases": [ "consulta de piel", "dermatólogo" ]}'The service.
{
"success": true,
"data": {
"id": "c06c8eaf-4b5d-4e7a-9c9f-1b3d5f7a9cb4",
"name": "Consulta dermatológica",
"description": "Valoración de piel, cabello y uñas.",
"category": "Dermatología",
"status": "active",
"duration_minutes": 30,
"buffer_before_minutes": 0,
"buffer_after_minutes": 10,
"color": "#0EA5E9",
"default_room_id": null,
"required_room_type": null,
"eligible_spot_ids": [],
"staff_involvement": "exclusive",
"required_staff_role": "doctor",
"allowed_doctor_ids": [
"3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7"
],
"min_notice_minutes": 60,
"max_advance_days": 90,
"full_hour_start": false,
"requires_human_confirmation": false,
"currency": "MXN",
"price": 900,
"price_note": null,
"search_aliases": [
"consulta de piel",
"dermatólogo"
],
"benefits": [],
"indications": [],
"contraindications": [],
"preparation_instructions": "Llegar sin maquillaje.",
"aftercare_instructions": null,
"patient_arrival_offset_minutes": 10,
"intake_form_required": false,
"intake_form_url": null,
"intake_form_instructions": null,
"handoff_summary": null,
"modality": null,
"mechanism_summary": null,
"ideal_candidate": null,
"operational_notes": null,
"service_details": [],
"information_sources": [],
"content_review_status": "tenant_confirmed",
"display_order": 100,
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | The body is not JSON, or a field is missing or invalid (details.errors lists each field). |
| 400 | validation_error | A room, spot or doctor named is not an active one of yours. |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Get a service
/v1/clinic/services/:idReturns one service (archived ones too).
clinic_setup:readPath parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The service id. |
Example request
curl -X GET "https://www.nutalk.ai/v1/clinic/services/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY"The service.
{
"success": true,
"data": {
"id": "c06c8eaf-4b5d-4e7a-9c9f-1b3d5f7a9cb4",
"name": "Consulta dermatológica",
"description": "Valoración de piel, cabello y uñas.",
"category": "Dermatología",
"status": "active",
"duration_minutes": 30,
"buffer_before_minutes": 0,
"buffer_after_minutes": 10,
"color": "#0EA5E9",
"default_room_id": null,
"required_room_type": null,
"eligible_spot_ids": [],
"staff_involvement": "exclusive",
"required_staff_role": "doctor",
"allowed_doctor_ids": [
"3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7"
],
"min_notice_minutes": 60,
"max_advance_days": 90,
"full_hour_start": false,
"requires_human_confirmation": false,
"currency": "MXN",
"price": 900,
"price_note": null,
"search_aliases": [
"consulta de piel",
"dermatólogo"
],
"benefits": [],
"indications": [],
"contraindications": [],
"preparation_instructions": "Llegar sin maquillaje.",
"aftercare_instructions": null,
"patient_arrival_offset_minutes": 10,
"intake_form_required": false,
"intake_form_url": null,
"intake_form_instructions": null,
"handoff_summary": null,
"modality": null,
"mechanism_summary": null,
"ideal_candidate": null,
"operational_notes": null,
"service_details": [],
"information_sources": [],
"content_review_status": "tenant_confirmed",
"display_order": 100,
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
}Errors
| Status | Code | When |
|---|---|---|
| 404 | not_found | No service with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Update a service
/v1/clinic/services/:idChanges the fields you send; a list replaces the stored list. Booked appointments keep their time.
clinic_setup:writeCan wait for approvalWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The service id. |
Request body (JSON)
| Name | Type | Description |
|---|---|---|
name | string | What patients book, e.g. |
description | string | null | What it is; the agents read it. Up to 5000 characters. |
category | string | null | A label to group services. Up to 200 characters. |
duration_minutes | integer | How long it takes. 5–480. |
buffer_before_minutes | integer | Time kept free before it. 0–240. |
buffer_after_minutes | integer | Time kept free after it. 0–240. |
color | string | null | Calendar color, |
default_room_id | uuid | null | The room it is usually booked in. |
required_room_type | string | null | Only rooms with this |
eligible_spot_ids | uuid[] | The spots it can be booked in, the main one first (active spots of yours). Replaces the stored list; [] removes the restriction. 0–100 items. |
staff_involvement | string |
|
required_staff_role | string | null | Only doctors with this role can take it. One of: doctor, nurse, therapist, technician, staff. |
allowed_doctor_ids | uuid[] | Only these doctors can take it (doctors of yours). Replaces the stored list; [] lets every qualified doctor take it. 0–200 items. |
min_notice_minutes | integer | How far ahead it must be booked (default 60). 0–20160. |
max_advance_days | integer | How far into the future it can be booked (default 90). 1–365. |
full_hour_start | boolean | Starts only on the hour. |
requires_human_confirmation | boolean | The agents don't book it on their own: reception or an outside provider confirms first. |
currency | string | ISO 4217 code of the price (default MXN). 3–3 characters. |
price | number | null | The regular price, in |
price_note | string | null | What the price includes or depends on. Up to 1000 characters. |
search_aliases | string[] | Other names patients use for it (the agents match them). Replaces the stored list. 0–50 items. |
benefits | string[] | Benefits the agents can mention. Replaces the stored list. 0–50 items. |
indications | string[] | Who it is for. Replaces the stored list. 0–50 items. |
contraindications | string[] | Who should not take it. Replaces the stored list. 0–50 items. |
preparation_instructions | string | null | What the patient does before coming. Up to 5000 characters. |
aftercare_instructions | string | null | What the patient does afterwards. Up to 5000 characters. |
patient_arrival_offset_minutes | integer | null | How many minutes early the patient should arrive. 0–240. |
intake_form_required | boolean | The patient fills a form before the visit. |
intake_form_url | string | null | The form's link. Up to 2000 characters. |
intake_form_instructions | string | null | How to fill it. Up to 5000 characters. |
handoff_summary | string | null | What the agents tell reception when they hand a patient over. Up to 5000 characters. |
modality | string | null | How it is given (e.g. in person, IV). Up to 200 characters. |
mechanism_summary | string | null | How it works, in plain words. Up to 5000 characters. |
ideal_candidate | string | null | Who benefits most. Up to 5000 characters. |
operational_notes | string | null | Notes for the team. Up to 5000 characters. |
service_details | string[] | Further facts the agents can share. Replaces the stored list. 0–50 items. |
information_sources | string[] | Where the facts above come from. Replaces the stored list. 0–50 items. |
content_review_status | string | How far the patient-facing content was reviewed (default |
display_order | integer | Lower comes first in lists (default 100). 0–10000. |
status | string |
|
Example request
curl -X PATCH "https://www.nutalk.ai/v1/clinic/services/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "price": 950, "price_note": "Incluye revisión con dermatoscopio."}'The updated service.
{
"success": true,
"data": {
"id": "c06c8eaf-4b5d-4e7a-9c9f-1b3d5f7a9cb4",
"name": "Consulta dermatológica",
"description": "Valoración de piel, cabello y uñas.",
"category": "Dermatología",
"status": "active",
"duration_minutes": 30,
"buffer_before_minutes": 0,
"buffer_after_minutes": 10,
"color": "#0EA5E9",
"default_room_id": null,
"required_room_type": null,
"eligible_spot_ids": [],
"staff_involvement": "exclusive",
"required_staff_role": "doctor",
"allowed_doctor_ids": [
"3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7"
],
"min_notice_minutes": 60,
"max_advance_days": 90,
"full_hour_start": false,
"requires_human_confirmation": false,
"currency": "MXN",
"price": 950,
"price_note": "Incluye revisión con dermatoscopio.",
"search_aliases": [
"consulta de piel",
"dermatólogo"
],
"benefits": [],
"indications": [],
"contraindications": [],
"preparation_instructions": "Llegar sin maquillaje.",
"aftercare_instructions": null,
"patient_arrival_offset_minutes": 10,
"intake_form_required": false,
"intake_form_url": null,
"intake_form_instructions": null,
"handoff_summary": null,
"modality": null,
"mechanism_summary": null,
"ideal_candidate": null,
"operational_notes": null,
"service_details": [],
"information_sources": [],
"content_review_status": "tenant_confirmed",
"display_order": 100,
"created_at": "2026-10-12T16:02:11.402+00:00",
"updated_at": "2026-10-12T16:02:11.402+00:00"
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | The body is not JSON, or a field is missing or invalid (details.errors lists each field). |
| 400 | validation_error | A room, spot or doctor named is not an active one of yours. |
| 404 | not_found | No service with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
| 409 | validation_error | The service is archived (removed). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Archive a service
/v1/clinic/services/:idArchives the service: it can no longer be booked; booked appointments and history keep it. Archiving an archived service changes nothing.
clinic_setup:writeCan wait for approvalWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Path parameters
| Name | Type | Description |
|---|---|---|
idRequired | uuid | The service id. |
Example request
curl -X DELETE "https://www.nutalk.ai/v1/clinic/services/3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" \ -H "Authorization: Bearer YOUR_API_KEY"The service is archived.
{
"success": true,
"data": {
"id": "c06c8eaf-4b5d-4e7a-9c9f-1b3d5f7a9cb4",
"archived": true
}
}Errors
| Status | Code | When |
|---|---|---|
| 404 | not_found | No service with this id in your workspace (ids of other workspaces answer the same). |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Get clinic settings
/v1/clinic/settingsReturns the clinic-wide settings: booking several services at once, how the AI agents offer and start appointments, and the round robin of new patients among doctors with each service's roster.
clinic_setup:readExample request
curl -X GET "https://www.nutalk.ai/v1/clinic/settings" \ -H "Authorization: Bearer YOUR_API_KEY"The settings.
{
"success": true,
"data": {
"allow_manual_simultaneous_services": false,
"ai_start_grid_minutes": 30,
"ai_offer_policy": {
"enabled": true,
"days": 2,
"options_per_daypart": 2,
"afternoon_start_minute": 780,
"rules": [
{
"day_of_week": 6,
"start_minute": 600,
"end_minute": 720,
"kind": "blocked"
}
]
},
"round_robin": {
"enabled": true,
"preference_consumes_turn": false,
"annul_on_switch": true,
"keep_existing_patients": true,
"full_agenda_behavior": "advance",
"full_agenda_days": 7,
"services": [
{
"service_id": "c06c8eaf-4b5d-4e7a-9c9f-1b3d5f7a9cb4",
"enabled": true,
"doctor_ids": [
"3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7"
]
}
]
}
}
}Errors
| Status | Code | When |
|---|---|---|
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
Plus the errors every request can return (401, 403, 429, 500): Errors.
Update clinic settings
/v1/clinic/settingsChanges the settings you send and returns them all. Service rosters are saved first, then the round-robin switches, then the clinic-wide settings, as the dashboard saves them; when one is refused, the ones before it stay saved.
clinic_setup:writeCan wait for approvalWorkspace keys only · acts as the key's creatorThe change runs through the dashboard's own Clinic Scheduling handler (the same rules as the dashboard), acting as the member who created the key: their role, at most admin, must allow it. It is recorded as the key's.
Request body (JSON)
| Name | Type | Description |
|---|---|---|
allow_manual_simultaneous_services | boolean | Reception (and the API) may book several services for one patient at the same time. |
ai_start_grid_minutes | integer | The minutes the AI agents may start an appointment on: 15 (any start the hours give), 30 (:00 and :30) or 60 (on the hour). Never applies to reception's bookings. |
ai_offer_policy | object | How the AI agents offer times (the whole policy; every field required). Never applies to reception's bookings. |
ai_offer_policy.enabledRequired | boolean | false switches the rules off. |
ai_offer_policy.daysRequired | integer | Lead with the first this many dates that have openings. 1–5. |
ai_offer_policy.options_per_daypartRequired | integer | Times offered per morning and per afternoon. 1–3. |
ai_offer_policy.afternoon_start_minuteRequired | integer | Minutes after midnight the afternoon starts (on the hour or half hour, 10:00 to 18:00). 600–1080. |
ai_offer_policy.rulesRequired | object[] | Weekly times the agents offer first ( |
round_robin | object | The round robin of new patients among doctors. Only the fields sent change. |
round_robin.enabled | boolean | The master switch. |
round_robin.preference_consumes_turn | boolean | A patient who asks for a doctor still counts as that doctor's turn. |
round_robin.annul_on_switch | boolean | When the conversation books another doctor, the first assignment is annulled. |
round_robin.keep_existing_patients | boolean | Returning patients keep their doctor. |
round_robin.full_agenda_behavior | string | When the assigned doctor has no opening soon: |
round_robin.full_agenda_days | integer | What "soon" means, in days. 1–30. |
round_robin.services | object[] | Per-service rosters to save (each replaces that service's roster; services not listed keep theirs). Saved before the switches. 0–200 items. |
Example request
curl -X PATCH "https://www.nutalk.ai/v1/clinic/settings" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "ai_start_grid_minutes": 30, "round_robin": { "enabled": true, "services": [ { "service_id": "c06c8eaf-4b5d-4e7a-9c9f-1b3d5f7a9cb4", "enabled": true, "doctor_ids": [ "3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7" ] } ] }}'Every setting, as saved.
{
"success": true,
"data": {
"allow_manual_simultaneous_services": false,
"ai_start_grid_minutes": 30,
"ai_offer_policy": {
"enabled": true,
"days": 2,
"options_per_daypart": 2,
"afternoon_start_minute": 780,
"rules": [
{
"day_of_week": 6,
"start_minute": 600,
"end_minute": 720,
"kind": "blocked"
}
]
},
"round_robin": {
"enabled": true,
"preference_consumes_turn": false,
"annul_on_switch": true,
"keep_existing_patients": true,
"full_agenda_behavior": "advance",
"full_agenda_days": 7,
"services": [
{
"service_id": "c06c8eaf-4b5d-4e7a-9c9f-1b3d5f7a9cb4",
"enabled": true,
"doctor_ids": [
"3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7"
]
}
]
}
}
}Errors
| Status | Code | When |
|---|---|---|
| 400 | validation_error | The body is not JSON, or a field is missing or invalid (details.errors lists each field). |
| 400 | validation_error | ai_offer_policy is not a whole valid policy, a roster names a service or doctor that is not yours, or newly adds an inactive doctor. |
| 403 | forbidden | Clinic Scheduling is not enabled for the workspace (NuTalk turns it on per workspace). |
| 403 | forbidden | Changes act as the member who created the key: their role can't make this change in the dashboard, they are no longer in the workspace, or the key is a reseller key. |
| 503 | internal_error | A setting needs a release that is not deployed yet: retry later. |
Plus the errors every request can return (401, 403, 429, 500): Errors.