---
title: Compute available slots for a service (no auth)
description: The unauthenticated availability lookup for the public booker.
api_method: GET
api_path: "/v1/public/availability"
canonical_url: https://wiblo.app/docs/developers/api/public/get-public-availability
last_updated: 2026-07-28T18:08:25+02:00
md_url: https://wiblo.app/docs/developers/api/public/get-public-availability.md
---

# Compute available slots for a service (no auth)

`GET /v1/public/availability`

The unauthenticated availability lookup for the public booker. Runs the same pipeline as `GET /v1/availability` with the workspace resolved from the service itself; hidden, retired, and unknown services collapse onto the same 404 (nothing to enumerate). `member_id` narrows to one assigned host. No credentials of any kind; aggressively rate-limited per IP at 60/60s and wrapped by Vercel BotID.

## Query parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `service_id` | `string` | Yes | Id of the service to compute availability for. |
| `member_id` | `string` | No | Restricts the computation to this assigned host; omitted computes across every assigned host. |
| `date_from` | `string` | Yes | First date of the window (`YYYY-MM-DD`), interpreted in `timezone`. |
| `date_to` | `string` | No | Last date of the window (`YYYY-MM-DD`), inclusive; omitted means a single-day lookup of `date_from`. Must be on or after `date_from`, and the inclusive range may span at most 366 dates. |
| `timezone` | `string` | No | IANA time zone the dates are interpreted in and slot times are generated for, e.g. `Europe/London`. Defaults to `"UTC"`. |

## Request

**curl**

```bash
curl "https://api.wiblo.app/v1/public/availability?service_id=3f8a2b9c-51d4-4e0b-9c6a-7d2e8f1a4b5c&date_from=2026-08-17&timezone=Europe/London"
```

**TypeScript**

```ts
import { createSdk, getPublicAvailability } from "@workspace/sdk"

const sdk = createSdk({ baseUrl: "https://api.wiblo.app" })

const { data, error } = await getPublicAvailability({
  client: sdk,
  query: { service_id: "3f8a2b9c-51d4-4e0b-9c6a-7d2e8f1a4b5c", date_from: "2026-08-17", timezone: "Europe/London" },
})
```

## Example response

```json
{
  "slots": [
    {
      "time": "2026-08-17T08:00:00.000Z",
      "available": true
    },
    {
      "time": "2026-08-17T08:30:00.000Z",
      "available": true
    },
    {
      "time": "2026-08-17T09:00:00.000Z",
      "available": true
    },
    {
      "time": "2026-08-17T09:30:00.000Z",
      "available": true
    },
    {
      "time": "2026-08-17T10:00:00.000Z",
      "available": true
    },
    {
      "time": "2026-08-17T10:30:00.000Z",
      "available": true
    },
    {
      "time": "2026-08-17T11:00:00.000Z",
      "available": true
    },
    {
      "time": "2026-08-17T13:00:00.000Z",
      "available": true
    },
    {
      "time": "2026-08-17T13:30:00.000Z",
      "available": true
    },
    {
      "time": "2026-08-17T14:00:00.000Z",
      "available": true
    },
    {
      "time": "2026-08-17T14:30:00.000Z",
      "available": true
    },
    {
      "time": "2026-08-17T15:00:00.000Z",
      "available": true
    },
    {
      "time": "2026-08-17T15:30:00.000Z",
      "available": true
    }
  ],
  "metadata": {
    "service_id": "3f8a2b9c-51d4-4e0b-9c6a-7d2e8f1a4b5c",
    "date_from": "2026-08-17",
    "date_to": "2026-08-17",
    "timezone": "Europe/London",
    "event_length": 30,
    "slot_interval": 30
  }
}
```

## Responses

**`200`** — The computed slots plus echo metadata. Returns `AvailabilityResponse`.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `slots` | `array<AvailabilitySlot>` | Yes | The bookable slots in time order; busy slots are not listed. |
| `metadata` | `object` | Yes | Echo of the query plus the resolved slot parameters. |
| `metadata.service_id` | `string` | Yes | The service the slots were computed for, echoed from the query. |
| `metadata.member_id` | `string` | No | The host filter applied; omitted when the query named no `member_id`. |
| `metadata.date_from` | `string` | Yes | First date of the computed window (`YYYY-MM-DD`), echoed from the query. |
| `metadata.date_to` | `string` | Yes | Last date of the computed window (`YYYY-MM-DD`); echoes `date_from` on single-day lookups. |
| `metadata.timezone` | `string` | Yes | The IANA time zone slots were generated in, echoed from the query. |
| `metadata.event_length` | `integer` | Yes | Appointment length in minutes, from the service. |
| `metadata.slot_interval` | `integer` | Yes | Minutes between offered start times — the service's `slot_interval`, falling back to its length. |

**`400`** — A query parameter failed validation (`VALIDATION_FAILED`). Returns `ApiErrorEnvelope`.

**`404`** — The service collapsed (`SERVICE_NOT_FOUND` — hidden, retired, and unknown ids look identical) or `member_id` is not an assigned host (`HOST_NOT_FOUND`). Returns `ApiErrorEnvelope`.

**`422`** — The service has no assigned hosts (`SERVICE_HAS_NO_HOSTS`). Returns `ApiErrorEnvelope`.

**`429`** — Rate limit exceeded. The body's `error.code` is `RATE_LIMITED` and `error.details.retry_after` is the same number of seconds as the `Retry-After` header. Returns `ApiErrorEnvelope`.

### The AvailabilitySlot object

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `time` | `string` | Yes | Slot start as a UTC ISO datetime. |
| `available` | `boolean` | Yes | Whether the slot can be booked. Busy slots are absent from the list entirely, so non-seated slots always carry `true`; a seated slot reports `false` when no seats remain. |
| `available_seats` | `integer \| null` | No | Seats still open on the slot; omitted when the service is not seated. |
| `total_seats` | `integer \| null` | No | The service's seat capacity per slot; omitted when the service is not seated. |
