---
title: "Бронювання"
description: "Створюйте запити на бронювання та керуйте бронюваннями за допомогою SDK Requiply."
canonical_url: "https://requiply.com/docs/uk/developers/typescript-sdk/bookings"
---
# Бронювання

> Створюйте запити на бронювання та керуйте бронюваннями за допомогою SDK Requiply.

## `bookings.create()`

```ts
bookings.create(
  input: BookingCreateInput,
  options?: RequiplyRequestOptions,
): Promise<BookingCreateResponse>
```

Обовʼязкові: `startDate`, `endDate`, `items` (до 100), `deliveryType` (`pickup` або `delivery`). Звичайне бронювання також потребує `paymentType`, а запит на бронювання (`asRequest: true`) не потребує. Необовʼязкові: `bundles`, `services`, `clientId` або дані клієнта в `client`, `allowOutsideWorkingHours`, `adjustment`, `saleLines`.

`paymentType` приймає `payOnPickup`, `stripe`, `wayforpay`, `monobank` або `liqpay`. Онлайн-спосіб оплати потребує активної інтеграції з цим провайдером.

```ts
const result = await requiply.bookings.create({
  startDate: '2026-07-01T10:00:00',
  endDate: '2026-07-03T18:00:00',
  items: [{ groupId: cameraKitId, quantity: 1 }],
  deliveryType: 'pickup',
  asRequest: true,
  client: { name: 'Alex', email: 'customer@example.com' },
});
```

`client` потребує `email` або `phone` і може додатково містити `name` і `lastName`. Його зіставляють із наявним клієнтом за email, потім за телефоном, а якщо збігу немає, створюють нового. Серверна інтеграція, яка вже знає клієнта, може натомість передати `clientId`. Запит на бронювання не утримує інвентар і не створює оплати, доки його не підтвердять співробітники.

<warning>

Публічні ключі можуть використовувати цей метод лише для запитів на бронювання з `asRequest: true`. Для створення звичайних бронювань використовуйте секретний ключ на довіреному сервері.

</warning>

