
## Search bookings

`POST /v1/bookings/search`

Returns bookings for the given date range. The start and end of the interval are required. Suitable when it is more convenient to pass the request parameters in the body rather than in the query string.

## Request fields (body)

Accepts two equivalent forms. Use either one.

**Form 1 — parameters at the top level:**

| Field | Type | Required | Default | Description |
|------|-----|:-----:|-----------|---------|
| `dateFrom` | string \| number | yes | — | Start of the interval. ISO 8601 (`"2026-05-01T00:00:00Z"`) or Unix seconds (`1714521600`) |
| `dateTo` | string \| number | yes | — | End of the interval. ISO 8601 or Unix seconds |
| `limit` | number | no | `50` | Number of records (from 1 to 5000) |
| `offset` | number | no | `0` | Offset |

**Form 2 — parameters in a nested filter:**

| Field | Type | Required | Description |
|------|-----|:-----:|---------|
| `filter.within.dateFrom` | string \| number | yes | Start of the interval |
| `filter.within.dateTo` | string \| number | yes | End of the interval |

## Examples

### curl — personal key

```bash
curl -X POST "https://vibecode.bitrix24.com/v1/bookings/search" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "dateFrom": "2024-01-01T00:00:00Z",
    "dateTo": "2026-12-31T23:59:59Z",
    "limit": 10
  }'
```

### curl — OAuth application

```bash
curl -X POST "https://vibecode.bitrix24.com/v1/bookings/search" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "dateFrom": "2024-01-01T00:00:00Z",
    "dateTo": "2026-12-31T23:59:59Z",
    "limit": 10
  }'
```

### JavaScript — personal key

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/bookings/search', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    dateFrom: '2024-01-01T00:00:00Z',
    dateTo: '2026-12-31T23:59:59Z',
    limit: 10,
  }),
})

const { success, data, meta } = await res.json()
console.log(`Received ${data.length} bookings, hasMore: ${meta.hasMore}`)
```

### JavaScript — OAuth application

```javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/bookings/search', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    dateFrom: '2024-01-01T00:00:00Z',
    dateTo: '2026-12-31T23:59:59Z',
    limit: 10,
  }),
})

const { success, data, meta } = await res.json()
```

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | Always `true` on success |
| `data` | array | Array of bookings (each record's fields — see [Bookings](/docs/entities/bookings)) |
| `meta.total` | number | Always `0` — the total count is not computed. To determine whether there are more records, use `meta.hasMore` |
| `meta.hasMore` | boolean | `true` if the number of records matching the condition exceeds `limit` |

The `meta` fields sit next to `data`, not inside it. Pages must be walked using `meta.hasMore`: a `data` length equal to `limit` does not rule out the last page.

## Response example

```json
{
  "success": true,
  "data": [
    {
      "datePeriod": {
        "from": {
          "timestamp": 1723446900,
          "timezone": "UTC"
        },
        "to": {
          "timestamp": 1723447800,
          "timezone": "UTC"
        }
      },
      "description": null,
      "id": 3,
      "name": null,
      "resourceIds": [1, 3]
    },
    {
      "datePeriod": {
        "from": {
          "timestamp": 1741687200,
          "timezone": "UTC"
        },
        "to": {
          "timestamp": 1741690800,
          "timezone": "UTC"
        }
      },
      "description": null,
      "id": 1,
      "name": "Booking",
      "resourceIds": [1]
    },
    {
      "datePeriod": {
        "from": {
          "timestamp": 1752570000,
          "timezone": "UTC"
        },
        "to": {
          "timestamp": 1752571800,
          "timezone": "UTC"
        }
      },
      "description": null,
      "id": 5,
      "name": null,
      "resourceIds": [1]
    }
  ],
  "meta": {
    "total": 0,
    "hasMore": true
  }
}
```

## Error response example

400 — required parameters not passed:

```json
{
  "success": false,
  "error": {
    "code": "MISSING_REQUIRED_PARAMS",
    "message": "POST /v1/bookings/search requires { dateFrom, dateTo } at the top level OR { filter: { within: { dateFrom, dateTo } } }. Values are ISO 8601 or Unix seconds."
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `MISSING_REQUIRED_PARAMS` | `dateFrom` or `dateTo` not passed in any of the allowed forms |
| 400 | `INVALID_DATE` | The `dateFrom` or `dateTo` value is not ISO 8601 or Unix seconds |
| 400 | `INVALID_PARAMS` | `limit` is less than 1 or is not a number |
| 403 | `SCOPE_DENIED` | The API key does not have the `booking` scope |
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header was not passed |
| 401 | `TOKEN_MISSING` | The API key has no configured tokens |

Full list of common API errors — [Errors](/docs/errors).

## See also

- [List bookings](/docs/entities/bookings/list)
- [Get a booking](/docs/entities/bookings/get)
- [Create a booking](/docs/entities/bookings/create)
- [Filtering syntax](/docs/filtering)
- [Batch](/docs/batch)
- [Limits and optimization](/docs/optimization)
