For AI agents: markdown of this page — /docs-content-en/infra/wake-schedules/create.md documentation index — /llms.txt

Create a wake window

POST /v1/infra/servers/:id/wake-schedules

Declares a new recurring wake window for a server in BLACKHOLE mode. The body is a flat object, with no fields wrapper.

Parameters

Parameter In Type Required Description
id path string (UUID) yes ID of the BLACKHOLE server

Request fields (body)

Field Type Required Default Description
cronExpr string yes A 5-field cron expression (minute hour day-of-month month day-of-week), 9 to 120 characters
timezone string yes IANA timezone of the window, e.g. America/New_York. Checked against Intl.supportedValuesOf('timeZone') — an unknown value is rejected at validation
label string no Display label for the window, up to 80 characters
lead number no the server's margin, else the platform's Margin, in seconds, before the cronExpr moment by which the server must already be up — covers VM boot time. 0 to 3600
enabled boolean no true Whether the window is active. A disabled window doesn't participate in waking but stays in the list

The lead margin resolves in three tiers: the window's own value, else a server-level margin set apart from this CRUD, else the platform default — currently 180 seconds. For a server with kind: "GALAXY_APP", waking runs in two phases — bringing up the host and starting the container — so budget lead up to 900 seconds.

Examples

curl — personal key

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/wake-schedules" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "cronExpr": "0 9 * * 1-5",
    "timezone": "America/New_York",
    "label": "daily report",
    "enabled": true
  }'

curl — OAuth app

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/wake-schedules" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "cronExpr": "0 9 * * 1-5",
    "timezone": "America/New_York",
    "label": "daily report",
    "enabled": true
  }'

JavaScript — personal key

javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/wake-schedules`,
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      cronExpr: '0 9 * * 1-5',
      timezone: 'America/New_York',
      label: 'daily report',
      enabled: true,
    }),
  }
)
const body = await res.json()
if (body.tzWarningCode === 'MULTI_ZONE') {
  console.warn('Windows span more than one timezone — TZ is not injected at deploy time')
}

JavaScript — OAuth app

javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/wake-schedules`,
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      cronExpr: '0 9 * * 1-5',
      timezone: 'America/New_York',
      label: 'daily report',
      enabled: true,
    }),
  }
)

Response fields

Field Type Description
success boolean Always true on success
data.id string Window ID for a later update or delete
data.serverId string (UUID) ID of the owning server
data.cronExpr string The stored cron expression
data.timezone string The stored timezone
data.label string | null Window label
data.lead number | null Margin in seconds. null when not set on the window itself
data.enabled boolean Whether the window is active
data.source string How the window was created. Always "MANUAL" for windows created through this CRUD
data.lastFiredAt string (ISO 8601) | null Timestamp of the last confirmed firing. null for a freshly created window
data.wakeAttemptStartedAt string (ISO 8601) | null Internal scheduler claim marker — non-null only during the short window while a wake is in flight. Normally null
data.lastWakeLateAt string (ISO 8601) | null Timestamp of the last wake that fired later than its computed window. null if there have been no late wakes
data.createdAt string (ISO 8601) Record creation date
data.updatedAt string (ISO 8601) Date of the last update to the record
tzWarning string | null Timezone-mismatch advisory, as text. null when the server has no active windows left after this mutation
tzWarningCode string | null Machine-readable code for the same advisory: "SINGLE_ZONE", "MULTI_ZONE", or null
preemptibleAdvisoryCode string | null "PREEMPTIBLE_BEST_EFFORT" when the server runs on a preemptible plan — otherwise null
preemptibleAdvisory string | null An explanation of the same advisory, as text (in English, for non-UI API clients). null when the server is on a non-preemptible plan

tzWarning, tzWarningCode, preemptibleAdvisoryCode, and preemptibleAdvisory are top-level response fields, not nested under data.

Response example

The server's only active window — the timezone is unambiguous:

