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

Delete a server

DELETE /v1/infra/servers/:id

Deletes a server irreversibly: the virtual machine is destroyed at the provider, the database record is marked as DELETED, and open billing transactions are finalized. A deleted server cannot be recovered — create a new one via POST /v1/infra/servers. Deletion is idempotent only for the virtual machine on the provider side: if it has already been deleted there, no error is returned. A repeated call for a server that is already marked deleted returns 404.

Parameters

Parameter In Type Required Description
id path string (UUID) yes Server ID from POST /v1/infra/servers or GET /v1/infra/servers

Examples

curl — personal key

Terminal
curl -X DELETE -H "X-Api-Key: YOUR_API_KEY" \
  https://vibecode.bitrix24.com/v1/infra/servers/db008c84-91a5-4e15-b9d5-6c6aa2838448

curl — OAuth application

Terminal
curl -X DELETE -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID

JavaScript — personal key

javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}`,
  {
    method: 'DELETE',
    headers: { 'X-Api-Key': 'YOUR_API_KEY' },
  }
)
const { success } = await res.json()
if (success) console.log('Server deleted')

JavaScript — OAuth application

javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}`,
  {
    method: 'DELETE',
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
    },
  }
)

Response fields

Field Type Description
success boolean true on successful deletion

The response is short — the body { "success": true } confirms the deletion. No additional data is returned.

Response example

JSON
{
  "success": true
}

Error response example

404 — the server is already deleted or does not exist:

JSON
{
  "success": false,
  "error": {
    "code": "NOT_FOUND",
    "message": "Server not found"
  }
}

Errors

HTTP Code Description
401 MISSING_API_KEY The X-Api-Key header was not provided
401 INVALID_API_KEY Invalid or expired API key
404 NOT_FOUND Server not found, belongs to another API key, or was already deleted
409 GALAXY_HAS_APPS The server is a Galaxy host that still has non-deleted applications. Delete the applications first, then the host. The body contains appCount
502 GALAXY_HOST_UNREACHABLE A Galaxy application: its host is unreachable and could not be woken. The response carries error.hint with a recovery plan — see "Known specifics"
429 RATE_LIMITED The platform's overall request limit was exceeded

The full list of common API errors — Errors.

