# Northlake Dental Studio — Voice Agent API

REST API the YouSpeak voice agent uses to answer callers, verify patients and make
real bookings against the same calendar the website shows. Base URL: the deployed
site origin (locally `http://localhost:4820`). All bodies are JSON. No auth in the
demo; put a bearer token in front of `/api/*` for production.

## Knowledge base (load once into the agent's context)

`GET /api/kb`
Returns everything the agent should know: practice info, opening hours, both
dentists with weekly schedules, all 28 services with printed prices and durations,
the FAQ, and `bookingRules` (45-min slot grid, lunch 12:30–14:00, emergency holds
at 08:00 & 16:30 reserved for urgent visits, 60-min same-day lead time, free
cancellation up to 24 h ahead).

## Tools to give the agent

### 1. check_availability
`GET /api/availability?service={serviceId}&dentist={dentistId}&date=YYYY-MM-DD`
→ `{ status: "off"|"past"|"open"|"full", times: ["08:45", ...], times12: ["8:45 AM", ...] }`

For a week overview (e.g. "when's the next free cleaning?"):
`GET /api/availability/week?service={serviceId}&dentist={dentistId}&start=YYYY-MM-DD`
→ `{ days: [{ date, weekday, day, status, freeCount }, ...] }` (7 days)

Service ids and which dentist can perform each are in the KB (`services[].dentist`
is `"any"` or a dentist id). Dentist ids: `raman`, `ellery`.

### 2. verify_patient
`GET /api/patients/verify?phone={phone}`
→ `{ found: false }` or `{ found: true, name, email, upcoming: [appointment...] }`

Call this early with the caller's phone number: greet returning patients by name
and read back their upcoming visits before booking anything new.

### 3. book_appointment
`POST /api/appointments`
```json
{
  "service": "hygiene-cleaning",
  "dentist": "ellery",
  "date": "2026-08-20",
  "time": "17:15",
  "patient": { "name": "Jane Doe", "phone": "+15125550137", "email": "optional" },
  "notes": "optional — mention nerves, pain location, etc.",
  "source": "voice-agent"
}
```
→ `201 { appointment: { code: "NDS-7K2M", ... } }` — read the code back to the
caller; it is how they manage the booking.
→ `422 { error: "..." }` — slot taken, wrong dentist for the service, bad phone.
Re-check availability and offer alternatives.

### 4. lookup_appointment
`GET /api/appointments/{code}` → `{ appointment }` or `404`.

### 5. cancel_appointment
`POST /api/appointments/{code}/cancel` → frees the slot.

### 6. reschedule_appointment
`POST /api/appointments/{code}/reschedule` with `{ "date": "...", "time": "...", "dentist": "optional" }`.

## Conversation rules baked into the data

- Always quote the printed price and duration when proposing a slot
  ("A hygiene cleaning is $120 and takes 45 minutes").
- Emergencies: offer today's 08:00 or 16:30 hold with the $135 emergency visit;
  only `urgent`-category services may take those slots.
- The $89 new-patient exam fee is credited toward same-day treatment.
- Crowns, implants, surgical extractions and Invisalign are quoted as ranges;
  final quote after imaging.
- Cancellations are free up to 24 h ahead; inside 24 h a $50 fee applies (waived
  once a year and for genuine emergencies).

## Website embed

The page exposes an empty `#voice-agent-embed` element inside the assistant
section and shows sample dialogue until the real widget is mounted. Drop the
YouSpeak embed snippet there (see `public/index.html`, "PHONE & WEB ASSISTANT").
