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

Publish the app to the Bitrix24 catalog

POST /v1/infra/servers/:id/b24-catalog/publish

Creates the app card in the Vibecode apps catalog on the Bitrix24 account. Before this call the card appeared only after a successful deployment, so an app brought up any other way was missing from the catalog, and granting access to employees did not surface it.

Editing the access policy or the access list does not create a card — it updates an existing one. Publishing stays a separate action: the card appears in the catalog for the owner and for the employees who already have access.

This is not REST app publishing and not an interface placement — those are POST /v1/apps/:id/publish and placements.

Parameters

Parameter In Type Req. Default Description
id path string (UUID) yes ID of a server that has no catalog card yet

The request body may be empty or {}. Unknown fields are ignored.

Examples

curl — personal key

Terminal
curl -X POST -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" -d '{}' \
  https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/b24-catalog/publish

curl — OAuth application

Terminal
curl -X POST -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" -d '{}' \
  https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/b24-catalog/publish

JavaScript — personal key

javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/b24-catalog/publish`,
  {
    method: 'POST',
    headers: { 'X-Api-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
    body: '{}',
  }
)
const body = await res.json()
if (!body.success) {
  // CATALOG_ALREADY_PUBLISHED means the card is already there — do not repeat
  console.error(body.error.code, body.error.message)
  throw new Error(body.error.code)
}
// The card appears in the catalog after the next synchronization cycle
console.log('Publication queued')

JavaScript — OAuth application

javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/b24-catalog/publish`,
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
      'Content-Type': 'application/json',
    },
    body: '{}',
  }
)

Response fields

Field Type Description
success boolean true when the publication is accepted
data.queued boolean true — the publication is queued. The card is created by background synchronization, not by this call
data.op string The queued operation. For this endpoint it is always ADD

The publication state is read through GET /v1/infra/servers/:id in the b24CatalogSync block:

Field Type Description
b24CatalogSync.itemId number | null ID of the card in the Bitrix24 catalog. null — there is no card. This is the "published" signal, the other fields describe the process
b24CatalogSync.status string IDLE — queued or nothing to synchronize, PENDING — being processed, SYNCED — the card is synchronized, FAILED — synchronization did not succeed, ORPHANED — the card was removed on the Bitrix24 side
b24CatalogSync.pendingOp string | null The queued operation: ADD, UPDATE, DELETE. null — the queue is empty
b24CatalogSync.attempts number Number of synchronization attempts for the current operation
b24CatalogSync.eligible boolean false when a card is impossible: the server has no subdomain, no app has been deployed to it yet, it is an agent runtime or a galaxy host, it was switched to OPEN mode, it has no managing key or account, or catalog synchronization is switched off on the platform side. With false the publish call answers 400 CATALOG_NOT_ELIGIBLE

A value of eligible: true means "a card is possible", not "publishing will succeed": for an app whose card already exists the call answers 409 CATALOG_ALREADY_PUBLISHED.

Response example

JSON
{
  "success": true,
  "data": {
    "queued": true,
    "op": "ADD"
  }
}

Error response example

409 — the catalog card already exists:

JSON
{
  "success": false,
  "error": {
    "code": "CATALOG_ALREADY_PUBLISHED",
    "message": "This server already has a Bitrix24 catalog card."
  }
}

Errors

HTTP Code Description
401 MISSING_API_KEY The X-Api-Key header is missing
401 INVALID_API_KEY The API key is wrong or expired
400 CATALOG_NOT_ELIGIBLE A card is impossible for this server: no subdomain, no app deployed yet, an agent runtime or a galaxy host, the server is in OPEN mode, it has no managing key or account, or catalog synchronization is switched off on the platform side
400 CATALOG_ORPHANED The card was removed on the Bitrix24 side. Restoring it is available in the Vibecode dashboard, not on this endpoint
403 INFRA_FORBIDDEN_FOR_COWORK_KEY The call was made with a Cowork/Code key — such a key works with data only and cannot perform write operations. To issue a key that can, see Project key for deploy
409 CATALOG_ALREADY_PUBLISHED The card already exists. There is no need to repeat the call
409 CATALOG_DELETE_PENDING A catalog delete is already queued — publishing is unavailable in this state
404 NOT_FOUND The server is deleted or managed by another API key
429 RATE_LIMITED Request limit exceeded. The response carries a Retry-After header with the recommended pause

The full list of shared API errors — Errors.

Known specifics

  • The call queues a task instead of creating the card. The card is created by background synchronization, so itemId in GET /v1/infra/servers/:id is not filled at response time. Track readiness by polling: b24CatalogSync.itemId stops being null and status becomes SYNCED.
  • Repeating the call while the publication is queued is safe. The answer is 200 again and no second card is created.
  • A managing key is required. Publishing runs on behalf of the owner of the server's managing key, so a server that lost its key answers 400 CATALOG_NOT_ELIGIBLE. The key is restored in your Vibecode account.
  • Granting access does not create the card. The order is: publish first, then the access policy and the access list. The reverse order also works — after publishing, the card picks up the access already granted on the first synchronization.
  • Deploy first, publish second. The subdomain is minted when the server is created, and an app only appears on it after a deploy, so a server with no deploy on record returns eligible: false and the call answers 400 CATALOG_NOT_ELIGIBLE. Otherwise the catalog card would lead to an address where nothing answers, and the only way to remove it would be to delete the server. The platform also holds no deploy record when the app arrived not through deploy but via a file upload, a command or SSH — such a server gets 400 CATALOG_NOT_ELIGIBLE too, even though the app is running on it. The only way around is a real deploy, and by default (cleanDeploy) it wipes the app directory, so save whatever is already there first.
  • Catalog synchronization can be switched off on the platform side. In that state eligible comes back false and the publish call answers 400 CATALOG_NOT_ELIGIBLE: nothing would process the queue, so the platform refuses up front instead of leaving the card "being added" indefinitely.

See also