[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"docs-infra\u002Fwake-schedules\u002Fcreate":3,"docs-tabs-infra\u002Fwake-schedules\u002Fcreate":6},{"content":4,"lastmod":5},"## Создать окно пробуждения\n\n`POST \u002Fv1\u002Finfra\u002Fservers\u002F:id\u002Fwake-schedules`\n\nОбъявляет новое повторяющееся окно пробуждения для сервера в режиме BLACKHOLE. Тело передаётся плоским объектом, без обёртки `fields`.\n\n## Параметры\n\n| Параметр | В | Тип | Обяз. | Описание |\n|----------|---|-----|:-----:|----------|\n| `id` | path | string (UUID) | да | ID BLACKHOLE-сервера |\n\n## Поля запроса (body)\n\n| Поле | Тип | Обяз. | По умолч. | Описание |\n|------|-----|:-----:|-----------|----------|\n| `cronExpr` | string | да | — | 5-польное cron-выражение (минута час день-месяца месяц день-недели), от 9 до 120 символов |\n| `timezone` | string | да | — | IANA-таймзона окна, например `Europe\u002FMoscow`. Проверяется по списку `Intl.supportedValuesOf('timeZone')` — незнакомое значение отклоняется на этапе валидации |\n| `label` | string | нет | — | Метка окна для отображения, до 80 символов |\n| `lead` | number | нет | запас сервера, иначе запас платформы | Запас в секундах перед моментом `cronExpr`, на который сервер должен быть уже поднят — покрывает время старта виртуальной машины. От 0 до 3600 |\n| `enabled` | boolean | нет | `true` | Активно ли окно. Отключённое окно не участвует в пробуждении, но остаётся в списке |\n\nЗапас `lead` разрешает три уровня: значение самого окна, иначе запас сервера, заданный отдельно от этого раздела CRUD, иначе запас по умолчанию на платформе — сейчас 180 секунд. Для сервера `kind: \"GALAXY_APP\"` пробуждение проходит два этапа — подъём хоста и старт контейнера, поэтому закладывайте `lead` до 900 секунд.\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fwake-schedules\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"cronExpr\": \"0 9 * * 1-5\",\n    \"timezone\": \"Europe\u002FMoscow\",\n    \"label\": \"daily report\",\n    \"enabled\": true\n  }'\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -X POST \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002FSERVER_ID\u002Fwake-schedules\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"cronExpr\": \"0 9 * * 1-5\",\n    \"timezone\": \"Europe\u002FMoscow\",\n    \"label\": \"daily report\",\n    \"enabled\": true\n  }'\n```\n\n### JavaScript — личный ключ\n\n```javascript\nconst res = await fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Fwake-schedules`,\n  {\n    method: 'POST',\n    headers: {\n      'X-Api-Key': 'YOUR_API_KEY',\n      'Content-Type': 'application\u002Fjson',\n    },\n    body: JSON.stringify({\n      cronExpr: '0 9 * * 1-5',\n      timezone: 'Europe\u002FMoscow',\n      label: 'daily report',\n      enabled: true,\n    }),\n  }\n)\nconst body = await res.json()\nif (body.tzWarningCode === 'MULTI_ZONE') {\n  console.warn('Окна расходятся по часовым поясам — TZ в деплое не проставляется')\n}\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nconst res = await fetch(\n  `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Finfra\u002Fservers\u002F${serverId}\u002Fwake-schedules`,\n  {\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      cronExpr: '0 9 * * 1-5',\n      timezone: 'Europe\u002FMoscow',\n      label: 'daily report',\n      enabled: true,\n    }),\n  }\n)\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|----------|\n| `success` | boolean | Всегда `true` при успехе |\n| `data.id` | string | ID окна для последующего обновления и удаления |\n| `data.serverId` | string (UUID) | ID сервера-владельца |\n| `data.cronExpr` | string | Сохранённое cron-выражение |\n| `data.timezone` | string | Сохранённая таймзона |\n| `data.label` | string \\| null | Метка окна |\n| `data.lead` | number \\| null | Запас в секундах. `null`, если не задан на уровне окна |\n| `data.enabled` | boolean | Активно ли окно |\n| `data.source` | string | Как создано окно. Всегда `\"MANUAL\"` для окон, созданных через этот CRUD |\n| `data.lastFiredAt` | string (ISO 8601) \\| null | Момент последнего подтверждённого срабатывания. `null` для только что созданного окна |\n| `data.wakeAttemptStartedAt` | string (ISO 8601) \\| null | Служебная метка планировщика — непусто только в течение короткого окна, пока идёт пробуждение. В норме `null` |\n| `data.lastWakeLateAt` | string (ISO 8601) \\| null | Момент последнего пробуждения, сработавшего позже расчётного окна. `null`, если опозданий не было |\n| `data.createdAt` | string (ISO 8601) | Дата создания записи |\n| `data.updatedAt` | string (ISO 8601) | Дата последнего обновления записи |\n| `tzWarning` | string \\| null | Предупреждение о рассинхроне таймзоны — текстом. `null`, если у сервера не осталось активных окон после этой мутации |\n| `tzWarningCode` | string \\| null | Машиночитаемый код того же предупреждения: `\"SINGLE_ZONE\"`, `\"MULTI_ZONE\"` или `null` |\n| `preemptibleAdvisoryCode` | string \\| null | `\"PREEMPTIBLE_BEST_EFFORT\"`, если сервер работает на вытесняемом тарифе — иначе `null` |\n| `preemptibleAdvisory` | string \\| null | Пояснение того же предупреждения текстом (на английском, для не-UI-клиентов API). `null`, если сервер на невытесняемом тарифе |\n\n`tzWarning`, `tzWarningCode`, `preemptibleAdvisoryCode` и `preemptibleAdvisory` — поля верхнего уровня ответа, не вложены в `data`.\n\n## Пример ответа\n\nЕдинственное активное окно сервера — таймзона однозначна:\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"cm38x02qp0001ml08g7k3h2a\",\n    \"serverId\": \"e765edfc-ba0a-43de-b8ea-838dd872c522\",\n    \"cronExpr\": \"0 9 * * 1-5\",\n    \"timezone\": \"Europe\u002FMoscow\",\n    \"label\": \"daily report\",\n    \"lead\": null,\n    \"enabled\": true,\n    \"source\": \"MANUAL\",\n    \"lastFiredAt\": null,\n    \"wakeAttemptStartedAt\": null,\n    \"lastWakeLateAt\": null,\n    \"createdAt\": \"2026-07-10T08:12:00.000Z\",\n    \"updatedAt\": \"2026-07-10T08:12:00.000Z\"\n  },\n  \"tzWarning\": \"The VM may have been deployed with a different timezone (or not redeployed since this window was declared) — verify the in-VM cron or redeploy the app so TZ is re-injected.\",\n  \"tzWarningCode\": \"SINGLE_ZONE\",\n  \"preemptibleAdvisoryCode\": null,\n  \"preemptibleAdvisory\": null\n}\n```\n\nСервер на вытесняемом тарифе получил бы `\"preemptibleAdvisoryCode\": \"PREEMPTIBLE_BEST_EFFORT\"` и непустой `preemptibleAdvisory` вместо `null` в тех же двух полях — остальная форма ответа не меняется.\n\n## Пример ответа при ошибке\n\n400 — окно нарушает гарантию сервера «Всегда онлайн»:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"ALWAYS_ON_CONFLICT\",\n    \"message\": \"Scheduled wake conflicts with an always-on (24\u002F7) server, which never auto-sleeps. Turn off the always-on toggle, or set a sleep timeout instead of \\\"Never\\\", to schedule wake windows.\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|----------|\n| 400 | `VALIDATION_ERROR` | Нарушена валидация тела — отсутствует `cronExpr`\u002F`timezone`, `timezone` не входит в список IANA-таймзон, `label` длиннее 80 символов, `lead` вне диапазона 0–3600 или в теле лишнее поле |\n| 400 | `BLACKHOLE_ONLY` | Сервер не в режиме BLACKHOLE |\n| 400 | `GALAXY_NOT_SUPPORTED` | Сервер — хост галактики (`kind: \"GALAXY\"`). Вложенные приложения (`kind: \"GALAXY_APP\"`) принимаются, отклоняется только сам хост |\n| 400 | `ALWAYS_ON_CONFLICT` | Сервер работает в режиме «Всегда онлайн» — на невытесняемом тарифе и без авто-сна. Расписание пробуждения тихо нарушило бы эту гарантию |\n| 400 | `CADENCE_TOO_LOW` | Интервал между соседними срабатываниями `cronExpr` меньше минимального, заданного на платформе — сейчас 5 минут |\n| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |\n| 401 | `INVALID_API_KEY` | Неверный или просроченный API-ключ |\n| 403 | `WAKE_SCHEDULE_DISABLED` | Пробуждение по расписанию не включено для этого портала |\n| 403 | `WAKE_SCHEDULE_LIMIT` | У сервера уже 50 окон — предел на сервер |\n| 403 | `INFRA_SCOPE_REQUIRED` | У ключа нет скоупа `vibe:infra` |\n| 404 | `NOT_FOUND` | Сервер не найден, удалён или принадлежит другому API-ключу |\n| 429 | `RATE_LIMITED` | Превышен лимит 10 запросов в минуту на этот эндпоинт |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n- **Порядок проверок.** Скоуп ключа и владение сервером проверяются раньше остальных гейтов, поэтому `WAKE_SCHEDULE_DISABLED`\u002F`BLACKHOLE_ONLY`\u002F`GALAXY_NOT_SUPPORTED`\u002F`ALWAYS_ON_CONFLICT` увидит только запрос с корректным ключом на существующий свой сервер. Проверка cron-выражения (`VALIDATION_ERROR`, затем `CADENCE_TOO_LOW`) идёт после этих гейтов.\n- **`tzWarning`\u002F`tzWarningCode` — консервативная эвристика.** Платформа не хранит, был ли сервер передеплоен после объявления окна, поэтому предупреждение приходит при любом наборе активных окон после мутации — даже если таймзона уже верно проставлена в переменных окружения. Ориентируйтесь на код: `\"SINGLE_ZONE\"` — таймзона однозначна и попадёт в `TZ` при следующем деплое, `\"MULTI_ZONE\"` — окна в разных поясах, `TZ` не проставляется автоматически.\n- **`preemptibleAdvisoryCode`\u002F`preemptibleAdvisory` — не гейт, а предупреждение.** Окно создаётся или обновляется независимо от значения этих полей — на вытесняемом тарифе платформа не запрещает расписание (это её целевой сценарий), а лишь честно сообщает, что подъём к моменту окна best-effort. Локализуйте по коду `preemptibleAdvisoryCode`, а не по строке `preemptibleAdvisory` — это фиксированная английская строка для не-UI-клиентов, не предназначенная для показа пользователю как есть.\n- **Cron внутри VM платформа не настраивает.** `POST \u002Fwake-schedules` только гарантирует, что сервер поднят к нужному моменту (на вытесняемом тарифе — best-effort, см. `preemptibleAdvisoryCode` выше). Запуск задачи в этот момент — ответственность собственного `cron`\u002Fтаймера внутри приложения.\n\n## Смотрите также\n\n- [Список окон](.\u002Flist.md)\n- [Обновить окно](.\u002Fupdate.md)\n- [Удалить окно](.\u002Fdelete.md)\n- [Что приходит в приложение](\u002Fdocs\u002Finfra\u002Fapp-runtime) — таймзона деплоя и in-VM cron\n","2026-07-22",{}]