Known specifics

  • Handling 404 on retries is normal. If the client lost the connection after the first DELETE, a retry will return 404. Catch 404 as "already deleted".
  • If the virtual machine has already been deleted at the provider by another means (the provider's panel, manual cleanup) — DELETE still succeeds and marks the database record as deleted.
  • The quota is freed immediately. After deletion you can create a new server right away — MAX_SERVERS_REACHED will no longer count this record.
  • Deletion works for any status. Servers in provisioning, running, sleeping, and error are all deleted normally.
  • A Galaxy application is deleted by this same method. When a Bitrix24 account places applications in galaxies (several applications run as containers on a shared host), DELETE /v1/infra/servers/:id removes the application the key owns: it tears down its container on the host and marks the record deleted. The response is 200 { "success": true }, the same as for a regular server.
  • The platform wakes a sleeping Galaxy host on its own. If the host of a Galaxy application is asleep, the platform wakes it before tearing down the container — there is no need to wake another application and retry the request. The error 502 GALAXY_HOST_UNREACHABLE remains only when the host is unreachable or could not be woken, for example when it is frozen for billing. In that case retry the request shortly.
  • The 502 GALAXY_HOST_UNREACHABLE response has an error.hint field with a recovery plan. It is an object of four strings: reason — why the host is unreachable right now, recovery — what to do, recoveryAction — the concrete call to retry, note — a caveat that the host status in the listing can lag behind the real tunnel state. The point of the hint: the server record is preserved until the container teardown actually runs on the host, so retrying the request in 1–2 minutes loses nothing. If the condition holds beyond 15 minutes, the host is genuinely down.
  • A Galaxy host with non-deleted applications is not deleted by this method. If the server is a Galaxy host that still has non-deleted applications, the request returns 409 GALAXY_HAS_APPS with an appCount field. Delete the host's applications first, then the host itself.

See also

Create a server

POST /v1/infra/servers

Creates an application with a cloud provider. Always in Black Hole mode — iptables blocks all inbound ports, the application is invisible from the internet.

Your Bitrix24 account has two placement models, and what to expect after creation depends on the model:

  • A dedicated virtual machine (the default model). The response is returned immediately with the provisioning status. Provisioning takes 1–3 minutes, after which you need to poll GET /v1/infra/servers/:id until status: "running" and blackholeStatus: "CONNECTED". The response contains the SSH data ssh.password and ssh.privateKey only once — they will be needed when switching to OPEN mode, so save them right away. This page describes that model in the request fields, response fields, and error table below.
  • A Galaxy application — a container on a shared host. If your Bitrix24 account places apps in galaxies, the same POST /v1/infra/servers creates a Galaxy application instead of a virtual machine. In the response, this model is marked by createdVia: "galaxy". The "Galaxy application" section below describes the two startup scenarios, and the full model is on the Galaxy app page.

Galaxy application

If your Bitrix24 account places apps in galaxies, POST /v1/infra/servers creates a Galaxy application — a container on a shared host rather than a dedicated virtual machine. The request and the call order are the same, but the lifecycle differs. In the response, this model is marked by createdVia: "galaxy". The full model, cost, and deploy differences are on the Galaxy app page.

Do not wait for CONNECTED before uploading the code. A Galaxy application never reaches blackholeStatus: "CONNECTED" on its own — its container is built on code upload. If you just poll the status, the app stays in provisioning, and after about 20 minutes the platform marks it as error and records in the provisionError field that the code was never uploaded. So upload the code right away — using one of the two scenarios below.

A single request. Pass the application code in the source field of POST /v1/infra/servers together with runtime and start (and, if needed, install, env, port). The build runs in the background. After the response, poll GET /v1/infra/servers/:id until status: "running". A separate code-upload call is not needed.

Terminal
curl -X POST https://vibecode.bitrix24.com/v1/infra/servers \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-crm-app",
    "displayName": "My CRM bot",
    "source": { "content": "<base64-archive>" },
    "runtime": "node20",
    "start": "node index.js",
    "install": "npm ci",
    "port": 3000
  }'

The source, runtime, start, install, env, port fields have the same meaning as in the POST /:id/deploy body:

Field Type Required Description
source object yes (for this scenario) The code source. source.content — the application archive in base64, up to 500 MB per request body
runtime string yes (if source is passed) Runtime ID: node20, python311, php83, static, and others. The list — GET /v1/infra/runtimes
start string yes (if source is passed) The application start command, on a single line. A line break will return 400
install string no The dependency-install command, on a single line
env object no Environment variables { "KEY": "value" }. Injected into the container at start, see below
port number no The port the application listens on

Without the runtime and start fields, the source field returns 400 — both fields are required. On a Bitrix24 account without Galaxy mode, source is forbidden and returns 400 SOURCE_AT_CREATE_GALAXY_ONLY.

Scenario 2 — two-step

Create the application without source — the response comes with the provisioning status and the hint next: "deploy". Immediately call POST /v1/infra/servers/:id/deploy with the code in source, the runtime, and the start command. Upload the code right away, without waiting for CONNECTED.

Terminal
# Step 1 — create the application without code
curl -X POST https://vibecode.bitrix24.com/v1/infra/servers \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "provider": "bitrix-cloud", "name": "my-crm-app", "plan": "bc-medium", "region": "bc-eu-central" }'

# The response contains data.id, data.next = "deploy", and data.hint.
# Step 2 — upload the code right away, without waiting for CONNECTED
curl -X POST https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/deploy \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": { "content": "<base64-archive>" },
    "runtime": "node20",
    "start": "node index.js",
    "port": 3000
  }'

