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

Deploy outcome

GET /v1/infra/operations/:operationId

Returns the outcome of one specific deploy by its operation id. Use it when the connection to POST /deploy dropped and the terminal response never reached the client: the id tells you how the run ended instead of forcing a blind redeploy.

The endpoint is read-only and has no side effects. Every deploy is addressable on its own, including earlier attempts on the same server. Outcomes are kept for 7 days.

Both deploy kinds receive an id, but at different points:

  • for a standalone virtual machine (kind: "STANDALONE"), the record is opened before the pipeline, the header arrives immediately, and SSE also carries the id in its first frame;
  • for a Galaxy application (kind: "GALAXY_APP"), the record is opened after the application mutex is acquired, on entry to the first step. The id arrives only with the terminal JSON response, in the header and body. If the connection dropped earlier, find the run through the server operation list.

Where the id comes from — three channels, all carried by the same deploy:

  • the X-Vibe-Operation-Id response header — immediate on a standalone machine, terminal-response-only for a Galaxy application;
  • the first event: operation frame with ?stream=true — standalone only; a browser EventSource does not expose response headers, so this is its only early channel;
  • the operationId field in the body — data.operationId on success, error.operationId on failure.

A missing id does not mean the deploy never started. For a Galaxy application, the connection may have dropped before the terminal response; the platform may also have failed to open a record, in which case the deploy continues without an id. Do not redeploy blindly: first call GET /v1/infra/servers/:id/operations, then reconcile the server state and logs.

Parameters

Parameter In Type Required Description
operationId path string yes Operation ID from the POST /deploy response

Examples

curl — personal key

Terminal
curl -H "X-Api-Key: YOUR_API_KEY" \
  https://vibecode.bitrix24.com/v1/infra/operations/OPERATION_ID

curl — OAuth application

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

JavaScript — personal key

javascript
// Deploy: take the id from the header BEFORE the body arrives
const deploy = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/deploy`,
  {
    method: 'POST',
    headers: { 'X-Api-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
    body: JSON.stringify({ source: { content: archiveBase64 }, start: 'node index.js' }),
  }
)
const operationId = deploy.headers.get('X-Vibe-Operation-Id')

// The connection dropped — ask for the outcome instead of redeploying
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/operations/${operationId}`,
  { headers: { 'X-Api-Key': 'YOUR_API_KEY' } }
)

if (res.status === 410) {
  console.log('The operation existed, its outcome is no longer stored')
} else if (res.status === 404) {
  console.log('No such operation')
} else {
  const { data } = await res.json()
  console.log(`Status: ${data.status}, step: ${data.step}`)
}

JavaScript — OAuth application

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

Response fields

Field Type Description
success boolean Always true on success
data.operationId string Operation ID
data.kind string Operation kind. Currently always deploy
data.serverId string ID of the server the deploy ran on
data.status string running, succeeded, failed or unknown — see the table below
data.step string | null Pipeline step the operation is on, or stopped at
data.startedAt string Start time, ISO 8601
data.finishedAt string | null Finish time, ISO 8601. null while the operation is running
data.error object | null { code, message } when status: "failed", otherwise null

Values of data.status:

Value Meaning
running The deploy is in progress right now
succeeded The deploy finished successfully
failed The deploy failed, the reason is in data.error
unknown The platform cannot prove the remote outcome: the transport was lost or the process died between the start and the outcome write. Not the same as "there was no deploy": the operation definitely ran. Check the current server state in GET /v1/infra/servers/:id

Response example

Deploy in progress:

JSON
{
  "success": true,
  "data": {
    "operationId": "clz9k2m4x0001qw8h3f7d2n5p",
    "kind": "deploy",
    "serverId": "8f14e45f-ceea-467a-9c8d-2f1c5a6b7e30",
    "status": "running",
    "step": "install",
    "startedAt": "2026-08-11T09:14:22.117Z",
    "finishedAt": null,
    "error": null
  }
}

Deploy finished successfully:

JSON
{
  "success": true,
  "data": {
    "operationId": "clz9k2m4x0001qw8h3f7d2n5p",
    "kind": "deploy",
    "serverId": "8f14e45f-ceea-467a-9c8d-2f1c5a6b7e30",
    "status": "succeeded",
    "step": null,
    "startedAt": "2026-08-11T09:14:22.117Z",
    "finishedAt": "2026-08-11T09:18:04.902Z",
    "error": null
  }
}

Deploy failed:

JSON
{
  "success": true,
  "data": {
    "operationId": "clz9k2m4x0001qw8h3f7d2n5p",
    "kind": "deploy",
    "serverId": "8f14e45f-ceea-467a-9c8d-2f1c5a6b7e30",
    "status": "failed",
    "step": "healthcheck",
    "startedAt": "2026-08-11T09:14:22.117Z",
    "finishedAt": "2026-08-11T09:17:41.338Z",
    "error": {
      "code": "DEPLOY_STEP_FAILED",
      "message": "connect ECONNREFUSED 127.0.0.1:3000"
    }
  }
}

Error response example

410 — the operation existed, but its outcome is no longer stored:

JSON
{
  "success": false,
  "error": {
    "code": "OPERATION_OUTCOME_EXPIRED",
    "message": "The outcome of this deploy is no longer stored (kept for 7 days).",
    "serverId": "8f14e45f-ceea-467a-9c8d-2f1c5a6b7e30",
    "startedAt": "2026-07-30T11:02:19.400Z"
  }
}

Errors

HTTP Code Description
400 INVALID_OPERATION_ID The ID is not in the format the platform hands out
401 MISSING_API_KEY The X-Api-Key header is missing
401 INVALID_API_KEY Invalid or expired API key
404 OPERATION_NOT_FOUND No such operation, it belongs to a different key, or the record has been removed
410 OPERATION_OUTCOME_EXPIRED The operation is yours, but its outcome is no longer stored
429 RATE_LIMITED Polling limit exceeded

The full list of common API errors — Errors.

Known specifics

  • Someone else's operation answers exactly like a non-existent one, and that is deliberate. All three cases (no such id, an id belonging to another key, a removed record) return the same 404. A distinct answer for someone else's operation would confirm that the id exists, and the id is itself the access key to the record: guessing one would let you read someone else's deploy.
  • 410 differs from 404 only for the owner. "The outcome is no longer stored" appears when the operation is yours and definitely ran, more than 7 days ago. An id that belongs to someone else, or a made-up one, never receives that answer.
  • The record outlives the outcome. After 7 days the outcome stops being served, but the fact that the operation existed is kept for a while longer — that is what makes the distinguishable 410 possible at all. The record is removed afterwards, and the same id starts answering 404.
  • unknown is an answer, not an error. The operation definitely ran, but a transport or process loss means the platform does not know how it ended. Reconcile the current server state and logs first; redeploy only after that check.
  • The polling limit is 60 requests per minute per key. An outcome does not change faster than the deploy itself, so polling every few seconds is enough.

See also