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

# Get open start times

> Free start times for one service over a window of up to 62 days.

Returns bookable start times as UTC instants. Minimum notice, booking horizon,
appointment duration, trailing buffers, and DST transitions are already applied, so every
instant returned was bookable at the moment it was computed.

The response never contains booking rows, customer data, or explicit busy ranges. `slots`
is the entire payload by design — a busy-range response would leak the tenant's calendar
to anyone with a slug.

<Warning>
  **Availability is advisory; the submit is authoritative.** Another customer can take a
  slot between this read and your write, which comes back as `409 booking_conflict`.

  Responses are cached 5s in the browser and 15s in the shared cache, so a plain refetch
  straight after a conflict can hand you back the slot you just lost. Append a
  cache-buster (`&_=${Date.now()}`) when you refetch after a `409`.
</Warning>

## Grouping into local days is your job

`slots` are instants; `timezone` is the tenant's IANA zone. Rendering "Tuesday" correctly
— and surviving DST — means bucketing in that zone, not the visitor's:

```js theme={null}
function groupSlotsByDate(slots, timeZone) {
  const byDate = new Map();
  for (const slot of slots) {
    // en-CA renders YYYY-MM-DD.
    const key = new Intl.DateTimeFormat("en-CA", {
      timeZone,
      year: "numeric",
      month: "2-digit",
      day: "2-digit",
    }).format(new Date(slot));
    byDate.set(key, [...(byDate.get(key) ?? []), slot]);
  }
  return byDate;
}
```

## Window rules

`from` is inclusive, `to` is exclusive, both must be ISO-8601 **with an offset**, and the
window may span at most 62 days. A wider window is `400 window_too_large` — page through
it instead. The hosted page requests 60 days, comfortably inside the cap.


## OpenAPI

````yaml openapi.json GET /api/public/tenants/{slug}/availability
openapi: 3.1.0
info:
  title: DPC Bookings API
  version: 1.0.0
  description: >-
    Public, unauthenticated endpoints for taking a booking from a custom
    website. Read services, read open times, submit one booking. Booking
    management lives in the DPC dashboard.
servers:
  - url: https://deepcontext.app
security: []
paths:
  /api/public/tenants/{slug}/availability:
    get:
      summary: Get open start times
      description: >-
        Free start times only — never bookings, customer data, or busy ranges.
        Minimum notice, booking horizon, duration, trailing buffers, and DST are
        already applied.


        Availability is advisory; the submit is authoritative. Another customer
        can take a slot between this read and your write, which is a `409
        booking_conflict`. Responses are cached 15s in the shared cache, so add
        a cache-buster when you refetch after a conflict.
      operationId: getBookingAvailability
      parameters:
        - name: slug
          in: path
          required: true
          description: >-
            The tenant's public booking slug. Issued by DPC; there is no
            discovery endpoint.
          schema:
            type: string
        - name: service_id
          in: query
          required: true
          description: Duration and buffers are taken from this service.
          schema:
            type: string
            format: uuid
            pattern: >-
              ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
        - name: from
          in: query
          required: true
          description: Inclusive window start. ISO-8601 with an offset.
          schema:
            type: string
            format: date-time
            pattern: >-
              ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
        - name: to
          in: query
          required: true
          description: >-
            Exclusive window end. ISO-8601 with an offset. At most 62 days after
            `from`.
          schema:
            type: string
            format: date-time
            pattern: >-
              ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
      responses:
        '200':
          description: Open start times as UTC instants
          content:
            application/json:
              schema:
                type: object
                properties:
                  service_id:
                    type: string
                    format: uuid
                    pattern: >-
                      ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
                  from:
                    type: string
                  to:
                    type: string
                  timezone:
                    type: string
                  slots:
                    type: array
                    items:
                      type: string
                required:
                  - service_id
                  - from
                  - to
                  - timezone
                  - slots
                additionalProperties: false
        '400':
          description: Invalid query, window too large, or unknown/inactive service
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    additionalProperties: false
                required:
                  - error
                additionalProperties: false
        '404':
          description: Unknown slug, or the tenant has booking disabled
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                    required:
                      - code
                      - message
                    additionalProperties: false
                required:
                  - error
                additionalProperties: false

````