Початковий статус бронювання береться з [налаштувань створення бронювання](https://requiply.com/docs/uk/guides/settings/bookings/booking-creation#%D0%B2%D0%B8%D0%B1%D1%96%D1%80-%D0%BF%D0%BE%D1%87%D0%B0%D1%82%D0%BA%D0%BE%D0%B2%D0%B8%D1%85-%D1%81%D1%82%D0%B0%D1%82%D1%83%D1%81%D1%96%D0%B2) організації: **Статус запитів на бронювання**, коли `asRequest` дорівнює `true`, інакше **Типовий статус нових бронювань**. Статуси належать кожній організації та можуть бути перейменовані, тож не вписуйте у свою інтеграцію жорстко назву статусу на кшталт `Request` чи `New`.

Дата й час без зсуву, як-от `2026-07-01T10:00:00`, читаються як місцевий час у часовому поясі організації з урахуванням переходу на літній час. Значення із `Z` або зсувом використовується як є. Дата без часу, як-от `2026-07-01`, читається як північ і зазвичай не проходить перевірку робочих годин, тож завжди надсилайте час.

`startDate` і `endDate` мають припадати на робочий день у межах робочих годин організації, які оцінюються в часовому поясі організації. Інакше відповідь містить `success: false`, `reason: "working_hours"`, а також повідомлення з дозволеним проміжком. Секретний ключ може передати `allowOutsideWorkingHours: true`, щоб пропустити цю перевірку для видачі чи повернення, які бізнес погодився провести поза графіком. Публічні ключі не можуть використовувати цей прапорець і отримують `403`.

### Коригування вартості бронювання

REST-ендпоінт `POST /api/public/v1/bookings/create` також приймає одне [коригування вартості бронювання](https://requiply.com/docs/uk/guides/bookings/changing/cost-adjustment), тобто разову знижку чи доплату для цього бронювання:

```json
"adjustment": { "type": "percent", "value": -10, "reason": "Returning client" }
```

`type` може бути `units` (оплачувані дні чи місяці), `percent` (від −100 до 100) або `amount` (у валюті організації). Значення має знак: відʼємне означає знижку, додатне означає доплату. Надсилати його може лише **секретний ключ**, група дозволів ключа має мати **Коригування вартості та застави**, а тип має бути ввімкнено у [Функції](https://requiply.com/docs/uk/guides/settings/organization/features#%D1%83%D0%B2%D1%96%D0%BC%D0%BA%D0%BD%D1%83%D1%82%D0%B8-%D0%BA%D0%BE%D1%80%D0%B8%D0%B3%D1%83%D0%B2%D0%B0%D0%BD%D0%BD%D1%8F-%D0%B2%D0%B0%D1%80%D1%82%D0%BE%D1%81%D1%82%D1%96-%D1%82%D0%B0-%D0%B7%D0%B0%D1%81%D1%82%D0%B0%D0%B2%D0%B8) організації. Інакше відповідь буде `403` (наприклад, *adjustment requires a secret key* або *Booking adjustments are not enabled for this organization*) чи `400` для нульового значення без причини. Те саме поле працює в [`pricing.quote()`](https://requiply.com/docs/uk/developers/typescript-sdk/availability-and-pricing#pricingquote), тож спершу можна показати скориговану ціну.

### Комплекти

Починаючи з 0.2.1, `bundles: [{ bundleId, quantity }]` бронює цілі набори [комплекту](https://requiply.com/docs/uk/guides/inventory/bundles) з ідентифікаторами з [`bundles.list()`](https://requiply.com/docs/uk/developers/typescript-sdk/inventory-and-categories#bundleslist). Тоді `items` може бути порожнім. Товари комплекту записуються в бронювання як звичайні рядки товарів із застосованою знижкою за комплект, а знижка клієнта додається зверху. Якщо надіслати комплекти, коли в організації вимкнено функцію «Комплекти», відповідь буде `403`. Спершу розрахуйте ціну з тими самими `bundles` через [`pricing.quote()`](https://requiply.com/docs/uk/developers/typescript-sdk/availability-and-pricing#pricingquote), щоб показати `bundleDiscountAmount`.

### Товари на продаж

Коли функцію «Продажі» ввімкнено, `saleLines: [{ saleItemId, quantity }]` продає товари разом із бронюванням за каталожною ціною. Публічний ключ може додати їх до запиту на бронювання, лише поки організація [продає клієнтам](https://requiply.com/docs/uk/developers/typescript-sdk/sales#%D0%B7-%D0%BF%D1%83%D0%B1%D0%BB%D1%96%D1%87%D0%BD%D0%B8%D0%BC-%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BC), причому ніколи понад наявний залишок. Сума товарів додається до `totalCost`. Залишок зменшується під час створення бронювання і повертається, якщо бронювання скасують. Див. [Продажі та товари на продаж](https://requiply.com/docs/uk/developers/typescript-sdk/sales#%D1%82%D0%BE%D0%B2%D0%B0%D1%80%D0%B8-%D0%B2-%D0%B1%D1%80%D0%BE%D0%BD%D1%8E%D0%B2%D0%B0%D0%BD%D0%BD%D1%96).

Публічні запити на бронювання не можуть містити ідентифікаторів товарів суборенди від постачальників. Створення бронювання із секретним ключем може їх містити, коли організація ввімкнула суборенду. Кожен вибраний товар створює зафіксований рядок закупівлі замість призначення власної одиниці інвентарю.

### Обробка відповіді

`bookings.create()` повертає одну з двох форм, які розрізняють за `success`. Бронювання, яке організація не може прийняти, **не** викидає помилку: метод повертає `success: false`. TypeScript дозволяє читати `reservationId` лише після перевірки `success`.

```ts
if (result.success) {
  console.log('Booking', result.reservationOrgId, result.isRequest);
  if (result.paymentUrl) redirectTo(result.paymentUrl);
} else {
  console.log(result.message, result.reason);
}
```

<table>
<thead>
  <tr>
    <th>
      <code>
        success: true
      </code>
      
       (<code>
        BookingCreated
      </code>
      
      )
    </th>
    
    <th>
      <code>
        success: false
      </code>
      
       (<code>
        BookingRefused
      </code>
      
      )
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        reservationId
      </code>
      
      : внутрішній ідентифікатор для <code>
        bookings.get()
      </code>
      
      .
    </td>
    
    <td>
      <code>
        message
      </code>
      
      : чому бронювання відхилено, наприклад товари недоступні на ці дати.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        reservationOrgId
      </code>
      
      : номер бронювання, який співробітники бачать у застосунку.
    </td>
    
    <td>
      <code>
        reason
      </code>
      
      : <code>
        working_hours
      </code>
      
       або <code>
        minimum_duration
      </code>
      
      , коли порушено правило бронювання; відсутній для інших відмов, як-от через доступність.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        isRequest
      </code>
      
      : <code>
        true
      </code>
      
       для запиту на бронювання.
    </td>
    
    <td>
      <code>
        minimumDuration
      </code>
      
      : деталі відмови <code>
        minimum_duration
      </code>
      
      , див. нижче.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        paymentUrl
      </code>
      
       або <code>
        paymentRedirect
      </code>
      
      : куди перенаправити клієнта для онлайн-оплати. Перенаправлення <code>
        post_form
      </code>
      
       містить <code>
        fields
      </code>
      
       форми.
    </td>
    
    <td>
      
    </td>
  </tr>
</tbody>
</table>

Обидві форми містять `totalCost` і `currency`. Неправильні вхідні дані (як-от відсутнє поле чи невідомий товар) і далі викидають [`RequiplyError`](https://requiply.com/docs/uk/developers/typescript-sdk/error-handling).

### Мінімальна тривалість бронювання

`endDate` має бути пізніше за `startDate` (інакше `400` *endDate must be after startDate*). Бронювання також має тривати щонайменше **Мінімальна тривалість бронювання** з налаштувань [Тривалість бронювання](https://requiply.com/docs/uk/guides/settings/bookings/booking-duration) організації (24 години, якщо не змінено). Коротше бронювання відхиляється з `success: false`, `reason: "minimum_duration"`, а також обʼєктом `minimumDuration`, за яким можна запропонувати допустимий час повернення:

```json
{
  "success": false,
  "reason": "minimum_duration",
  "message": "...",
  "minimumDuration": {
    "minimumDurationMinutes": 1440,
    "requestedDurationMinutes": 240,
    "earliestReturn": "2026-10-07T10:00",
    "timeZone": "Europe/Kyiv"
  }
}
```

`earliestReturn` є найранішим допустимим поверненням для цієї видачі як місцевий час (`YYYY-MM-DDTHH:mm`) у `timeZone`. Тривалість вимірюється за місцевим часом організації, тож перехід на літній час не робить бронювання коротшим чи довшим.

## `bookings.list()`

```ts
bookings.list(
  params?: BookingListParams,
  options?: RequiplyRequestOptions,
): Promise<BookingListResponse>
```

Це серверна операція із секретним ключем. Бронювання йдуть від найновіших за часом створення. Необовʼязкові фільтри:

<table>
<thead>
  <tr>
    <th>
      Параметр
    </th>
    
    <th>
      Дія
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        dateFrom
      </code>
      
      , <code>
        dateTo
      </code>
    </td>
    
    <td>
      Бронювання, <strong>
        видача
      </strong>
      
       яких (<code>
        startDate
      </code>
      
      ) припадає на проміжок. Дата без часу означає північ, тож <code>
        dateTo: '2026-07-31'
      </code>
      
       не включає видачі пізніше 31 липня; передайте <code>
        '2026-07-31T23:59:59'
      </code>
      
       або наступний день.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        createdFrom
      </code>
      
      , <code>
        createdTo
      </code>
    </td>
    
    <td>
      Бронювання, створені в проміжку. Зручно для синхронізації нових бронювань з останнього запуску.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        status
      </code>
    </td>
    
    <td>
      Одна назва статусу або кілька через коми, без урахування регістру. Статуси належать кожній організації, тож беріть назви з власного застосунку. Невідома назва повертає порожній список.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        clientId
      </code>
    </td>
    
    <td>
      Бронювання одного клієнта.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        limit
      </code>
      
      , <code>
        cursor
      </code>
    </td>
    
    <td>
      Розмір сторінки (від 1 до 200, за замовчуванням 50) і <code>
        nextCursor
      </code>
      
       попередньої сторінки.
    </td>
  </tr>
</tbody>
</table>

```ts
const page = await requiply.bookings.list({
  dateFrom: '2026-07-01',
  dateTo: '2026-07-31',
  limit: 25,
});
```

Відповідь містить `bookings`, `currency`, а також `nextCursor: string | null`. Поля статусу, клієнта, загальної вартості та номера бронювання в організації в елементах списку можуть бути `null`.

## `bookings.get()`

```ts
bookings.get(
  id: number,
  params?: { idKind?: 'internal' | 'org' },
  options?: RequiplyRequestOptions,
): Promise<BookingDetailResponse>
```

Використовуйте `idKind: 'org'`, коли `id` є номером бронювання, який бачить організація. Інакше не передавайте параметр або використовуйте `internal`.

```ts
const { booking } = await requiply.bookings.get(1042, { idKind: 'org' });
```

Бронювання містить товари, послуги та оплати. Кілька полів статусу, клієнта, ціни, провайдера та URL оплати можуть бути `null`. `items` перелічує заброньовану кількість кожного товару, навіть коли одиниці призначають лише під час видачі.

`saleItems` перелічує товари, продані разом із бронюванням, а `saleId` вказує на їхній [продаж](https://requiply.com/docs/uk/developers/typescript-sdk/sales#salesget). Обидва порожні або `null`, коли нічого не продано чи функцію «Продажі» вимкнено. Сума товарів завжди входить у `totalCost`.

## `bookings.addNote()`

```ts
bookings.addNote(
  id: number,
  content: string,
  options?: RequiplyRequestOptions,
): Promise<BookingNoteResponse>
```

```ts
const note = await requiply.bookings.addNote(42, 'Customer confirmed pickup time.');
```

`content` має до 4000 символів. Нотатка внутрішня: співробітники бачать її в бронюванні, клієнт ніколи. Відповідь містить `noteId`, `reservationId`, а також `createdAt`, який може бути `null`. Це серверна операція із секретним ключем.


## Sitemap

See the full [sitemap](https://requiply.com/docs/sitemap.md) for all pages.
