Для AI-агентов: markdown этой страницы — /docs-content/applications/list.md индекс документации — /llms.txt

Список приложений

GET /v1/applications

Возвращает приложения портала, которые видит владелец ключа, — свои, открытые коллегами или всё вместе. Выборка постраничная, набор полей строки совпадает с карточкой приложения.

Параметры

Параметр Тип Обяз. По умолч. Описание
scope (query) string нет feed Какие приложения вернуть: mine — свои, shared — доступные вам чужие, feed — общий список из первых двух. Значения регистрозависимы, а пустое scope= отвечает 400 INVALID_SCOPE наравне с неизвестным: параметр либо опускают, либо задают одним из трёх значений
page (query) number нет 1 Номер страницы, считая с единицы. Значение меньше единицы и нечисловое читаются как 1
limit (query) number нет 50 Сколько приложений на странице, максимум 100. Большее значение приводится к 100, 0 и нечисловое — к 50, отрицательное — к 1

Постраничный обход строится по total, page и limit из ответа: страницы запрашиваются подряд, пока сумма полученных строк не догонит total. Страница за пределами выдачи отвечает 200 с пустым массивом data, а не ошибкой.

Считать число страниц как total / limit можно только при truncated: false. При true total перестаёт быть полным числом, страниц за ним нет, и за остатком идут в mine и shared — у них предела нет.

Примеры

curl — личный ключ

Terminal
curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://vibecode.bitrix24.tech/v1/applications?scope=mine&limit=20"

curl — OAuth-приложение

Terminal
curl -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  "https://vibecode.bitrix24.tech/v1/applications?scope=mine&limit=20"

JavaScript — личный ключ

javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/applications?scope=mine&limit=20', {
  headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})
const { data: applications, total } = await res.json()

applications.forEach(app => {
  const state = app.activeOperation
    ? `${app.activeOperation.kind} — ${app.activeOperation.status}`
    : app.server?.status ?? 'сервера нет'
  console.log(`${app.name}: ${state}`)
})
console.log(`Показано ${applications.length} из ${total}`)

JavaScript — OAuth-приложение

javascript
const res = await fetch('https://vibecode.bitrix24.tech/v1/applications?scope=mine&limit=20', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})
const { data: applications, total } = await res.json()

Поля ответа

Поле Тип Описание
success boolean Всегда true при успехе
data array Массив приложений. Элемент массива и data одной карточки — одна и та же форма, её поля разобраны в Карточке приложения
total number Сколько приложений попало под запрошенный scope. У feed это размер выборки, а не число приложений портала — прежде чем считать по нему страницы, читайте truncated
page number Номер выданной страницы, уже приведённый к допустимому значению
limit number Размер страницы, уже приведённый к допустимому значению
truncated boolean Урезана ли выдача. Приходит всегда, в любом scope. falsetotal точное число. truetotal это размер выборки, а не «сколько есть», и страниц за ним нет

Пример ответа

JSON
{
  "success": true,
  "data": [
    {
      "id": "cmsw806qp0001tdskzf6mitka",
      "name": "Черновик без сервера",
      "description": null,
      "type": "PERSONAL",
      "iconUrl": null,
      "createdAt": "2026-08-16T19:51:18.817Z",
      "updatedAt": "2026-08-16T19:51:18.817Z",
      "viewerState": "owner",
      "pinned": false,
      "author": { "name": "Автор приложений" },
      "isEmbedded": true,
      "openUrl": null,
      "openTarget": null,
      "server": null,
      "sources": { "hasVersions": false, "latestVersionId": null, "latestSavedAt": null },
      "activeOperation": null
    },
    {
      "id": "cmsw806qi0000tdskiw2aegii",
      "name": "Отчёт по сделкам",
      "description": "Сводка по воронке за период",
      "type": "PERSONAL",
      "iconUrl": null,
      "createdAt": "2026-08-16T19:51:18.810Z",
      "updatedAt": "2026-08-16T19:51:18.810Z",
      "viewerState": "owner",
      "pinned": false,
      "author": { "name": "Автор приложений" },
      "isEmbedded": false,
      "openUrl": "https://app-05b67cf7.vibecode.bitrix24.tech",
      "openTarget": "app",
      "server": {
        "id": "5cbb50f9-f95f-4ddf-ba3b-b771209cb6fb",
        "status": "RUNNING",
        "url": "https://app-05b67cf7.vibecode.bitrix24.tech",
        "kind": "STANDALONE",
        "reachable": true,
        "lastDeployedAt": "2026-08-16T19:50:41.302Z"
      },
      "sources": {
        "hasVersions": true,
        "latestVersionId": "v2",
        "latestSavedAt": "2026-08-16T19:41:18.818Z"
      },
      "activeOperation": {
        "kind": "deploy",
        "status": "running",
        "step": "build",
        "startedAt": "2026-08-16T19:50:33.822Z"
      }
    }
  ],
  "total": 2,
  "page": 1,
  "limit": 50,
  "truncated": false
}