provider, plan and region are required by the schema for a create without source; for a galaxy app the values are informational — the app inherits its host's plan and region.

Diagnostics and environment variables

  • The provisionError field. If the build or the startup failed, GET /v1/infra/servers/:id returns the failure reason in data.provisionError, and on an image-build failure — also the tail of the Docker build log. Read this field to find the cause.
  • env variables are injected at start. Values from env are passed into the container at start time via docker run --env, not baked into the image. So API keys and secrets from env do not end up in the image layers.

Request fields (body)

Field Type Required Description
provider string yes Provider ID from GET /v1/infra/providers, for example bitrix-cloud. 1–50 characters
name string yes System name of the server — the technical identifier. 2–63 characters, only lowercase Latin letters, digits, and -, with a letter as the first character. Pattern: ^[a-z][a-z0-9-]*$. Used in the subdomain URL (app-<hex> is generated separately), logs, the audit log. Immutable after creation. For a human-readable name, use displayName
displayName string no Human-readable name in any language (Russian, Chinese, emoji — anything). 2–100 characters, no control bytes. Displayed in the UI, server-down notifications, security alerts, billing lines, the Bitrix24 catalog. If not passed — name is substituted. The name itself remains the technical identifier, immutable, and is used in the subdomain URL and logs
description string no Application description shown on the Bitrix24 catalog card, up to 500 characters. Line breaks and tabs are allowed, other control bytes are rejected. The value is trimmed at both ends. If not passed — the description stays empty, and it can be set later via PATCH /v1/infra/servers/:id
plan string yes Plan ID from GET /v1/infra/providers/:providerId/plans, for example bc-small
region string yes Region ID from GET /v1/infra/providers/:providerId/regions, for example bc-eu-central
image string no OS image ID from GET /v1/infra/providers/:providerId/images. If omitted — the platform resolves the provider's current image itself. If you pass it, take the current one from the response: the ID changes when the build is updated
sshPublicKey string no Your SSH public key (ssh-rsa …, ssh-ed25519 …, ecdsa-sha2-nistp256/384/521 …, security keys). Up to 8192 characters. If not passed — the platform will generate a private key and return it once in ssh.privateKey
placement string no Placement model: auto (default) or dedicated. On a Bitrix24 account in Galaxy First mode (galaxies-only), the value dedicated creates a standalone virtual machine instead of a Galaxy application — "graduating" the application onto its own server. It passes the same checks as a normal server create: the serverCreation policy and the per-user server quota. With auto the behavior is unchanged (in Galaxy First mode a Galaxy application is created)
graduateFrom string no The identifier of your Galaxy application (kind=GALAXY_APP) to delete after the dedicated server is created (graduation cleanup — so the old application does not linger in the galaxy). Owner-scoped: the same key, the same Bitrix24 account, kind=GALAXY_APP. A foreign or non-Galaxy identifier returns 404 and deletes nothing. Meaningful only together with placement: dedicated. For a dedicated server, the Idempotency-Key header is not compatible with this parameter — see Idempotency

Note: for the dedicated-virtual-machine model the runtime parameter is not accepted in POST /v1/infra/servers — passing it will return 400 RUNTIME_PARAM_REMOVED. The runtime is installed at the deploy stage. See POST /:id/deploy. Exception — Galaxy mode: when source is passed, runtime is required (see the "Galaxy application" section), and 400 RUNTIME_PARAM_REMOVED is not returned in that case.

Examples

curl — personal key

Terminal
# name — lowercase Latin letters, digits and hyphens only, first character a letter (^[a-z][a-z0-9-]*$)
curl -X POST https://vibecode.bitrix24.com/v1/infra/servers \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "bitrix-cloud",
    "name": "my-crm-app",
    "displayName": "My CRM bot",
    "plan": "bc-small",
    "region": "bc-eu-central",
    "image": "ubuntu-2404-lts"
  }'

