## Агент Диска

Агент Диска ищет файлы и папки на Диске Битрикс24, записывает файлы и проверяет, видны ли объекты пользователю.

**Скоуп:** `disk` | **Базовый URL:** `https://vibecode.bitrix24.tech/v1` | **Авторизация:** `X-Api-Key`, для OAuth-приложения — также `Authorization: Bearer`

Все вызовы выполняются от имени одного пользователя Битрикс24: владельца личного ключа или пользователя сессии OAuth-приложения. Агент видит только то, что доступно этому пользователю.

Что доступно на портале, сообщает [`GET /v1/disk/capabilities`](/docs/disk/capabilities). Вызывайте его первым: поиск, загрузка и синхронизация проверяются каждая своим признаком и не зависят друг от друга.

Запись файла идёт в два шага. Резерв фиксирует, что и куда записать, и выдаёт `operationId`. Загрузка передаёт содержимое по этому `operationId` и пишет в Битрикс24 ровно один раз. Повтор того же запроса не создаёт второй файл, а возвращает уже записанную операцию. Поэтому `operationId` сохраняйте до загрузки, а после сбоя читайте операцию, а не загружайте заново.

ID и размеры в ответах агента — строки. Курсор поиска и списка операций непрозрачен: передавайте его обратно без изменений.

## Быстрый старт

Проверить возможности и найти файлы, в имени которых есть `report`:

```bash
curl https://vibecode.bitrix24.tech/v1/disk/capabilities \
  -H "X-Api-Key: YOUR_API_KEY"

curl -X POST https://vibecode.bitrix24.tech/v1/disk/search \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "query": "report", "type": "file", "limit": 10 }'
```

## Полный пример

Записать текстовый файл в папку и прочитать результат операции. Скрипт для Node.js 18 и новее, ключ — в переменной окружения `VIBE_API_KEY`. ID папки — из [`GET /v1/folders`](/docs/entities/folders/list) или поле `rootFolderId` хранилища из [`GET /v1/storages/:id`](/docs/entities/storages/get).

```javascript
import { createHash, randomUUID } from 'node:crypto'

const API = 'https://vibecode.bitrix24.tech/v1'
const headers = { 'X-Api-Key': process.env.VIBE_API_KEY, 'Content-Type': 'application/json' }

async function call(method, path, body) {
  const res = await fetch(API + path, { method, headers, body: body && JSON.stringify(body) })
  const json = await res.json()
  if (!json.success) throw new Error(`${path}: ${res.status} ${json.error.code}`)
  return json.data
}

// 1. Проверить, что загрузка доступна
const caps = await call('GET', '/disk/capabilities')
if (!caps.save.create) throw new Error('Загрузка новых файлов недоступна этому ключу')

// 2. Зарезервировать загрузку в папку
const folderId = '1'
const name = `report-${Date.now()}.txt`
const bytes = Buffer.from('Отчёт за неделю\n')
const contentHash = createHash('sha256').update(bytes).digest('hex')
const intent = [1, 'create', folderId, contentHash, String(bytes.length), null, name, 'createFail']
const reserve = await call('POST', '/disk/uploads/reserve', {
  reserveRequestId: randomUUID(),
  intent,
  lineage: { kind: 'initial' },
})

// 3. Передать содержимое
const upload = await call('POST', '/disk/uploads', {
  operationId: reserve.operationId,
  intentHash: reserve.intentHash,
  effectiveFilename: name,
  content: bytes.toString('base64'),
  contentHash,
})
console.log('Запись:', upload.application, 'файл', upload.fileId)

// 4. Прочитать операцию позже, например после перезапуска приложения
const op = await call('GET', `/disk/uploads/${reserve.operationId}`)
console.log('Сверка:', op.verification)
```

Результат прогона:

```text
Запись: applied файл 10903
Сверка: matched
```

В рабочем приложении сохраняйте `reserveRequestId`, `intent` и `operationId` в своё хранилище до каждого следующего шага. Тогда после сбоя повтор того же запроса вернёт уже созданную операцию.

## Справочник эндпоинтов

| Метод | Путь | Описание |
|-------|------|----------|
| GET | [`/v1/disk/capabilities`](/docs/disk/capabilities) | Возможности агента Диска на портале |
| POST | [`/v1/disk/search`](/docs/disk/search) | Поиск файлов и папок |
| POST | [`/v1/disk/uploads/reserve`](/docs/disk/uploads-reserve) | Зарезервировать загрузку |
| POST | [`/v1/disk/uploads`](/docs/disk/uploads) | Загрузить содержимое по резерву |
| GET | [`/v1/disk/uploads`](/docs/disk/uploads-list) | Список операций загрузки |
| GET | [`/v1/disk/uploads/:operationId`](/docs/disk/uploads-get) | Операция загрузки |
| POST | [`/v1/disk/sync/check`](/docs/disk/sync-check) | Проверить видимость объектов |

## Коды ошибок

Ошибки агента Диска приходят в конверте `{ "success": false, "error": { "code", "message", "retrySafe" } }`. Поле `message` у них всегда `Disk request unavailable`, поэтому решение принимайте по `code`.

### Ошибки агента Диска

| HTTP | Код | Описание |
|------|-----|----------|
| 400 | `INVALID_PARAMS` | Тело или параметры запроса не прошли проверку |
| 401 | `DISK_AUTH_UNAVAILABLE` | Не удалось подтвердить пользователя Битрикс24 |
| 403 | `DISK_ACCESS_DENIED` | Битрикс24 отказал пользователю в доступе |
| 403, 409 | `DISK_GENERATION_STALE` | Курсор поиска устарел (403) или подключение ключа сменилось во время записи (409) |
| 409 | `DISK_OPERATION_CONFLICT` | Повтор запроса с другим телом или содержимое не совпало с резервом |
| 409 | `DISK_OPERATION_EXPIRED` | Операция не найдена или срок резерва истёк |
| 409 | `DISK_PRIOR_REQUIRED` | Прошлая операция для продолжения или повтора не найдена, не завершена или не подходит по `lineage.kind` |
| 409 | `DISK_OUTCOME_UNKNOWN` | Результат прошлой операции неизвестен, продолжение от неё не принимается |
| 409 | `DISK_VERSION_CONFLICT` | Файл изменился после того, как прочитано его состояние |
| 413 | `DISK_UPLOAD_TOO_LARGE` | Файл больше 25 МиБ |
| 501 | `DISK_UNSUPPORTED` | Портал не поддерживает возможность |
| 502 | `DISK_READ_UNAVAILABLE` | Чтение с портала не удалось |

### Системные ошибки

| HTTP | Код | Описание |
|------|-----|----------|
| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |
| 401 | `TOKEN_MISSING` | У ключа нет подключения к Битрикс24 |
| 403 | `SCOPE_DENIED` | У ключа нет скоупа `disk` |
| 403 | `WRITE_BLOCKED_READONLY` | Ключ в режиме «только чтение» не может загружать файлы |
| 503 | `QUERY_LIMIT_EXCEEDED` | Битрикс24 ограничил частоту запросов |

Условия каждого кода — на страницах эндпоинтов. Полный список общих ошибок — [Ошибки](/docs/errors).

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

- [Файлы](/docs/entities/files)
- [Папки](/docs/entities/folders)
- [Хранилища](/docs/entities/storages)
- [Режим доступа ключа](/docs/keys-auth/access-mode)
- [Ошибки](/docs/errors)