Пример ответа при ошибке

400 — значение scope вне допустимого набора:

JSON
{
  "success": false,
  "error": {
    "code": "INVALID_SCOPE",
    "message": "scope must be one of: mine, shared, feed"
  }
}

Ошибки

HTTP Код Описание
400 INVALID_SCOPE Значение scope вне набора mine, shared, feed. Сюда же попадают пустое значение и другой регистр
401 NO_PORTAL Ключ не привязан к порталу — фактический ответ на этот случай
403 MANAGEMENT_KEY_NO_ENTITY_ACCESS Управляющий ключ: нужен API-ключ или ключ авторизации
403 PORTAL_KEY_REQUIRED Страховка раздела: повреждённая запись ключа без владельца. Обычный «ключ без портала» — это 401 NO_PORTAL выше
401 MISSING_API_KEY Не передан заголовок X-Api-Key
401 INVALID_API_KEY Неверный или просроченный API-ключ
429 RATE_LIMITED Превышена частота. 60 запросов в минуту — суммарный лимит платформы, доля одной реплики сегодня 20; ориентируйтесь на X-RateLimit-Limit из ответа. Счётчик на владельца ключа. Лимит строже, чем у карточки: список рассчитан на обновление экрана, а не на опрос в цикле. Есть Retry-After — пауза в целых секундах
429 QUOTA_EXCEEDED Исчерпана суточная квота бесплатных вызовов ключа. Тот же статус, другая причина: ожидание не поможет

Текст error.message всегда английский и предназначен для журналов: тексты для интерфейса стройте по error.code. Полный список общих ошибок API — Ошибки.

Известные особенности

  • Выборка идёт по владельцу ключа, а не по самому ключу. В список попадают и приложения, заведённые в личном кабинете: их серверы привязаны к другим ключам того же человека, поэтому в GET /v1/infra/servers они не видны, а здесь видны. Обратное тоже верно: сменив ключ на новый, вы увидите тот же список приложений.
  • Порядок строк зависит от scope, и он полный. У feed сверху идут закреплённые приложения, за ними свои, затем открытые вам, и внутри каждой группы новее по updatedAt. У mine и shared порядок один — по createdAt, новые сверху. В обоих случаях при равных метках времени порядок доопределяется по id, и это важно для обхода: у приложений, созданных пакетно, метки совпадают, а без вторичного ключа две страницы одного обхода могли бы пересечься или пропустить приложение.
  • У feed выборка ограничена сверху, и об этом говорит truncated. Порядок для этого списка считается на стороне сервиса, а не выборкой из базы, поэтому страница нарезается уже после сортировки, а total показывает размер выборки, а не всего портала. Признак читайте осторожно: он поднимается, когда выборка упёрлась в предел, а отличить «упёрлись» от «ровно столько и было» одним запросом нельзя, поэтому платформа ошибается в сторону признания неполноты. Ложное true вы диагностируете сами — сходите за следующей страницей и получите пустую. Ложное false не диагностируется никак, поэтому его и не допускают. У mine и shared предела нет, total — полное число строк под фильтр, truncated всегда false.
  • updatedAt — не свежесть кода. Поле двигает запись в саму карточку: переименование, смена описания, отвязка удалённого сервера. Выкладка его не двигает, поэтому приложение, куда сегодня выкладывались десять раз, по updatedAt уедет в хвост feed. Свежесть кода — sources.latestSavedAt.
  • В shared и feed сводка исходников почти всегда пустая. Оба блока обогащения наполняются только тому, кто приложением управляет, поэтому у чужих строк sources приходит пустым, а activeOperationnull. Форма строки при этом не меняется, и отличить «данные не отдаются» от «версий нет» по самой строке нельзя. Экран, который рисует статус кода для всей выдачи, обязан это учитывать.
  • Пустой shared — рабочее состояние, а не отказ. Ответ 200 с пустым data и total: 0 означает, что доступных вам чужих приложений нет. Ошибку в этом случае искать негде.
  • requestable в списке не возвращается — ни в одном scope. В выдачу попадают только приложения, которые ваши, доступны вам через политику сервера, открыты вам лично грантом или не имеют сервера и открыты всему порталу. То есть кнопка «запросить доступ» разделу не нужна — и вести её было бы некуда: операций записи здесь нет. Значение requestable существует для полноты набора и приходит только там, где карточка отказывает: 403 FORBIDDEN на прямой запрос чужого закрытого приложения.
  • У scope и viewerState разные границы. В shared попадают не только приложения, доступ к которым открыли лично вам, но и приложения без сервера, открытые всему порталу, — а такая строка приходит с viewerState: "usable", не "shared". Клиент, который отбирает строки по viewerState === "shared", часть выдачи потеряет.

Смотрите также