curl — OAuth application

Terminal
# name — lowercase Latin letters, digits and hyphens only, first character a letter (^[a-z][a-z0-9-]*$)
curl -X POST https://vibecode.bitrix24.com/v1/infra/servers \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "bitrix-cloud",
    "name": "my-crm-app",
    "displayName": "My CRM bot",
    "plan": "bc-small",
    "region": "bc-eu-central",
    "image": "ubuntu-2404-lts"
  }'

JavaScript — personal key

javascript
// name — lowercase Latin letters, digits and hyphens only, first character a letter (^[a-z][a-z0-9-]*$)
const res = await fetch('https://vibecode.bitrix24.com/v1/infra/servers', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    provider: 'bitrix-cloud',
    name: 'my-crm-app',
    displayName: 'My CRM bot',
    plan: 'bc-small',
    region: 'bc-eu-central',
    image: 'ubuntu-2404-lts',
  }),
})
const { data } = await res.json()
console.log('Server ID:', data.id, 'Subdomain:', data.subdomain)

// Save the SSH credentials just in case — they are returned only once
if (data.ssh.privateKey) {
  await saveLocally(`${data.id}.key`, data.ssh.privateKey)
}

JavaScript — OAuth application

javascript
// name — lowercase Latin letters, digits and hyphens only, first character a letter (^[a-z][a-z0-9-]*$)
const res = await fetch('https://vibecode.bitrix24.com/v1/infra/servers', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    provider: 'bitrix-cloud',
    name: 'my-crm-app',
    displayName: 'My CRM bot',
    plan: 'bc-small',
    region: 'bc-eu-central',
    image: 'ubuntu-2404-lts',
  }),
})

Response fields

Field Type Description
success boolean Always true on success
data.id string (UUID) Unique server identifier
data.status string Always "provisioning" right after creation. Wait for "running" in 1–3 minutes
data.provider string Echo of the passed provider
data.name string Echo of the passed name — the system name of the server
data.kind string Server type, always: STANDALONE or GALAXY_APP
data.galaxyId string Only for the galaxy branch (the galaxy host id); absent from a standalone response
data.displayName string | null Human-readable name. If displayName was not passed at creation — it will equal name
data.description string | null Echo of the passed description. The key is present only in the response for a dedicated virtual machine. For a Galaxy application, where createdVia equals galaxy, the key is absent from the response even though the description is stored — read it via GET /v1/infra/servers/:id
data.ip string | null Public IP. null right after creation, filled in when the virtual machine starts
data.ssh.user string User for SSH: root for new servers
data.ssh.port number SSH port: 22
data.ssh.password string | null One-time! The root password. Save it right away — it will not be returned later. Needed when switching to OPEN mode
data.ssh.privateKey string | null One-time! Private key in OpenSSH format (if sshPublicKey was not passed at creation). Save it right away
data.plan string Echo of the passed plan. Exception — a Galaxy application (createdVia: "galaxy"): the host's plan is returned, not the one requested
data.region string The region the server actually landed in. May differ from the requested one when a zone fallback triggers (see "Known specifics"). For a Galaxy application — the host's region
data.image string Echo of the passed image
data.mode string Always "BLACKHOLE" right after creation
data.createdVia string "api" for calls via the v1 API, "ui" for calls from the Vibecode dashboard
data.subdomain string Subdomain for the application, for example app-92fb1c34. Used in appUrl
data.blackholeStatus string State of the agent tunnel. Right after creation — "NONE", then it passes through WAITING and ends at CONNECTED
data.accessPolicy string Access policy for the application. By default "OWNER_ONLY" — only the key owner
data.runtimeId string | null Always null at creation. Filled in on deploy with runtime
data.runtimeStatus string | null Always null at creation. Updated during deploy
data.appUrl string | null HTTPS address of the application: https://{subdomain}.vibecode.bitrix24.com
data.createdAt string (ISO 8601) Creation timestamp

