Specialist API Endpoints
All specialist endpoints are org-scoped and require Clerk authentication. The authenticated user's organization is resolved from the Clerk session.
Authentication & Authorization
| Header | Value |
|---|---|
Authorization | Bearer <clerk_session_token> |
Permissions:
- SELECT (list, get): All authenticated users in the organization
- CREATE, UPDATE, DELETE: Admin role only
Base URL
All endpoints use the /v1/ prefix.
List Specialists
GET /v1/specialists
List specialists for the authenticated organization. Automatically filtered by RLS.
Query Parameters:
?page=1- Page number (default: 1)?page_size=25- Results per page (max: 100, default: 25)?sort=-created_at- Sort order (minus prefix = descending)?include=specialties,user- Include related resources?deleted=false- Filter by soft delete status (default: false, only active specialists)
Response: 200
{
"data": [
{
"id": 2,
"organization_id": 1,
"user_id": 44,
"name": "Dr. Jane Smith",
"title": "Cardiologist",
"description": "Board-certified cardiologist with 15 years of experience...",
"slug": "dr-jane-smith",
"signature_url": "https://s3.amazonaws.com/restartix/signatures/smith-sig.png",
"avatar_url": "https://s3.amazonaws.com/restartix/avatars/smith.jpg",
"scheduling_timezone": "America/New_York",
"scheduling_active": true,
"minicrm_name": "DrSmith",
"deleted_at": null,
"created_at": "2025-01-10T08:00:00Z",
"updated_at": "2025-01-15T10:30:00Z",
"specialties": [
{"id": 1, "title": "Cardiology", "slug": "cardiology"},
{"id": 3, "title": "Internal Medicine", "slug": "internal-medicine"}
]
}
],
"meta": {
"page": 1,
"page_size": 25,
"total": 5,
"total_pages": 1
}
}Create Specialist
POST /v1/specialists
Create a new specialist. Admin only.
Request:
{
"name": "Dr. Jane Smith",
"title": "Cardiologist",
"description": "Board-certified cardiologist with 15 years of experience in cardiovascular health.",
"slug": "dr-jane-smith",
"user_id": 44,
"specialty_ids": [1, 3],
"scheduling_timezone": "America/New_York",
"scheduling_active": true,
"minicrm_name": "DrSmith"
}Validation:
name(required, 1-200 chars)slug(required, unique per organization, lowercase alphanumeric + hyphens)user_id(optional, must reference existing user in the same organization)specialty_ids(optional array, each ID must reference existing specialty in the same org)scheduling_timezone(optional, must be valid IANA timezone)scheduling_active(optional, default: true)
Response: 201
{
"data": {
"id": 2,
"organization_id": 1,
"user_id": 44,
"name": "Dr. Jane Smith",
"title": "Cardiologist",
"description": "Board-certified cardiologist with 15 years of experience in cardiovascular health.",
"slug": "dr-jane-smith",
"signature_url": null,
"avatar_url": null,
"scheduling_timezone": "America/New_York",
"scheduling_active": true,
"minicrm_name": "DrSmith",
"deleted_at": null,
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
}Errors:
400 name_required- Name is required400 slug_required- Slug is required400 invalid_slug- Slug must be lowercase alphanumeric with hyphens409 slug_exists- A specialist with this slug already exists in this organization404 user_not_found- User ID references a non-existent user404 specialty_not_found- One or more specialty IDs are invalid400 invalid_timezone- Timezone is not a valid IANA timezone403 forbidden- User does not have admin role
Get Specialist
GET /v1/specialists/{id}
Get a single specialist by ID with all details.
Query Parameters:
?include=specialties,user,weekly_hours,overrides- Include related resources
Response: 200
{
"data": {
"id": 2,
"organization_id": 1,
"user_id": 44,
"name": "Dr. Jane Smith",
"title": "Cardiologist",
"description": "Board-certified cardiologist with 15 years of experience...",
"slug": "dr-jane-smith",
"signature_url": "https://s3.amazonaws.com/restartix/signatures/smith-sig.png",
"avatar_url": "https://s3.amazonaws.com/restartix/avatars/smith.jpg",
"scheduling_timezone": "America/New_York",
"scheduling_active": true,
"minicrm_name": "DrSmith",
"deleted_at": null,
"created_at": "2025-01-10T08:00:00Z",
"updated_at": "2025-01-15T10:30:00Z",
"specialties": [
{"id": 1, "title": "Cardiology", "slug": "cardiology"},
{"id": 3, "title": "Internal Medicine", "slug": "internal-medicine"}
],
"user": {
"id": 44,
"email": "[email protected]",
"username": "[email protected]",
"role": "specialist"
}
}
}Errors:
404 specialist_not_found- Specialist doesn't exist or not accessible in current organization
Update Specialist
PUT /v1/specialists/{id}
Update a specialist. Admin only.
Request:
{
"name": "Dr. Jane Marie Smith",
"title": "Senior Cardiologist",
"description": "Updated biography...",
"specialty_ids": [1, 3, 5],
"scheduling_timezone": "Europe/Bucharest",
"scheduling_active": false
}Validation:
- All fields are optional
- Same validation rules as
POSTfor fields that are provided - Cannot change
id,organization_id,created_at scheduling_timezonechange is blocked if appointment-type-specific overrides exist for this specialist
Field Protection:
- Patients and specialists can view specialists but cannot modify
- Only admins can update specialist records
Response: 200
{
"data": {
"id": 2,
"organization_id": 1,
"user_id": 44,
"name": "Dr. Jane Marie Smith",
"title": "Senior Cardiologist",
"description": "Updated biography...",
"slug": "dr-jane-smith",
"signature_url": "https://s3.amazonaws.com/restartix/signatures/smith-sig.png",
"avatar_url": "https://s3.amazonaws.com/restartix/avatars/smith.jpg",
"scheduling_timezone": "Europe/Bucharest",
"scheduling_active": false,
"minicrm_name": "DrSmith",
"deleted_at": null,
"created_at": "2025-01-10T08:00:00Z",
"updated_at": "2025-01-15T11:45:00Z"
}
}Errors:
404 specialist_not_found- Specialist doesn't exist or not accessible403 forbidden- User does not have admin role409 slug_exists- Another specialist already has this slug in the organization400 timezone_locked- Cannot change timezone while appointment-type-specific overrides exist404 user_not_found- User ID references a non-existent user404 specialty_not_found- One or more specialty IDs are invalid
Delete Specialist
DELETE /v1/specialists/{id}
Soft-delete a specialist. Admin only. Sets deleted_at timestamp instead of removing the record (medical record integrity / HIPAA compliance).
Response: 200
{
"data": {
"id": 2,
"message": "Specialist soft-deleted successfully",
"deleted_at": "2025-01-15T12:00:00Z"
}
}Business Logic:
- Validate specialist exists and belongs to current organization
- Check user has admin role
- Set
deleted_at = NOW() - Historical appointments and clinical records remain intact
- Specialist no longer appears in active listings
- Can be filtered with
?deleted=trueto view soft-deleted records
Errors:
404 specialist_not_found- Specialist doesn't exist or not accessible403 forbidden- User does not have admin role409 already_deleted- Specialist is already soft-deleted
Integration Notes
Scheduling System Integration
For scheduling-related operations (weekly hours, overrides, availability), see:
- scheduling-config.md - Scheduling configuration details
- ../scheduling/ - Full scheduling feature documentation
Related Endpoints
For specialty management, see the Specialty endpoints:
GET /v1/specialties- List all specialtiesPOST /v1/specialties- Create specialtyGET /v1/specialties/{id}- Get specialty with specialistsPUT /v1/specialties/{id}- Update specialtyDELETE /v1/specialties/{id}- Delete specialty