Skip to main content

Creating Appointments

Create a new appointment against a configured calendar window using POST /v1/appointments. The request is validated against availability, slot capacity, and duplicate rules before the booking is confirmed.


Before You Begin

Your API key requires the appointments:write scope. Make sure the following are configured in your HuskyVoice dashboard before calling this endpoint:

  • At least one Service (appointment type)
  • At least one Branch with Calendar Windows set up for the relevant days and sessions
  • The correct timezone set in your org configuration (see Appointments Overview)

Creating an Appointment

  • Endpoint: POST https://api.huskyvoice.ai/v1/appointments
  • Required scope: appointments:write
curl -s -X POST https://api.huskyvoice.ai/v1/appointments \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"appointment_type": "General Checkup",
"appointment_date": "2026-06-15T09:30:00.000Z",
"patient_name": "Aadhi",
"parent_phone": "+919840XXXXXX",
"session": "Morning",
"branch_id": "branch_uuid_here"
}'

Response — 201 Created

{
"success": true,
"appointment_id": "appt_a1b2c3d4e5",
"token": null,
"data": {
"appointment_id": "appt_a1b2c3d4e5",
"appointment_type": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"branch_id": "branch_uuid_here",
"date": "2026-06-15",
"session": "Morning",
"batch": "MA",
"token": null,
"patient_name": "Aadhi",
"parent_phone": "+919840XXXXXX",
"assigned_doctor": null,
"status": "confirmed",
"external_reference_id": null,
"created_at": "2026-05-26T10:00:00.000Z",
"updated_at": "2026-05-26T10:00:00.000Z"
}
}

Request Fields

FieldRequiredDescription
appointment_typeYesService UUID or human-readable name (e.g. "General Checkup") — resolved case-insensitively
appointment_dateYesISO 8601 UTC datetime (e.g. "2026-06-15T09:30:00.000Z") — time component required
patient_nameYesPatient's full name
parent_phoneYesPatient's phone number
branch_idConditionalRequired when your organization has more than one branch; auto-resolved if only one exists. Find your branch IDs via GET /v1/appointment-slots/availability or from Dashboard → Settings → Branches
sessionNo"Morning", "Afternoon", or "Evening" — used to match the correct calendar window
batchNoSpecific batch label (e.g. "MA") — auto-populated from the matched calendar window if omitted
assigned_doctorNoName or identifier of the assigned doctor
external_reference_idNoYour own unique identifier for idempotency (see below)
About appointment_date

Pass a full UTC datetime string, not a date-only value. The booking engine converts the time to the org's local timezone (read from GET /v1/appointment-config) and checks it against configured calendar windows. A date-only value like "2026-06-15" resolves to UTC midnight, which will likely fall outside any window.

About appointment_type

You can pass either the service UUID ("f47ac10b-58cc-4372-a567-0e02b2c3d479") or the human-readable name ("General Checkup"). Names are resolved case-insensitively. Use GET /v1/services to list all configured types.


Idempotency

Pass external_reference_id to prevent duplicate bookings on retries. If an active (non-cancelled) appointment already exists for that reference ID within your organization, the API returns the existing record with "idempotent": true and HTTP 200 instead of 201.

{
"success": true,
"idempotent": true,
"appointment_id": "appt_a1b2c3d4e5",
"token": null,
"data": { ... }
}

Validation Rules

The API enforces these rules before confirming a booking:

  1. Future timeappointment_date must be in the future.
  2. Slot availabilityappointment_date must fall within an active, open calendar window for the specified branch and session.
  3. Capacity — The window must have remaining capacity. Each service type is counted independently.
  4. No duplicate — Only one active booking per patient phone number per appointment type per date is allowed.
  5. Valid typeappointment_type must resolve to a configured service.

Error Codes

StatusCodeCause
400VALIDATION_ERRORMissing required field
400PAST_APPOINTMENTappointment_date is in the past
409SLOT_FULLWindow has no remaining capacity
409SLOT_INACTIVEWindow is closed (status: "CLOSED")
409DUPLICATE_BOOKINGA future non-cancelled appointment already exists for this patient's phone number. The response includes existing_appointment_id. Only applies when duplicate prevention is enabled in your org settings
422INVALID_APPOINTMENT_TYPEappointment_type does not match any configured service
422OUTSIDE_AVAILABILITYappointment_date does not fall within any configured calendar window
404NOT_FOUNDAppointment not found (GET / PATCH only)
403INSUFFICIENT_SCOPEAPI key does not have the required scope