Response example

A dedicated virtual machine:

JSON
{
  "success": true,
  "data": {
    "id": "db008c84-91a5-4e15-b9d5-6c6aa2838448",
    "status": "provisioning",
    "provider": "bitrix-cloud",
    "name": "docs-test-temp",
    "kind": "STANDALONE",
    "ip": null,
    "ssh": {
      "user": "root",
      "port": 22,
      "password": "0FPIIR9EfO2OAeSSMK6bKA",
      "privateKey": "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmU…\n-----END OPENSSH PRIVATE KEY-----\n"
    },
    "plan": "bc-small",
    "region": "bc-eu-central",
    "image": "ubuntu-2404-lts",
    "mode": "BLACKHOLE",
    "createdVia": "api",
    "subdomain": "app-92fb1c34",
    "blackholeStatus": "NONE",
    "accessPolicy": "OWNER_ONLY",
    "runtimeId": null,
    "runtimeStatus": null,
    "appUrl": "https://app-92fb1c34.vibecode.bitrix24.com",
    "createdAt": "2026-04-22T10:50:11.477Z"
  }
}

A Galaxy application via scenario 1 — source was passed, the build runs in the background. There are no ssh or next fields:

JSON
{
  "success": true,
  "data": {
    "id": "7c2b1f08-3a4d-4e91-9b6c-2f5e8a1d0c33",
    "status": "provisioning",
    "provider": "bitrix-cloud",
    "name": "my-crm-app",
    "kind": "GALAXY_APP",
    "galaxyId": "<galaxy-host-id>",
    "displayName": "My CRM bot",
    "ip": null,
    "ssh": null,
    "plan": "bc-medium",
    "region": "bc-eu-central",
    "image": "ubuntu-2404-lts",
    "mode": "BLACKHOLE",
    "createdVia": "galaxy",
    "subdomain": "app-7c2b1f08",
    "blackholeStatus": "NONE",
    "accessPolicy": "OWNER_ONLY",
    "runtimeId": null,
    "runtimeStatus": null,
    "appUrl": "https://app-7c2b1f08.vibecode.bitrix24.com",
    "createdAt": "2026-04-22T10:50:11.477Z"
  }
}

A Galaxy application via scenario 2 — source was not passed, next and hint appear:

JSON
{
  "success": true,
  "data": {
    "id": "7c2b1f08-3a4d-4e91-9b6c-2f5e8a1d0c33",
    "status": "provisioning",
    "provider": "bitrix-cloud",
    "name": "my-crm-app",
    "kind": "GALAXY_APP",
    "galaxyId": "<galaxy-host-id>",
    "displayName": "My CRM bot",
    "ip": null,
    "ssh": null,
    "plan": "bc-medium",
    "region": "bc-eu-central",
    "image": "ubuntu-2404-lts",
    "mode": "BLACKHOLE",
    "createdVia": "galaxy",
    "subdomain": "app-7c2b1f08",
    "blackholeStatus": "NONE",
    "accessPolicy": "OWNER_ONLY",
    "runtimeId": null,
    "runtimeStatus": null,
    "appUrl": "https://app-7c2b1f08.vibecode.bitrix24.com",
    "createdAt": "2026-04-22T10:50:11.477Z",
    "next": "deploy",
    "hint": "This is a galaxy app — POST /v1/infra/servers/:id/deploy with source.content now; it will not reach \"running\" on its own."
  }
}

If a Galaxy application's build failed, GET /v1/infra/servers/:id returns the reason in data.provisionError:

JSON
{
  "success": true,
  "data": {
    "id": "7c2b1f08-3a4d-4e91-9b6c-2f5e8a1d0c33",
    "status": "error",
    "createdVia": "galaxy",
    "provisionError": "Docker build failed: npm ci exited with code 1"
  }
}

Error response example

400 — validation failed (the name starts with an uppercase letter):

