> ## Documentation Index
> Fetch the complete documentation index at: https://docs.voxhealth.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration

> Every attribute and programmatic option.

Configuration is split in two. **Script attributes** control the shell: how the widget looks and where it sits on the page. **Practice settings**, held server-side and fetched at load, control what it offers.

## Script attributes

| Attribute            | Required | Description                                                                                 |
| -------------------- | :------: | ------------------------------------------------------------------------------------------- |
| `data-token`         |    Yes   | The public token generated in **Settings → Scheduling Widget**.                             |
| `data-api-url`       |    Yes   | The `scheduling-widget` endpoint for the practice's VoxHealth backend.                      |
| `data-title`         |    No    | Panel heading. Defaults to a generic booking heading in the active language.                |
| `data-subtitle`      |    No    | Line under the heading.                                                                     |
| `data-primary-color` |    No    | Accent color, any CSS color.                                                                |
| `data-position`      |    No    | `bottom-right` (default), `bottom-left`, `top-right`, `top-left`.                           |
| `data-lang`          |    No    | BCP-47 tag. Unset follows the browser. See [Localization](/developers/widget/localization). |

Auto-init runs on load. With `data-token` or `data-api-url` missing, it exits without rendering.

## Programmatic use

The bundle exposes a `run(config)` function for hosts that need more than the attributes give: an inline mount, a location callback, or an origin the host is still resolving.

```js theme={null}
run({
  token: 'YOUR_PUBLIC_TOKEN',
  apiUrl: 'https://YOUR_SUPABASE_HOST/functions/v1/scheduling-widget',
  title: 'Book an appointment',
  primaryColor: '#D93C00',
  container: '#booking',
  locale: 'es',
  onLocationChange: (locationId, source) => {
    // source: 'patient' | 'suggested' | 'pinned'
  },
  originHint: resolveVisitorLocation(),
})
```

| Option              | Type                           | Description                                                                                                                                                                                                                                                                                                  |
| ------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `token`             | `string`                       | Required.                                                                                                                                                                                                                                                                                                    |
| `apiUrl`            | `string`                       | Required.                                                                                                                                                                                                                                                                                                    |
| `title`, `subtitle` | `string`                       | As the attributes.                                                                                                                                                                                                                                                                                           |
| `primaryColor`      | `string`                       | As the attribute.                                                                                                                                                                                                                                                                                            |
| `position`          | `string`                       | Ignored when `container` is set.                                                                                                                                                                                                                                                                             |
| `container`         | `HTMLElement \| string`        | Render the flow **inline** inside this element instead of as a floating bubble. This is what the hosted booking page uses.                                                                                                                                                                                   |
| `locale`            | `string`                       | BCP-47 tag.                                                                                                                                                                                                                                                                                                  |
| `onLocationChange`  | `(locationId, source) => void` | Fires whenever the office being booked at changes. `source` says who decided: `patient`, `suggested` (an origin the host supplied), or `pinned` (the practice has one office). A host that ignores it loses nothing.                                                                                         |
| `originHint`        | `Promise<GeoPoint \| null>`    | An approximate visitor origin the host is still looking up. The widget joins this wait to its own config load, bounded by a short timeout, so it never picks an office and immediately swaps it, which reads to a patient as the page reloading itself. Resolve to `null` when the visitor cannot be placed. |

## Practice settings

These come from the server at load, set by an admin in **Settings → Scheduling Widget**. You cannot override them from the page. A website should not be able to widen what a practice offers.

| Setting                                   | Effect                                                                             |
| ----------------------------------------- | ---------------------------------------------------------------------------------- |
| Location                                  | Pin the widget to one office, or leave it to offer all of them.                    |
| Published visit reasons                   | Which appointment types appear in the reason picker.                               |
| Default duration                          | Used when a reason does not carry its own.                                         |
| New-patient appointment type and duration | What a new patient is booked into.                                                 |
| Allow new patients                        | Whether new patients can book at all, or only returning ones.                      |
| Collect insurance                         | Whether the insurance step is shown.                                               |
| Title and subtitle, per language          | Overrides the generic heading in each language you set.                            |
| Booking slug                              | The practice's [hosted booking page](/developers/hosted-booking-page) path.        |
| Allowed domains                           | The origins the token will answer on. See [Security](/developers/widget/security). |

## Session behaviour

An in-progress booking is kept in `sessionStorage` only, so an accidental reload mid-flow resumes. It dies with the tab, is bounded by a 30-minute server-side session, and is re-validated on booking.

Nothing the patient typed is retained afterwards. Booking links get opened on shared phones, family tablets, and waiting-room devices, and a form pre-filled with the previous person's name and number is a worse trade than making a returning patient type theirs again.