JSON
{
  "success": true,
  "data": {
    "id": "cm38x02qp0001ml08g7k3h2a",
    "serverId": "e765edfc-ba0a-43de-b8ea-838dd872c522",
    "cronExpr": "0 9 * * 1-5",
    "timezone": "America/New_York",
    "label": "daily report",
    "lead": null,
    "enabled": true,
    "source": "MANUAL",
    "lastFiredAt": null,
    "wakeAttemptStartedAt": null,
    "lastWakeLateAt": null,
    "createdAt": "2026-07-10T08:12:00.000Z",
    "updatedAt": "2026-07-10T08:12:00.000Z"
  },
  "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.",
  "tzWarningCode": "SINGLE_ZONE",
  "preemptibleAdvisoryCode": null,
  "preemptibleAdvisory": null
}

A server on a preemptible plan would get "preemptibleAdvisoryCode": "PREEMPTIBLE_BEST_EFFORT" and a non-empty preemptibleAdvisory instead of null in those same two fields — the rest of the response shape is unchanged.

Error response example

400 — the window conflicts with an always-on server:

JSON
{
  "success": false,
  "error": {
    "code": "ALWAYS_ON_CONFLICT",
    "message": "Scheduled wake conflicts with an always-on (24/7) server, which never auto-sleeps. Turn off the always-on toggle, or set a sleep timeout instead of \"Never\", to schedule wake windows."
  }
}

Errors

HTTP Code Description
400 VALIDATION_ERROR Body validation failed — missing cronExpr/timezone, timezone not in the IANA timezone list, label over 80 characters, lead outside 0–3600, or an unknown field in the body
400 BLACKHOLE_ONLY The server is not in BLACKHOLE mode
400 GALAXY_NOT_SUPPORTED The server is a Galaxy host (kind: "GALAXY"). Nested apps (kind: "GALAXY_APP") are accepted — only the host itself is rejected
400 ALWAYS_ON_CONFLICT The server runs in always-on mode — no auto-sleep. A wake schedule would silently break that guarantee
400 CADENCE_TOO_LOW The gap between consecutive cronExpr occurrences is below the platform's floor — currently 5 minutes
401 MISSING_API_KEY The X-Api-Key header is missing
401 INVALID_API_KEY The API key is invalid or expired
403 WAKE_SCHEDULE_DISABLED Scheduled wake is not enabled for this portal
403 WAKE_SCHEDULE_LIMIT The server already has 50 windows — the per-server cap
403 INFRA_SCOPE_REQUIRED The key lacks the vibe:infra scope
404 NOT_FOUND The server was not found, was deleted, or belongs to a different API key
429 RATE_LIMITED The 10-requests-per-minute limit for this endpoint was exceeded

Full list of shared error codes — Errors.

Known behavior

  • Check order. The key's scope and server ownership are checked before the other gates, so WAKE_SCHEDULE_DISABLED/BLACKHOLE_ONLY/GALAXY_NOT_SUPPORTED/ALWAYS_ON_CONFLICT only ever surface for a request with a valid key against an owned, existing server. The cron-expression checks (VALIDATION_ERROR, then CADENCE_TOO_LOW) run after these gates.
  • tzWarning/tzWarningCode are a conservative heuristic. The platform doesn't track whether the server was actually redeployed since a window was declared, so the advisory fires for any set of active windows after a mutation — even when the timezone is already correctly set in the environment. Go by the code: "SINGLE_ZONE" means the timezone is unambiguous and lands in TZ on the next deploy, "MULTI_ZONE" means the windows span more than one zone and TZ is not auto-injected.
  • preemptibleAdvisoryCode/preemptibleAdvisory are an advisory, not a gate. The window is created or updated regardless of these fields' value — on a preemptible plan the platform does not forbid a schedule (that's its intended use case), it only honestly reports that waking by the window's moment is best-effort. Localize on the preemptibleAdvisoryCode code, not on the preemptibleAdvisory string — that is a fixed English string for non-UI clients, not meant to be shown to a user as-is.
  • The platform does not configure the cron inside the VM. POST /wake-schedules only guarantees the server is up by the target moment (best-effort on a preemptible plan — see preemptibleAdvisoryCode above). Firing the task at that moment is the app's own cron/timer's job.

See also