JSON
{
  "success": false,
  "error": {
    "code": "INVALID_REQUEST",
    "message": "name: Name must start with a letter and contain only lowercase letters, digits, and hyphens"
  }
}

Errors

HTTP Code Description
400 INVALID_REQUEST Field validation failed (invalid name format, a required field is missing, an invalid SSH key, etc.). The message field contains the specific reason. On a portal that places applications in a galaxy, when the body carries neither source nor the full provider + plan + region tuple, an error.hint object is added (see below)
400 SOURCE_AT_CREATE_GALAXY_ONLY The source field was passed on a portal without Galaxy mode. Upload the code via POST /:id/deploy after creation
400 RUNTIME_PARAM_REMOVED The runtime parameter was passed without source. Specify the runtime in POST /:id/deploy, or pass runtime, start and source together in this same request. On a portal that places applications in a galaxy, an error.hint object is added (see below)
400 UNKNOWN_PARAM The request body has an unknown field (e.g. deployMode instead of placement). details.unknownFields lists the extra fields, details.suggestions proposes the correct name, and details.validParams is the full list of accepted fields
401 MISSING_API_KEY The X-Api-Key header was not passed
401 INVALID_API_KEY Invalid or expired API key
402 COMMERCIAL_PLAN_REQUIRED The Bitrix24 plan is free and the trial period is unavailable (already used). See the Plan and access section
402 TRIAL_EXPIRED The trial was used and has ended
402 TRIAL_PORTAL_LIMIT The portal's server quota on trial was exceeded
402 TRIAL_USER_LIMIT The per-user server quota on trial was exceeded
402 PLAN_NOT_ALLOWED_ON_TRIAL The requested plan is not available during the trial period. error.details.allowedPlans lists the plans the trial gate is configured for; error.details.requestedPlan, when present, echoes the rejected plan
402 ACCOUNT_FROZEN The Vibecode balance is frozen, a top-up is required
403 INFRA_NOT_PERMITTED Infrastructure is disabled on the platform or on the portal
403 SERVER_CREATION_DISABLED Server creation is forbidden by portal policy
403 MAX_SERVERS_REACHED The per-API-key server limit was exceeded. Delete unneeded ones via DELETE or create a new API key
403 WRITE_BLOCKED_READONLY_KEY The key is in read-only mode, but creating a server is a write operation. Switch the key to read and write — see Access mode
403 INFRA_SCOPE_REQUIRED The key lacks the vibe:infra scope — infrastructure management is unavailable. Add the scope or use a key with infrastructure permissions
403 INFRA_FORBIDDEN_FOR_COWORK_KEY The call was made with a Co-work key. Such a key works with data only and does not manage servers. error.details.requiredAction carries the steps for obtaining a key with deploy rights
404 NO_CREDENTIALS The provider is not configured on the platform
502 PROVIDER_ERROR The cloud provider returned an error while creating the virtual machine. The server record is marked as deleted, the quota is not consumed — you can retry immediately. The message field contains the text from the provider
429 RATE_LIMITED The platform's overall request limit was exceeded
503 POOL_EXHAUSTED The service is temporarily overloaded — the database connection pool is exhausted. The response carries retryAfter and a Retry-After header, retry after a few seconds

The full list of common API errors — Errors.

The `error.hint` object

On a Bitrix24 account that places applications in a galaxy, the INVALID_REQUEST and RUNTIME_PARAM_REMOVED errors are extended with an error.hint object. It names the reason for the refusal and gives a ready-made request body. The condition differs between the two codes. For INVALID_REQUEST the hint arrives when the body carries neither source nor the full provider + plan + region tuple. For RUNTIME_PARAM_REMOVED it arrives when runtime is passed without source, even if the tuple is filled in completely. On a Bitrix24 account with dedicated virtual machines there is no hint in either case.

Do not confuse it with data.hint from a successful response: that one is a string about the next step after creating an application via scenario 2, this one is an object inside error.

