For AI agents: markdown of this page — /docs-content-en/infra/servers/activity.md documentation index — /llms.txt
Server activity feed
GET /v1/infra/servers/:id/activity
Returns a timeline of failures and key events for a server: undelivered Bitrix24 events, bot delivery problems, deployments, wake-ups and status changes.
Call this first when an application has stopped working, a bot is silent, a Bitrix24 event did not arrive or a deployment failed: an entry names the cause as a machine-readable code, and an entry about a deployment or a command leads to its outcome. The feed does not record API call errors, events polled by a bot, or successful deliveries, so an empty feed does not prove that events were delivered.
The feed is read by the server owner with a personal key or with the key of their own OAuth application from the same Bitrix24 account, and by a development team member whose role includes server settings, with their own personal key. An OAuth application key reads the feed with the rights of its owner: the session user does not affect access, and the session token can be omitted. Keys issued for a narrow task with their own list of routes (an agent maintenance key, an application external API key, a team member key and an external collaborator key) do not read the feed and get 403 with a code of the form …_KEY_OUT_OF_SCOPE. For everyone else, including a Bitrix24 account administrator without a role in the team, the server responds as if it did not exist.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
Parameterid (path) |
Typestring | Requiredyes | Default— | DescriptionServer ID. List: GET /v1/infra/servers |
Parametercursor (query) |
Typestring | Requiredno | Default— | DescriptionThe nextCursor value from the previous page, unchanged. Not passed for the first page |
Parameterlimit (query) |
Typeinteger | Requiredno | Default50 |
DescriptionEntries per page, from 1 to 100. A value above 100 is capped at 100. Zero, negative, non-numeric and empty values give 400 INVALID_LIMIT |
Parameterseverity (query) |
Typestring | Requiredno | Defaultall | DescriptionSeverities, comma-separated: error, warning, info |
Parameterkind (query) |
Typestring | Requiredno | Defaultall | DescriptionEntry kinds, comma-separated, for example deploy.failed,wake.failed. The list of kinds is in the table below |
Parametersince (query) |
Typestring | Requiredno | Default— | DescriptionAn RFC 3339 date and time with an explicit UTC offset, Z or +03:00, for example 2026-10-06T12:00:00Z. Only entries whose last repetition is not earlier than this moment are returned |
An empty parameter value counts as passed: ?severity= gives 400 INVALID_SEVERITY, not all severities.
Pages. Entries go from newest to oldest by time of first appearance. While the response contains a non-empty nextCursor, pass it unchanged as the cursor parameter in the next request. null means the last page.
Examples
curl — personal key
curl -H "X-Api-Key: YOUR_API_KEY" \
"https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/activity?limit=20"
curl — OAuth application
curl -H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
"https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/activity?limit=20"
JavaScript — personal key
const res = await fetch(
`https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/activity?limit=20`,
{ headers: { 'X-Api-Key': 'YOUR_API_KEY' } }
)
const { data } = await res.json()
for (const e of data.events) {
console.log(e.firstAt, e.severity, e.kind, e.code ?? '', e.count > 1 ? `×${e.count}` : '')
if (e.ref?.type === 'deploy_operation') {
console.log(` details: /v1/infra/servers/${serverId}/operations/${e.ref.id}`)
}
}
JavaScript — OAuth application
const res = await fetch(
`https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/activity?limit=20`,
{
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
},
}
)
const { data } = await res.json()
Response fields
| Field | Type | Description |
|---|---|---|
Fieldsuccess |
Typeboolean | DescriptionAlways true on success |
Fielddata.events |
Typearray | DescriptionFeed entries, from newest to oldest |
Fielddata.events[].id |
Typestring | DescriptionEntry identifier |
Fielddata.events[].kind |
Typestring | DescriptionEntry kind — see the table below |
Fielddata.events[].severity |
Typestring | DescriptionSeverity: error, warning or info |
Fielddata.events[].code |
Typestring | null | DescriptionCause from the closed list for the kind. A value that is not in the list is returned as other |
Fielddata.events[].meta |
Typeobject | null | DescriptionKind details — keys from the table below, no free text |
Fielddata.events[].ref |
Typeobject | null | Description{ type: "deploy_operation", id } on an entry about a deployment or a command that has an operation: its outcome is read through GET /v1/infra/servers/:id/operations/:operationId. On all other entries it is null |
Fielddata.events[].firstAt |
Typestring | DescriptionFirst appearance, ISO 8601 |
Fielddata.events[].lastAt |
Typestring | DescriptionLast repetition, ISO 8601 |
Fielddata.events[].count |
Typenumber | DescriptionHow many times the event occurred in the entry's five-minute window |
Fielddata.nextCursor |
Typestring | null | DescriptionCursor of the next page. null on the last one |
Entry kinds:
kind |
What happened | severity |
code |
meta |
|---|---|---|---|---|
kindportal_event.delivery_paused |
What happenedDelivery of Bitrix24 events to the application is paused | severitywarning |
codenot_connected, http, http_hard, error |
metaretryAt |
kindportal_event.delivery_failed |
What happenedA Bitrix24 event was not delivered | severityerror |
codehttp_NNN — the application's response code, not_connected, no_app_url, park_expired, policy_denied |
metaeventName, attempts |
kindportal_event.subscription_degraded |
What happenedThe Bitrix24 event subscription was moved to degraded mode | severityerror |
codebreaker_trips, max_attempts |
meta— |
kindportal_event.dropped |
What happenedA Bitrix24 event arrived at an inactive subscription and was dropped | severitywarning |
codesubscription_inactive |
metaeventName, subscriptionStatus |
kindbot.delivery_deferred |
What happenedDelivery of an event to the bot was deferred | severitywarning |
codeNO_TUNNEL, AGENT_NOT_CONNECTED, TUNNEL_SEND_FAILED, GATEWAY_ERROR, BACKLOG |
metabotId, eventType |
kindbot.event_dropped |
What happenedAn undelivered bot event was deleted after 72 hours | severityerror |
codeoutbox_ttl_expired |
metabotId |
kindbot.disabled |
What happenedThe bot was disabled | severityerror |
codeAUTH_FAILURES, B24_UNREGISTERED, PORTAL_DELETED, USER_BLOCKED |
metabotId |
kindbot.event_mode_changed |
What happenedThe bot was switched between delivery to an address and polling for events | severitywarning |
codewebhook_to_fetch, fetch_to_webhook |
metabotId, reason |
kinddeploy.succeeded |
What happenedThe deployment completed successfully | severityinfo |
code— | metadurationMs |
kinddeploy.failed |
What happenedThe deployment failed | severityerror |
codethe same code as error.code of the operation outcome, or null — explained in "Known specifics" |
metastep |
kinddeploy.unknown |
What happenedThe deployment outcome is unknown | severitywarning |
code— | metastep |
kindexec.failed |
What happenedThe command did not run | severitywarning |
codefailure code — the same as error.code of the operation outcome, or null |
meta— |
kindwake.succeeded |
What happenedThe server woke up through a blocking wake-up | severityinfo |
code— | metatrigger |
kindwake.failed |
What happenedThe server did not wake up | severityerror |
codewake-up failure code | metatrigger |
kindserver.status_changed |
What happenedThe server status changed | severityerror on transition to error, warning on a balance freeze, info otherwise |
code— | metafrom, to, reason |
meta.trigger — who woke the server: manual, api, deploy, gateway, auto-wake-on-preempt, auto-wake-on-unfreeze, scheduled. meta.from and meta.to are server statuses in lowercase, as in GET /v1/infra/servers/:id. meta.reason of a status change equals billing_freeze when a running server was put to sleep by a balance freeze; otherwise the field is absent.
Response example
{
"success": true,
"data": {
"events": [
{
"id": "0b6f5b0e-3c4d-4a51-9a53-3f1d2c7e8a10",
"kind": "deploy.failed",
"severity": "error",
"code": "DOWNLOAD_HTTP_STATUS",
"meta": {
"step": "download"
},
"ref": {
"type": "deploy_operation",
"id": "cmop1abcdefghijklmnopqrs"
},
"firstAt": "2026-10-06T12:13:32.251Z",
"lastAt": "2026-10-06T12:13:32.251Z",
"count": 1
},
{
"id": "5e2a7c41-9d8b-4f06-8e1a-6b0c4d9f2e33",
"kind": "server.status_changed",
"severity": "info",
"code": null,
"meta": {
"to": "provisioning",
"from": "sleeping"
},
"ref": null,
"firstAt": "2026-10-06T12:13:28.740Z",
"lastAt": "2026-10-06T12:13:28.740Z",
"count": 1
},
{
"id": "a3d9e2f7-6b1c-4e8a-b5d0-7c2f9e4a1b68",
"kind": "server.status_changed",
"severity": "info",
"code": null,
"meta": {
"to": "sleeping",
"from": "running"
},
"ref": null,
"firstAt": "2026-10-06T12:13:28.367Z",
"lastAt": "2026-10-06T12:13:28.367Z",
"count": 1
},
{
"id": "c71f04b2-8e5a-4d93-9f6e-2b8a0d5c3e17",
"kind": "server.status_changed",
"severity": "info",
"code": null,
"meta": {
"to": "running",
"from": "provisioning"
},
"ref": null,
"firstAt": "2026-10-06T12:13:08.096Z",
"lastAt": "2026-10-06T12:13:29.035Z",
"count": 2
}
],
"nextCursor": null
}
}
Error response example
404 — the server does not exist, is unavailable to this key, or the feed is not enabled for the server owner:
{
"success": false,
"error": {
"code": "SERVER_NOT_FOUND",
"message": "Server not found"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| HTTP400 | CodeINVALID_LIMIT |
Descriptionlimit is zero, negative, non-numeric or empty |
| HTTP400 | CodeINVALID_CURSOR |
Descriptioncursor was not obtained from nextCursor or was altered |
| HTTP400 | CodeINVALID_SEVERITY |
Descriptionseverity contains a value other than error, warning, info, or the parameter is empty |
| HTTP400 | CodeINVALID_KIND |
Descriptionkind contains a kind that is not in the kinds table, or the parameter is empty |
| HTTP400 | CodeINVALID_SINCE |
Descriptionsince is not an RFC 3339 date and time or has no UTC offset |
| HTTP401 | CodeMISSING_API_KEY |
DescriptionThe X-Api-Key header was not passed |
| HTTP401 | CodeINVALID_API_KEY |
DescriptionThe key is not recognized |
| HTTP401 | CodeINVALID_SESSION |
DescriptionAn OAuth application key was passed with a session token that is not recognized or has expired |
| HTTP403 | CodeSESSION_APP_MISMATCH |
DescriptionThe session token was issued to a different application or for a different portal than the OAuth application key in X-Api-Key |
| HTTP403 | CodeAGENT_MAINTENANCE_KEY_OUT_OF_SCOPE |
DescriptionThe request was made with an agent maintenance key: it has its own list of routes |
| HTTP403 | CodeAPP_API_KEY_OUT_OF_SCOPE |
DescriptionThe request was made with an application external API key: it has its own list of routes |
| HTTP403 | CodeEXTERNAL_COLLABORATOR_KEY_OUT_OF_SCOPE |
DescriptionThe request was made with an external collaborator key: it has its own list of routes |
| HTTP403 | CodePORTAL_COLLABORATOR_KEY_OUT_OF_SCOPE |
DescriptionThe request was made with a team member key. A team member reads the feed with their personal key |
| HTTP403 | CodeSERVER_ROLE_FORBIDDEN |
DescriptionYou are on the server's development team, but the role does not include server settings |
| HTTP404 | CodeSERVER_NOT_FOUND |
DescriptionThe server does not exist, was deleted, is unavailable to this key, or the feed is not enabled for the server owner. The cases are intentionally indistinguishable |
| HTTP429 | CodeRATE_LIMITED |
DescriptionThe limit of 60 requests per minute per key was exceeded. The exact value is in the x-ratelimit-limit header |
The full list of common API errors is in Errors.
Known specifics
- A repeat does not create a new entry. Identical server events within one five-minute window are merged into one entry:
countgrows andlastAtmoves. Windows are aligned to five-minute UTC boundaries: 12:10–12:15, 12:15–12:20 and so on. The entry does not move to the top of the feed; the order is kept byfirstAt, so paging throughnextCursorhas no gaps or repeats, even if the server keeps failing while you read the feed. The exception is a status change inside a long operation, see below. firstAtis the moment of writing to the feed, not of the event itself. An entry appears a few seconds after the event: the deployment in the response example finished at 12:13:28, and its entry is dated 12:13:32.- A wake-up is visible through status changes. A sleeping standalone virtual machine wakes through the chain
sleeping→provisioning→running, while a Galaxy application goes straight fromsleepingtorunning. Awake.succeededentry appears only after a blocking wake-up that waited for the server to come up. A non-blocking wake-up leaves only status changes in the feed. - The code in a deployment entry is not the top-level code of the deployment response. The response of
POST /deploycarrieserror.code: "DEPLOY_FAILED"when a step fails, and the step cause inerror.causeCode. Adeploy.failedentry carries the same code aserror.codeof the operation outcome: the step cause if it is known, for exampleDOWNLOAD_HTTP_STATUSwhen a download fails,DEPLOY_STEP_FAILEDif the step failed without a named cause, andDEPLOY_FAILEDon a failure of the platform itself. - The deployment error text is not stored in the feed, only the code. The message and the step are read by
ref.idthroughGET /v1/infra/servers/:id/operations/:operationId, while the platform retains the outcome (7 days). - History depth. Entries are kept for 30 days. Status changes are recorded for every server. Other entries are recorded from the moment the feed was enabled for the server owner, so for a while after that the history can be shorter than 30 days.
- A status change can appear below an already read page if the status changed inside a long platform operation: the entry carries the start time of that operation. The next read of the feed from the first page will show it.
- The feed belongs to the server. After a server is transferred to another owner, the new owner sees the entries made before the transfer, and the previous one gets
404.