[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"docs-entities\u002Fsites\u002Fsearch":3,"docs-tabs-entities\u002Fsites\u002Fsearch":6},{"content":4,"lastmod":5},"\n## Search sites\n\n`POST \u002Fv1\u002Fsites\u002Fsearch`\n\nSearches for sites with filtering and auto-pagination. Equivalent to `GET \u002Fv1\u002Fsites` with filters, but via POST — more convenient for complex requests with many conditions.\n\n## Request fields (body)\n\n| Parameter | Type | Default | Description |\n|----------|-----|-----------|---------|\n| `filter` | object | — | Filtering by the fields from `GET \u002Fv1\u002Fsites\u002Ffields`.\u003Cbr>[Filtering syntax](\u002Fdocs\u002Ffiltering) |\n| `limit` | number | `50` | Number of records (up to 5000) |\n| `offset` | number | `0` | Skip N records. Combined with a date-range filter longer than 14 days, the request is rejected — see `UNSTABLE_OFFSET_PAGINATION` in the \"Errors\" section |\n| `select` | string[] | — | Field selection: `[\"id\", \"title\", \"type\"]` |\n| `autoWindow` | boolean | `true` | Split the result set into weekly windows when filtering by a date range longer than 14 days. `false` disables splitting |\n| `sort` | string | ascending by `id` | Sort field and direction: `\"-id\"` for descending, `\"id\"` for ascending. The parameter is also accepted under the name `order` |\n| `scope` | string | — | Internal landing area: `KNOWLEDGE` \u002F `GROUP` \u002F `MAINPAGE`. Without the parameter, regular landing sites are returned. Accepted at the top level of the body (`\"scope\": \"KNOWLEDGE\"`) or inside `filter.scope` — both forms produce the same request to Bitrix24 |\n\n> **Type filter and area (`scope`).** Bitrix24 binds `filter.type` to the current area — the default area exposes only `PAGE` \u002F `STORE` \u002F `SMN` \u002F `VIBE`. If you filter by `{\"filter\": {\"type\": \"KNOWLEDGE\"}}` or `\"GROUP\"` and do **not** pass `scope`, Vibecode supplies the matching area itself (`type=KNOWLEDGE` → `scope=KNOWLEDGE`), and the search returns exactly the knowledge bases \u002F group pages. An explicit `scope` wins. If the type is specified using a list or operator (`{\"type\": {\"$in\": [\"KNOWLEDGE\", \"PAGE\"]}}`) and no single area can be determined, `meta.warnings` includes a hint with the code `TYPE_REQUIRES_SCOPE`. `MAINPAGE` is an area, not a site type (its sites have type `VIBE`), so it is not derived from the filter.\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fsites\u002Fsearch\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"filter\": { \"type\": \"PAGE\", \"active\": true },\n    \"limit\": 10,\n    \"select\": [\"id\", \"title\", \"type\", \"active\"]\n  }'\n```\n\n### curl — OAuth application\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fsites\u002Fsearch\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"filter\": { \"type\": \"PAGE\", \"active\": true },\n    \"limit\": 10,\n    \"select\": [\"id\", \"title\", \"type\", \"active\"]\n  }'\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fsites\u002Fsearch', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    filter: { type: 'PAGE', active: true },\n    limit: 10,\n    select: ['id', 'title', 'type', 'active'],\n  }),\n})\n\nconst { success, data, meta } = await res.json()\nconsole.log('Returned:', data.length)\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fsites\u002Fsearch', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    filter: { type: 'PAGE', active: true },\n    limit: 10,\n    select: ['id', 'title', 'type', 'active'],\n  }),\n})\n\nconst { success, data, meta } = await res.json()\n```\n\n## Response fields\n\n| Field | Type | Description |\n|------|-----|---------|\n| `success` | boolean | Always `true` on success |\n| `data` | array | Array of sites. All item fields — [Site fields](\u002Fdocs\u002Fentities\u002Fsites\u002Ffields). With `select`, each item holds only the listed fields |\n| `meta.total` | number | The exact number of records matching the filter, when known. Omitted when the search across time windows is incomplete |\n| `meta.hasMore` | boolean | Whether there are more records beyond `limit` |\n| `meta.durationMs` | number | Request duration in milliseconds |\n| `meta.autoWindowed` | boolean | `true` if the result set was split into time windows |\n| `meta.windowCount` | number | Number of windows. Present with `autoWindowed: true` |\n| `meta.batchWaves` | number | Number of parallel request waves. Present with `autoWindowed: true` |\n\nThe `meta` fields sit next to `data`, not inside it. Use `meta.hasMore` to paginate: even when the length of `data` equals `limit`, this can be the last page.\n\nUse a site's `id` from the `data` array in the following URL:\n\n```\nhttps:\u002F\u002F\u003Cportal>.bitrix24.com\u002Fsites\u002Fsite\u002F\u003Cid>\u002F\n```\n\n`\u003Cportal>` is your Bitrix24 account domain. Access is restricted by the employee's permissions in Bitrix24.\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": [\n    {\n      \"id\": 157,\n      \"title\": \"Promo landing\",\n      \"code\": \"\u002Fpromo\u002F\",\n      \"type\": \"PAGE\",\n      \"active\": true,\n      \"domainId\": 5,\n      \"createdById\": 1,\n      \"dateCreate\": \"12.09.2024 10:23:14\",\n      \"dateModify\": \"04.11.2025 08:51:20\"\n    }\n  ],\n  \"meta\": {\n    \"total\": 10,\n    \"hasMore\": false,\n    \"durationMs\": 99\n  }\n}\n```\n\nWith a date-range filter longer than 14 days, `meta` also includes `autoWindowed`, `windowCount`, and `batchWaves`:\n\n```json\n{\n  \"success\": true,\n  \"data\": [ \u002F* ... *\u002F ],\n  \"meta\": {\n    \"total\": 2,\n    \"hasMore\": false,\n    \"autoWindowed\": true,\n    \"windowCount\": 339,\n    \"batchWaves\": 4,\n    \"durationMs\": 3136\n  }\n}\n```\n\n## Error response example\n\n403 — missing required scope:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"SCOPE_DENIED\",\n    \"message\": \"This endpoint requires 'landing' scope\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|---------|\n| 400 | `UNSTABLE_OFFSET_PAGINATION` | `offset` greater than zero together with a date-range filter longer than 14 days. Two different retrieval algorithms produce inconsistent results, so the request is rejected. Fetch everything in a single request with `limit` up to 5000, or pass `autoWindow: false` with sorting by `id`, or split the date range into parts yourself |\n| 403 | `SCOPE_DENIED` | The API key does not have the `landing` scope |\n| 401 | `TOKEN_MISSING` | The API key has no configured tokens |\n| 409 | `LANDING_MODULE_NOT_ENABLED` | The Sites module is unavailable on this portal. Ask the portal administrator to enable it — requests will continue to return the same error until it is enabled |\n| 429 | `RATE_LIMITED` | Rate limit exceeded: 300 requests per minute per portal. All API keys for the portal share this limit. The exact value is returned in the `x-ratelimit-limit` header. Retry after the delay specified in the `Retry-After` header |\n\nFor the full list of common API errors, see [Errors](\u002Fdocs\u002Ferrors).\n\n## Known specifics\n\n**Time-window splitting.** A date-range filter longer than 14 days is automatically split into weekly windows executed in parallel waves, so the result set bypasses the ceiling of 5000 records per call. `meta` then includes `autoWindowed: true`, the number of windows `windowCount`, and the number of waves `batchWaves`. The `autoWindow: false` parameter disables splitting. While splitting is active, an `offset` greater than zero is rejected with `UNSTABLE_OFFSET_PAGINATION`.\n\n**Visibility by user permissions.** The search returns only the sites the API key owner has \"view\" permission for. If a result is expected but `data` is empty, check the user's permissions.\n\n**Deleted sites.** Excluded by default. To include them in the result, pass `{\"filter\": {\"deleted\": \"Y\"}}`. Values are `Y` or `N`.\n\n**Pagination via `offset` is supported.** Vibecode returns the requested `[offset, offset + limit)` window. When present, `meta.total` is the exact number of records matching the filter. A search across time windows returns the count only after all windows have been read successfully and duplicates removed; the field is omitted when the search stops early at `limit` or a window returns an incomplete result. The API does not make additional requests solely to obtain a count. `data.length` is the number of returned records, and `meta.hasMore` shows whether there are records beyond the window.\n## See also\n\n- [List sites](\u002Fdocs\u002Fentities\u002Fsites\u002Flist)\n- [Get site](\u002Fdocs\u002Fentities\u002Fsites\u002Fget)\n- [Filtering syntax](\u002Fdocs\u002Ffiltering)\n- [Batch](\u002Fdocs\u002Fbatch)\n- [Limits and optimization](\u002Fdocs\u002Foptimization)\n","2026-10-23",{},1794739421774]