Field Type Description
error.hint.reason string Why the request was refused
error.hint.recovery string What to change in the request so it succeeds
error.hint.example object A ready-made request body to start from
JSON
{
  "success": false,
  "error": {
    "code": "INVALID_REQUEST",
    "message": "provider: Required; plan: Required; region: Required",
    "hint": {
      "reason": "This portal places new apps on shared galaxy hosts, and the request lacked `source` and the full provider/plan/region tuple.",
      "recovery": "RECOMMENDED: create-and-deploy in ONE call — POST /v1/infra/servers { name, source: { content }, runtime, start }; OMIT provider/plan/region. Two-step also works: pass provider/plan/region (informational for a galaxy — values from GET /v1/infra/providers catalogs) to create an empty slot, then POST /v1/infra/servers/:id/deploy with the source. See GET /v1/me -> deployment.galaxyApp.checklist. For a deliberate dedicated standalone VM pass placement: \"dedicated\" together with provider/plan/region.",
      "example": {
        "name": "<slug>",
        "source": { "content": "<base64 gzip-tar of the app>" },
        "runtime": "node20",
        "start": "node server.js",
        "port": 3000
      }
    }
  }
}

If the body carries placement: "dedicated", the hint is different: it suggests adding provider, plan and region while keeping the dedicated server, instead of moving the application into a galaxy container.

Idempotency

Pass the optional Idempotency-Key header to safely retry creating a standalone server. If the response to the first request is lost (a network drop, a load-balancer timeout), a retry with the same key does not create a second server — it returns the same server the first request created, with status 201 and an Idempotent-Replayed: true response header.

  • The key is a 1–255 character string from [A-Za-z0-9_.:-]. It is scoped to your API key.
  • On a replay the one-time SSH credentials are not re-exposed. In the response body ssh.privateKey and ssh.password are null, and a note field explains this. Keep the credentials from the first create response.
  • The header applies to standalone servers only. On galaxy-placement Bitrix24 accounts a well-formed key is ignored without an error, and the retry protection does not extend to that path.
  • The header is not supported together with graduateFrom for a dedicated server — it returns 400 IDEMPOTENCY_UNSUPPORTED_WITH_GRADUATION.
Status code When
400 INVALID_IDEMPOTENCY_KEY The key fails validation (length or disallowed characters)
400 IDEMPOTENCY_UNSUPPORTED_WITH_GRADUATION The key together with graduateFrom for a dedicated server
409 IDEMPOTENCY_KEY_ALREADY_USED The key was already used for a server that has since been deleted — pick a new key
409 IDEMPOTENCY_CONCURRENT_RETRY A concurrent request with the same key is still in progress — retry shortly

Known specifics

  • Examples of valid and invalid names by the pattern ^[a-z][a-z0-9-]*$:
    • Valid: my-app, bot-1, crm-dashboard.
    • Invalid: My-App (uppercase), bot_1 (underscore), my.app (dot), café (non-ASCII letters).
  • sshPublicKey vs auto-generation. If you pass your own public key — the platform does not generate a private one, and ssh.privateKey in the response will be null. The password in ssh.password is still returned.
  • When region in the response differs from the requested one. The requested zone may have run out of IP addresses (Address space exhausted) — then the platform automatically tries the next zones in the order from GET /v1/infra/providers/:providerId/regions, and records this in the audit log with the SERVER_ZONE_FALLBACK event.
  • Provisioning timeout is 15 minutes. If status stays in provisioning longer, the platform moves the server to error and fills in provisionError and provisionErrorCode. After that, all that remains is to call DELETE and create a new one.
  • The runtime is installed at the deploy stage. The runtime parameter has been removed from POST /v1/infra/servers (it will return 400 RUNTIME_PARAM_REMOVED). Specify runtime in the body of POST /:id/deploy — it will be installed between archive extraction and application start.

See also