# Get the booking catalog

`GET https://app.pozyskajpacjenta.pl/api/v1/booking/catalog` · operationId `getBookingCatalog` · since 1.3.0 · tag Booking

Active booking services and specialists, with links to the published treatments and team profiles. The ids are the `service` and `resource` parameters of /booking/slots and the `serviceId` and `resourceId` of /booking/appointments. A treatment points at its service with `bookingServiceId`, a team profile at its specialist with `bookingResourceId`. Responses are private to the key: `Cache-Control: private, max-age=60`, so cache them on your side for up to a minute.

## Request

Authorization: `Bearer <the clinic's key>`.

### cURL

```bash
curl "https://app.pozyskajpacjenta.pl/api/v1/booking/catalog" \
  -H "Authorization: Bearer $PP_API_KEY"
```

### TypeScript

```ts
import { PozyskajPacjentaClient } from "@pozyskajpacjenta/sdk";

const client = new PozyskajPacjentaClient({
  apiKey: process.env.PP_API_KEY ?? "",
  baseUrl: "https://app.pozyskajpacjenta.pl",
});

const { services, resources } = await client.getBookingCatalog();
```

### PHP

```php
<?php
$response = wp_remote_get(
    'https://app.pozyskajpacjenta.pl/api/v1/booking/catalog',
    array(
        'headers' => array( 'Authorization' => 'Bearer ' . getenv( 'PP_API_KEY' ) ),
        'timeout' => 10,
    )
);
if ( is_wp_error( $response ) ) {
    error_log( $response->get_error_message() );
    return;
}
$status = wp_remote_retrieve_response_code( $response );
$data   = json_decode( wp_remote_retrieve_body( $response ), true );
```

## Response

### 200: Services and specialists.

- `services` (`BookingCatalogService[]`, required): Active booking services.
  - `id` (`string`, required): Service id: the `service` parameter of /booking/slots.
  - `name` (`string`, required): Name of the service.
  - `durationMin` (`integer`, required): Length of the visit in minutes.
  - `priceLabel` (`string | null`, required): Price of the visit for display: the booking service's own price label (e.g. a consultation at 300 zł), else the `priceFromLabel` of the published treatment linked to it (as in /services/{slug}); null when there is neither.
  - `resourceIds` (`string[]`, required): Active specialists who perform the service (ids from `resources`). An empty list means nobody can be booked for it. Free slots always come from /booking/slots.
  - `serviceSlug` (`string | null`, required): Slug of the published treatment linked to the service (GET /services/{slug}); null when no published treatment points at it.
  - `nfz` (`boolean`, since 1.8.0): true: an NFZ (public health fund) service. Show it for information with a note that booking is by phone and the clinic's phone; it cannot be booked online (/booking/slots and /booking/appointments answer 400 nfz_phone_only). Absent on older servers, which means false.
- `resources` (`BookingCatalogResource[]`, required): Active specialists.
  - `id` (`string`, required): Specialist id: the `resource` parameter of /booking/slots.
  - `name` (`string`, required): Full name.
  - `title` (`string | null`, required): Professional title, e.g. lek. dent.; null when none.
  - `doctorSlug` (`string | null`, required): Slug of the published team profile (GET /doctors/{slug}); null when no published profile points at the specialist.

Example (Bookable services (trimmed) and specialists, one of them NFZ):

```json
{
  "services": [
    {
      "id": "bsvc_konsultacja",
      "name": "Konsultacja stomatologiczna",
      "durationMin": 30,
      "priceLabel": "200 zł",
      "resourceIds": [
        "bres_anna",
        "bres_piotr",
        "bres_maria"
      ],
      "serviceSlug": "konsultacja-stomatologiczna",
      "nfz": false
    },
    {
      "id": "bsvc_higienizacja",
      "name": "Higienizacja (skaling + piaskowanie + fluoryzacja)",
      "durationMin": 60,
      "priceLabel": "290 zł",
      "resourceIds": [
        "bres_maria"
      ],
      "serviceSlug": "higienizacja",
      "nfz": false
    },
    {
      "id": "bsvc_nfz",
      "name": "Leczenie zachowawcze (NFZ)",
      "durationMin": 30,
      "priceLabel": null,
      "resourceIds": [
        "bres_piotr"
      ],
      "serviceSlug": null,
      "nfz": true
    }
  ],
  "resources": [
    {
      "id": "bres_anna",
      "name": "Anna Wzorcowa",
      "title": "dr n. med.",
      "doctorSlug": "anna-wzorcowa"
    },
    {
      "id": "bres_piotr",
      "name": "Piotr Nowicki",
      "title": "lek. dent.",
      "doctorSlug": "piotr-nowicki"
    },
    {
      "id": "bres_maria",
      "name": "Maria Zielińska",
      "title": "lek. dent. spec. stomatologii estetycznej",
      "doctorSlug": "maria-zielinska"
    }
  ]
}
```

## Errors

| Status | code | When |
| --- | --- | --- |
| 401 |  | No Authorization header |
| 401 |  | Unknown or rotated key |
| 429 |  | Over 120 requests in this minute |

401 (No Authorization header):

```json
{
  "error": "missing Authorization: Bearer <klucz z panelu Ustawienia>"
}
```

401 (Unknown or rotated key):

```json
{
  "error": "invalid key"
}
```

429 (Over 120 requests in this minute):

```json
{
  "error": "przekroczono limit 120 zapytań/min"
}
```

## Rate limit

- 120 requests per minute per key, shared by every endpoint.

## SDK method

`client.getBookingCatalog(): Promise<BookingCatalog>`
