[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"docs-storage\u002Fupload":3,"docs-tabs-storage\u002Fupload":6},{"content":4,"lastmod":5},"# Загрузка\n\nТри пути загрузки файлов в хранилище: прямая форма для небольших файлов, предподписанный PUT для загрузки из браузера и составная загрузка для крупных файлов.\n\n**Скоуп:** `vibe:storage` | **Базовый URL:** `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1` | **Авторизация:** API-ключ (`X-Api-Key`)\n\n## Операции\n\n- [Прямая загрузка](.\u002Fupload\u002Fdirect.md) — `POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fupload`\n- [Предподписанный URL](.\u002Fupload\u002Fpresigned.md) — `POST \u002Fv1\u002Fstorage\u002Fobjects`\n- [Подтвердить загрузку](.\u002Fupload\u002Fcomplete.md) — `POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fcomplete`\n- [Создать составную загрузку](.\u002Fupload\u002Fmultipart-create.md) — `POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fcreate`\n- [Завершить составную загрузку](.\u002Fupload\u002Fmultipart-complete.md) — `POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fcomplete`\n- [Отменить составную загрузку](.\u002Fupload\u002Fmultipart-abort.md) — `POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fabort`\n\n## Пути загрузки\n\n| Путь | Размер файла | Шагов |\n|---|---|---|\n| **A** | до 10 МБ | 1 |\n| **B** | до 5 ГБ | 3: создать URL → PUT → подтвердить |\n| **C** | до 5 ТБ | 3 + N: создать → N × PUT → завершить |\n\n## Сценарии\n\n**Выбор пути.** Для файлов до 10 МБ используйте путь A — один запрос с полем `file` в форме `multipart\u002Fform-data`. Для файлов от 10 МБ до 5 ГБ из браузера используйте путь B: `POST \u002Fv1\u002Fstorage\u002Fobjects` возвращает предподписанный URL, браузер отправляет файл напрямую через PUT, затем сервер вызывает `\u002Fcomplete`. Для файлов крупнее 100 МБ рекомендуется путь C с параллельными частями от 5 МБ каждая.\n\n**Отмена составной загрузки.** Если загрузка прервана, вызовите `POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fabort` — незавершённые части занимают место до явной отмены или автоматического удаления через 24 часа.\n\n**Видимость при загрузке.** Атрибут `visibility` задаётся один раз при загрузке: `PRIVATE` (по умолчанию) или `PUBLIC`. Для `PUBLIC`-объектов заблокированы типы `text\u002Fhtml`, `application\u002Fjavascript`, `application\u002Fx-javascript`, `image\u002Fsvg+xml` — такой файл вернёт `415 STORAGE_FORBIDDEN_CONTENT_TYPE`.\n\n## Смотрите также\n\n- [Хранилище](\u002Fdocs\u002Fstorage)\n- [Объекты](\u002Fdocs\u002Fstorage\u002Fobjects)\n- [Ключи и авторизация](\u002Fdocs\u002Fkeys-auth)\n","2026-06-16",{"upload\u002Fdirect.md":7,"upload\u002Fpresigned.md":8,"upload\u002Fcomplete.md":9,"upload\u002Fmultipart-create.md":10,"upload\u002Fmultipart-complete.md":11,"upload\u002Fmultipart-abort.md":12},"## Прямая загрузка файла\n\n`POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fupload`\n\nЗагружает файл до 10 МБ одним запросом в формате `multipart\u002Fform-data` — сервер принимает файл и возвращает готовый объект хранилища.\n\n## Поля запроса (body)\n\nТело запроса должно быть в формате `multipart\u002Fform-data`.\n\n| Параметр | Тип | Обяз. | По умолч. | Описание |\n|----------|-----|:-----:|-----------|---------|\n| `file` | file | да | — | Бинарный файл размером не более 10 МБ. MIME-тип определяется из заголовка `Content-Type` части формы. Если заголовок отсутствует, используется `application\u002Foctet-stream` |\n| `key` | string | да | — | Логический ключ объекта: от 1 до 1024 символов, допустимы `a-z`, `A-Z`, `0-9`, `.`, `_`, `\u002F`, `-`. Не начинать с `\u002F` или `.`, не содержать `..` |\n| `visibility` | string | нет | `PRIVATE` | Видимость объекта: `PRIVATE` или `PUBLIC` |\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl -X POST https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fupload \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -F \"file=@avatar.png;type=image\u002Fpng\" \\\n  -F \"key=users\u002F42\u002Favatar.png\" \\\n  -F \"visibility=PRIVATE\"\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -X POST https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fupload \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -F \"file=@avatar.png;type=image\u002Fpng\" \\\n  -F \"key=users\u002F42\u002Favatar.png\" \\\n  -F \"visibility=PRIVATE\"\n```\n\n### JavaScript — личный ключ\n\n```javascript\nconst formData = new FormData()\nformData.append('file', fileInput.files[0])\nformData.append('key', 'users\u002F42\u002Favatar.png')\nformData.append('visibility', 'PRIVATE')\n\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fupload', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n  },\n  body: formData,\n})\n\nif (!res.ok) {\n  const { error } = await res.json()\n  console.error(error.code, error.message)\n  return\n}\nconst { object } = await res.json()\nconsole.log('Object ID:', object.id)\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nconst formData = new FormData()\nformData.append('file', fileInput.files[0])\nformData.append('key', 'users\u002F42\u002Favatar.png')\nformData.append('visibility', 'PRIVATE')\n\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fupload', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n  },\n  body: formData,\n})\n\nconst { object } = await res.json()\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `object.id` | string | Идентификатор объекта |\n| `object.key` | string | Логический ключ объекта |\n| `object.contentType` | string | MIME-тип файла |\n| `object.sizeBytes` | string | Размер файла в байтах (строка) |\n| `object.sha256` | string | SHA-256 хеш файла. При прямой загрузке вычисляется всегда |\n| `object.visibility` | string | Видимость: `PRIVATE` или `PUBLIC` |\n| `object.uploadStatus` | string | Статус загрузки: `COMPLETED` |\n| `object.createdAt` | string | Дата создания (ISO 8601) |\n| `object.deletedAt` | string | Дата удаления или `null` |\n\n## Пример ответа\n\n```json\n{\n  \"object\": {\n    \"id\": \"cmpf9b1gp003omr0zkc0qjojn\",\n    \"key\": \"users\u002F42\u002Favatar.png\",\n    \"contentType\": \"image\u002Fpng\",\n    \"sizeBytes\": \"20480\",\n    \"sha256\": \"10068f1908d45621f11b50a1d23ddc0720a669c15f45a43d883604e7793537cd\",\n    \"visibility\": \"PRIVATE\",\n    \"uploadStatus\": \"COMPLETED\",\n    \"createdAt\": \"2026-05-21T08:56:32.809Z\",\n    \"deletedAt\": null\n  }\n}\n```\n\n## Пример ответа при ошибке\n\n415 — для `PUBLIC`-объектов передан MIME-тип, недопустимый из соображений межсайтового выполнения скриптов:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"STORAGE_FORBIDDEN_CONTENT_TYPE\",\n    \"message\": \"Content-Type text\u002Fhtml is not allowed for PUBLIC objects (XSS-prone)\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|---------|\n| 403 | `STORAGE_SCOPE_REQUIRED` | API-ключу не хватает скоупа `vibe:storage` |\n| 401 | `STORAGE_NO_AUTH_CONTEXT` | Запрос выполнен без авторизации |\n| 400 | `STORAGE_FILE_REQUIRED` | Не передано поле `file` |\n| 400 | `STORAGE_KEY_REQUIRED` | Не передано поле `key` |\n| 400 | `STORAGE_INVALID_KEY` | Значение `key` нарушает правила формата |\n| 400 | `STORAGE_INVALID_VISIBILITY` | Недопустимое значение `visibility` |\n| 400 | `STORAGE_MULTIPART_PARSE_FAILED` | Не удалось разобрать тело запроса как `multipart\u002Fform-data` |\n| 413 | `STORAGE_UPLOAD_TOO_LARGE` | Файл превышает 10 МБ — используйте предподписанный URL |\n| 415 | `STORAGE_FORBIDDEN_CONTENT_TYPE` | Для `PUBLIC`-объектов запрещены типы `text\u002Fhtml`, `application\u002Fjavascript`, `application\u002Fx-javascript`, `image\u002Fsvg+xml` |\n| 402 | `BILLING_INSUFFICIENT` | Недостаточно средств на балансе |\n| 507 | `STORAGE_QUOTA_EXCEEDED` | Исчерпана квота хранилища |\n| 503 | `STORAGE_FEATURE_DISABLED` | Хранилище отключено для портала |\n| 502 | `STORAGE_BUCKET_ERROR` | Ошибка при взаимодействии с хранилищем |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n**Файлы крупнее 10 МБ.** Для файлов от 10 МБ до 5 ГБ используйте [предподписанный URL](\u002Fdocs\u002Fstorage\u002Fupload\u002Fpresigned) (Путь B). Для файлов крупнее 5 ГБ — [составную загрузку](\u002Fdocs\u002Fstorage\u002Fupload\u002Fmultipart-create) (Путь C).\n\n**Проверка типа для `PUBLIC`-объектов.** Проверка выполняется по заявленному `Content-Type` части формы до записи файла — при нарушении запрос отклоняется без обращения к хранилищу.\n\n## Смотрите также\n\n- [Загрузка](\u002Fdocs\u002Fstorage\u002Fupload)\n- [Создать предподписанный URL](\u002Fdocs\u002Fstorage\u002Fupload\u002Fpresigned)\n- [Подтвердить загрузку](\u002Fdocs\u002Fstorage\u002Fupload\u002Fcomplete)\n- [Составная загрузка](\u002Fdocs\u002Fstorage\u002Fupload\u002Fmultipart-create)\n- [Хранилище](\u002Fdocs\u002Fstorage)\n","## Создать предподписанный URL\n\n`POST \u002Fv1\u002Fstorage\u002Fobjects`\n\nПервый шаг загрузки файла от 10 МБ до 5 ГБ — возвращает временный URL, по которому клиент отправляет файл напрямую методом PUT; после отправки вызывается подтверждение загрузки.\n\n## Поля запроса (body)\n\n| Поле | Тип | Обяз. | По умолч. | Описание |\n|------|-----|:-----:|-----------|---------|\n| `key` | string | да | — | Логический ключ объекта: от 1 до 1024 символов, допустимы `a-z`, `A-Z`, `0-9`, `.`, `_`, `\u002F`, `-`; не начинать с `\u002F` или `.`, не содержать `..` |\n| `contentType` | string | да | — | MIME-тип файла; должен совпасть с заголовком `Content-Type` при PUT-запросе на `uploadUrl` |\n| `visibility` | string | нет | `PRIVATE` | Видимость объекта: `PRIVATE` или `PUBLIC` |\n| `sizeBytes` | number | нет | — | Ожидаемый размер файла в байтах; используется как подсказка при проверке квоты, фактический размер фиксируется на шаге подтверждения |\n| `ttlSeconds` | number | нет | `3600` | Срок действия предподписанного URL в секундах: от 60 до 86400 |\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\n# Шаг 1 — получить предподписанный URL\ncurl -X POST https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"key\": \"users\u002F42\u002Freport.pdf\",\n    \"contentType\": \"application\u002Fpdf\",\n    \"visibility\": \"PRIVATE\"\n  }'\n\n# Шаг 2 — отправить файл на полученный uploadUrl\ncurl -X PUT \"https:\u002F\u002Fstorage.example.com\u002Fupload\u002F...\" \\\n  -H \"Content-Type: application\u002Fpdf\" \\\n  --data-binary @report.pdf\n```\n\n### curl — OAuth-приложение\n\n```bash\n# Шаг 1 — получить предподписанный URL\ncurl -X POST https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"key\": \"users\u002F42\u002Freport.pdf\",\n    \"contentType\": \"application\u002Fpdf\",\n    \"visibility\": \"PRIVATE\"\n  }'\n\n# Шаг 2 — отправить файл на полученный uploadUrl\ncurl -X PUT \"https:\u002F\u002Fstorage.example.com\u002Fupload\u002F...\" \\\n  -H \"Content-Type: application\u002Fpdf\" \\\n  --data-binary @report.pdf\n```\n\n### JavaScript — личный ключ\n\n```javascript\n\u002F\u002F Шаг 1 — получить предподписанный URL\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    key: 'users\u002F42\u002Freport.pdf',\n    contentType: 'application\u002Fpdf',\n    visibility: 'PRIVATE',\n  }),\n})\nif (!res.ok) {\n  const { error } = await res.json()\n  console.error(error.code, error.message)\n  return\n}\nconst result = await res.json()\n\n\u002F\u002F Шаг 2 — отправить файл на предподписанный URL\nconst put = await fetch(result.uploadUrl, {\n  method: 'PUT',\n  headers: { 'Content-Type': 'application\u002Fpdf' },\n  body: file, \u002F\u002F File или Blob\n})\nif (!put.ok) throw new Error(`PUT failed: ${put.status}`)\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\n\u002F\u002F Шаг 1 — получить предподписанный URL\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    key: 'users\u002F42\u002Freport.pdf',\n    contentType: 'application\u002Fpdf',\n    visibility: 'PRIVATE',\n  }),\n})\nconst result = await res.json()\n\n\u002F\u002F Шаг 2 — отправить файл на предподписанный URL\nawait fetch(result.uploadUrl, {\n  method: 'PUT',\n  headers: { 'Content-Type': 'application\u002Fpdf' },\n  body: file, \u002F\u002F File или Blob\n})\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `objectId` | string | Идентификатор объекта; передать в [`POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fcomplete`](\u002Fdocs\u002Fstorage\u002Fupload\u002Fcomplete) |\n| `uploadUrl` | string | Предподписанный URL для отправки файла методом PUT |\n| `bucket` | string | Служебное название контейнера |\n| `objectKey` | string | Служебный ключ объекта в хранилище |\n| `expiresAt` | string | Срок действия предподписанного URL (ISO 8601) |\n\n## Пример ответа\n\n```json\n{\n  \"objectId\": \"cmpf9b1gp003omr0zkc0qjojn\",\n  \"uploadUrl\": \"https:\u002F\u002Fstorage.example.com\u002Fupload\u002Fportals\u002Fexample-portal\u002Fusers\u002F42\u002Freport.pdf?X-Amz-Signature=abc123\",\n  \"bucket\": \"example-storage-bucket\",\n  \"objectKey\": \"portals\u002Fexample-portal\u002Fusers\u002F42\u002Freport.pdf\",\n  \"expiresAt\": \"2026-05-21T09:57:43.675Z\"\n}\n```\n\n## Пример ответа при ошибке\n\n400 — `ttlSeconds` вне допустимого диапазона:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"STORAGE_INVALID_TTL\",\n    \"message\": \"ttlSeconds must be between 60 and 86400\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|---------|\n| 403 | `STORAGE_SCOPE_REQUIRED` | API-ключу не хватает скоупа `vibe:storage` |\n| 401 | `STORAGE_NO_AUTH_CONTEXT` | Запрос выполнен без авторизации |\n| 400 | `STORAGE_KEY_REQUIRED` | Не передано поле `key` |\n| 400 | `STORAGE_CONTENT_TYPE_REQUIRED` | Не передано поле `contentType` |\n| 400 | `STORAGE_INVALID_KEY` | Значение `key` нарушает правила формата |\n| 400 | `STORAGE_INVALID_VISIBILITY` | Недопустимое значение `visibility` |\n| 400 | `STORAGE_INVALID_SIZE` | Недопустимое значение `sizeBytes` |\n| 400 | `STORAGE_INVALID_TTL` | `ttlSeconds` вне диапазона 60–86400 |\n| 402 | `BILLING_INSUFFICIENT` | Недостаточно средств на балансе |\n| 507 | `STORAGE_QUOTA_EXCEEDED` | Исчерпана квота хранилища |\n| 503 | `STORAGE_FEATURE_DISABLED` | Хранилище отключено для портала |\n| 503 | `STORAGE_STS_UNAVAILABLE` | Сервис выдачи временных учётных данных недоступен |\n| 502 | `STORAGE_BUCKET_ERROR` | Ошибка при взаимодействии с хранилищем |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n**Обязательный второй шаг.** После отправки файла на `uploadUrl` необходимо вызвать [подтверждение загрузки](\u002Fdocs\u002Fstorage\u002Fupload\u002Fcomplete) с `objectId` из этого ответа. До подтверждения объект находится в статусе `PENDING` и недоступен для скачивания.\n\n**Срок действия URL.** `ttlSeconds` ограничивает срок действия предподписанного URL загрузки, а не срок хранения готового объекта.\n\n## Смотрите также\n\n- [Загрузка](\u002Fdocs\u002Fstorage\u002Fupload)\n- [Прямая загрузка](\u002Fdocs\u002Fstorage\u002Fupload\u002Fdirect)\n- [Подтвердить загрузку](\u002Fdocs\u002Fstorage\u002Fupload\u002Fcomplete)\n- [Составная загрузка](\u002Fdocs\u002Fstorage\u002Fupload\u002Fmultipart-create)\n- [Хранилище](\u002Fdocs\u002Fstorage)\n","## Подтвердить загрузку\n\n`POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fcomplete`\n\nВторой шаг загрузки через предподписанный URL — фиксирует фактический размер и тип файла из хранилища и переводит объект в статус `COMPLETED`.\n\n## Поля запроса (body)\n\n| Поле | Тип | Обяз. | По умолч. | Описание |\n|------|-----|:-----:|-----------|---------|\n| `objectId` | string | да | — | Идентификатор объекта из ответа [`POST \u002Fv1\u002Fstorage\u002Fobjects`](\u002Fdocs\u002Fstorage\u002Fupload\u002Fpresigned) |\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl -X POST https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fcomplete \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"objectId\":\"cmpf9b1gp003omr0zkc0qjojn\"}'\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -X POST https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fcomplete \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"objectId\":\"cmpf9b1gp003omr0zkc0qjojn\"}'\n```\n\n### JavaScript — личный ключ\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fcomplete', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({ objectId: 'cmpf9b1gp003omr0zkc0qjojn' }),\n})\n\nif (!res.ok) {\n  const { error } = await res.json()\n  console.error(error.code, error.message)\n  return\n}\nconst { object } = await res.json()\nconsole.log('Upload complete, key:', object.key)\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fcomplete', {\n  method: 'POST',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({ objectId: 'cmpf9b1gp003omr0zkc0qjojn' }),\n})\n\nconst { object } = await res.json()\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `object.id` | string | Идентификатор объекта |\n| `object.key` | string | Логический ключ объекта |\n| `object.contentType` | string | Фактический MIME-тип файла (зафиксирован из хранилища) |\n| `object.sizeBytes` | string | Фактический размер файла в байтах (строка) |\n| `object.sha256` | string | SHA-256 хеш файла или `null` |\n| `object.visibility` | string | Видимость: `PRIVATE` или `PUBLIC` |\n| `object.uploadStatus` | string | Статус загрузки: `COMPLETED` |\n| `object.createdAt` | string | Дата создания (ISO 8601) |\n| `object.deletedAt` | string | Дата удаления или `null` |\n\n## Пример ответа\n\n```json\n{\n  \"object\": {\n    \"id\": \"cmpf9b1gp003omr0zkc0qjojn\",\n    \"key\": \"users\u002F42\u002Favatar.png\",\n    \"contentType\": \"image\u002Fpng\",\n    \"sizeBytes\": \"20480\",\n    \"sha256\": null,\n    \"visibility\": \"PRIVATE\",\n    \"uploadStatus\": \"COMPLETED\",\n    \"createdAt\": \"2026-05-21T08:56:32.809Z\",\n    \"deletedAt\": null\n  }\n}\n```\n\n## Пример ответа при ошибке\n\n409 — файл не был отправлен на предподписанный URL:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"STORAGE_UPLOAD_NOT_FOUND_IN_BUCKET\",\n    \"message\": \"...\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|---------|\n| 403 | `STORAGE_SCOPE_REQUIRED` | API-ключу не хватает скоупа `vibe:storage` |\n| 401 | `STORAGE_NO_AUTH_CONTEXT` | Запрос выполнен без авторизации |\n| 400 | `STORAGE_OBJECT_ID_REQUIRED` | Не передано поле `objectId` |\n| 404 | `STORAGE_OBJECT_NOT_FOUND` | Объект с указанным `objectId` не найден |\n| 409 | `STORAGE_UPLOAD_NOT_PENDING` | Объект уже подтверждён ранее |\n| 409 | `STORAGE_UPLOAD_NOT_FOUND_IN_BUCKET` | Файл не был отправлен на предподписанный URL |\n| 415 | `STORAGE_FORBIDDEN_CONTENT_TYPE` | Для `PUBLIC`-объектов обнаружен MIME-тип, недопустимый из соображений безопасности; объект удаляется |\n| 503 | `STORAGE_FEATURE_DISABLED` | Хранилище отключено для портала |\n| 503 | `STORAGE_STS_UNAVAILABLE` | Сервис выдачи временных учётных данных недоступен |\n| 502 | `STORAGE_BUCKET_ERROR` | Ошибка при взаимодействии с хранилищем |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n**Проверка типа для `PUBLIC`-объектов.** Фактический MIME-тип определяется из данных хранилища, а не из поля `contentType`, переданного на шаге создания объекта. Запрещены типы `text\u002Fhtml`, `application\u002Fjavascript`, `application\u002Fx-javascript`, `image\u002Fsvg+xml`.\n\n## Смотрите также\n\n- [Загрузка](\u002Fdocs\u002Fstorage\u002Fupload)\n- [Создать предподписанный URL](\u002Fdocs\u002Fstorage\u002Fupload\u002Fpresigned)\n- [Прямая загрузка](\u002Fdocs\u002Fstorage\u002Fupload\u002Fdirect)\n- [Составная загрузка](\u002Fdocs\u002Fstorage\u002Fupload\u002Fmultipart-create)\n- [Хранилище](\u002Fdocs\u002Fstorage)\n","## Создать составную загрузку\n\n`POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fcreate`\n\nОткрывает сессию составной загрузки для файлов до 5 ТБ. Возвращает идентификатор объекта, идентификатор сессии и предподписанные URL для загрузки частей. После загрузки всех частей вызовите [`POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fcomplete`](\u002Fdocs\u002Fstorage\u002Fupload\u002Fmultipart-complete), чтобы собрать объект.\n\n## Поля запроса (body)\n\nТело запроса — JSON.\n\n| Параметр | Тип | Обяз. | По умолч. | Описание |\n|----------|-----|:-----:|-----------|---------|\n| `key` | string | да | — | Логический ключ объекта: от 1 до 1024 символов, допустимы `a-z`, `A-Z`, `0-9`, `.`, `_`, `\u002F`, `-`; не начинать с `\u002F` или `.`, не содержать `..` |\n| `contentType` | string | да | — | MIME-тип файла, например `video\u002Fmp4` или `application\u002Fzip` |\n| `totalSize` | number | да | — | Общий размер файла в байтах; положительное целое число; не более 5 ТБ (5 497 558 138 880 байт) |\n| `partSize` | number | нет | `8388608` | Размер одной части в байтах; от 5 МБ (5 242 880) до 5 ГБ (5 368 709 120); последняя часть может быть меньше минимума |\n| `visibility` | string | нет | `PRIVATE` | Видимость объекта: `PRIVATE` или `PUBLIC` |\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl -X POST https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fcreate \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"key\": \"videos\u002Flecture-01.mp4\",\n    \"contentType\": \"video\u002Fmp4\",\n    \"totalSize\": 209715200\n  }'\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -X POST https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fcreate \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"key\": \"videos\u002Flecture-01.mp4\",\n    \"contentType\": \"video\u002Fmp4\",\n    \"totalSize\": 209715200\n  }'\n```\n\n### JavaScript — личный ключ\n\n```javascript\nconst file = fileInput.files[0]\n\n\u002F\u002F Шаг 1 — открыть сессию составной загрузки\nconst createRes = await fetch(\n  'https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fcreate',\n  {\n    method: 'POST',\n    headers: {\n      'X-Api-Key': 'YOUR_API_KEY',\n      'Content-Type': 'application\u002Fjson',\n    },\n    body: JSON.stringify({\n      key: 'videos\u002Flecture-01.mp4',\n      contentType: file.type,\n      totalSize: file.size,\n    }),\n  }\n)\nconst { objectId, parts } = await createRes.json()\n\n\u002F\u002F Шаг 2 — загрузить части параллельно, сохранить ETag из заголовков ответов\nconst PART_SIZE = 8 * 1024 * 1024\nconst uploadedParts = await Promise.all(\n  parts.map(async ({ partNumber, uploadUrl }) => {\n    const start = (partNumber - 1) * PART_SIZE\n    const end = Math.min(start + PART_SIZE, file.size)\n\n    const putRes = await fetch(uploadUrl, {\n      method: 'PUT',\n      body: file.slice(start, end),\n    })\n    const etag = putRes.headers.get('ETag')\n    return { partNumber, etag }\n  })\n)\n\n\u002F\u002F Шаг 3 — завершить сборку объекта\nconst completeRes = await fetch(\n  'https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fcomplete',\n  {\n    method: 'POST',\n    headers: {\n      'X-Api-Key': 'YOUR_API_KEY',\n      'Content-Type': 'application\u002Fjson',\n    },\n    body: JSON.stringify({ objectId, parts: uploadedParts }),\n  }\n)\nconst { object } = await completeRes.json()\nconsole.log('Object ID:', object.id)\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nconst file = fileInput.files[0]\n\nconst createRes = await fetch(\n  'https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fcreate',\n  {\n    method: 'POST',\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n      'Content-Type': 'application\u002Fjson',\n    },\n    body: JSON.stringify({\n      key: 'videos\u002Flecture-01.mp4',\n      contentType: file.type,\n      totalSize: file.size,\n    }),\n  }\n)\nconst { objectId, parts } = await createRes.json()\n\nconst PART_SIZE = 8 * 1024 * 1024\nconst uploadedParts = await Promise.all(\n  parts.map(async ({ partNumber, uploadUrl }) => {\n    const start = (partNumber - 1) * PART_SIZE\n    const end = Math.min(start + PART_SIZE, file.size)\n\n    const putRes = await fetch(uploadUrl, { method: 'PUT', body: file.slice(start, end) })\n    const etag = putRes.headers.get('ETag')\n    return { partNumber, etag }\n  })\n)\n\nconst completeRes = await fetch(\n  'https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fcomplete',\n  {\n    method: 'POST',\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n      'Content-Type': 'application\u002Fjson',\n    },\n    body: JSON.stringify({ objectId, parts: uploadedParts }),\n  }\n)\nconst { object } = await completeRes.json()\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `objectId` | string | Идентификатор объекта в хранилище |\n| `uploadId` | string | Идентификатор сессии составной загрузки |\n| `partCount` | number | Количество частей, рассчитанное из `totalSize` и `partSize` |\n| `parts` | array | Массив описателей частей |\n| `parts[].partNumber` | number | Номер части (начиная с 1) |\n| `parts[].uploadUrl` | string | Предподписанный URL для загрузки части методом `PUT` |\n| `parts[].expiresAt` | string | Срок действия URL (ISO 8601); совпадает со сроком сессии — 24 часа |\n\n## Пример ответа\n\n```json\n{\n  \"objectId\": \"cmpfg012a01aco510mrr6u632\",\n  \"uploadId\": \"00065252B4EA33D1\",\n  \"partCount\": 2,\n  \"parts\": [\n    {\n      \"partNumber\": 1,\n      \"uploadUrl\": \"https:\u002F\u002Fstorage.example.com\u002Fupload?partNumber=1&uploadId=00065252B4EA33D1&...\",\n      \"expiresAt\": \"2026-05-22T12:03:56.398Z\"\n    },\n    {\n      \"partNumber\": 2,\n      \"uploadUrl\": \"https:\u002F\u002Fstorage.example.com\u002Fupload?partNumber=2&uploadId=00065252B4EA33D1&...\",\n      \"expiresAt\": \"2026-05-22T12:03:56.398Z\"\n    }\n  ]\n}\n```\n\n## Пример ответа при ошибке\n\n413 — файл превышает ограничение 5 ТБ:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"STORAGE_OBJECT_TOO_LARGE\",\n    \"message\": \"Object exceeds 5 TB cap\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|---------|\n| 403 | `STORAGE_SCOPE_REQUIRED` | API-ключу не хватает скоупа `vibe:storage` |\n| 401 | `STORAGE_NO_AUTH_CONTEXT` | Запрос выполнен без авторизации |\n| 400 | `STORAGE_INVALID_PATH` | Идентификатор вызывающего содержит недопустимые символы пути |\n| 400 | `STORAGE_KEY_REQUIRED` | Не передано поле `key` |\n| 400 | `STORAGE_INVALID_KEY` | Значение `key` нарушает правила формата |\n| 400 | `STORAGE_CONTENT_TYPE_REQUIRED` | Не передано поле `contentType` |\n| 400 | `STORAGE_INVALID_VISIBILITY` | Недопустимое значение `visibility` |\n| 400 | `STORAGE_INVALID_TOTAL_SIZE` | `totalSize` не является положительным целым числом |\n| 400 | `STORAGE_INVALID_PART_SIZE` | `partSize` выходит за пределы допустимого диапазона (5 МБ – 5 ГБ) или не является положительным целым числом |\n| 413 | `STORAGE_OBJECT_TOO_LARGE` | `totalSize` превышает 5 ТБ |\n| 400 | `STORAGE_TOO_MANY_PARTS` | Рассчитанное количество частей превышает 10 000 — увеличьте `partSize` |\n| 402 | `BILLING_INSUFFICIENT` | Недостаточно средств на балансе |\n| 503 | `STORAGE_FEATURE_DISABLED` | Хранилище отключено для портала |\n| 503 | `STORAGE_STS_UNAVAILABLE` | Служба выдачи временных учётных данных недоступна |\n| 502 | `STORAGE_BUCKET_ERROR` | Ошибка при взаимодействии с хранилищем |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n**Предподписанные URL для частей не требуют заголовков авторизации.** Запросы `PUT` на эти URL отправляются напрямую в хранилище без `X-Api-Key` или `Authorization` — все необходимые учётные данные уже подписаны в самом URL.\n\n**Срок действия сессии — 24 часа.** По истечении срока предподписанные URL становятся недействительными, незагруженные части удаляются автоматически. Для досрочного освобождения ресурсов вызовите [`POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fabort`](\u002Fdocs\u002Fstorage\u002Fupload\u002Fmultipart-abort).\n\n**Файлы меньшего размера.** Для файлов до 10 МБ используйте [прямую загрузку](\u002Fdocs\u002Fstorage\u002Fupload\u002Fdirect) (Путь A). Для файлов до 5 ГБ — [предподписанный URL](\u002Fdocs\u002Fstorage\u002Fupload\u002Fpresigned) (Путь B).\n\n## Смотрите также\n\n- [Загрузка](\u002Fdocs\u002Fstorage\u002Fupload)\n- [Завершить составную загрузку](\u002Fdocs\u002Fstorage\u002Fupload\u002Fmultipart-complete)\n- [Отменить составную загрузку](\u002Fdocs\u002Fstorage\u002Fupload\u002Fmultipart-abort)\n- [Прямая загрузка файла](\u002Fdocs\u002Fstorage\u002Fupload\u002Fdirect)\n- [Хранилище](\u002Fdocs\u002Fstorage)\n","## Завершить составную загрузку\n\n`POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fcomplete`\n\nФинализирует сессию составной загрузки: собирает загруженные части в единый объект хранилища и переводит его в статус `COMPLETED`. Возвращает готовый объект.\n\n## Поля запроса (body)\n\nТело запроса — JSON.\n\n| Параметр | Тип | Обяз. | По умолч. | Описание |\n|----------|-----|:-----:|-----------|---------|\n| `objectId` | string | да | — | Идентификатор объекта, полученный из ответа `\u002Fmultipart\u002Fcreate` |\n| `parts` | array | да | — | Непустой массив описателей частей с номерами и ETag |\n| `parts[].partNumber` | number | да | — | Номер части (целое от 1 до 10 000); должен совпадать с номерами из ответа `\u002Fmultipart\u002Fcreate`; дубликаты не допускаются |\n| `parts[].etag` | string | да | — | Значение заголовка `ETag` из ответа на `PUT`-запрос части; принимается со скобками (`\"abc...\"`) и без |\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl -X POST https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fcomplete \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"objectId\": \"cmpfg012a01aco510mrr6u632\",\n    \"parts\": [\n      { \"partNumber\": 1, \"etag\": \"b315b942673d13dbdd2d866e92b0ec13\" },\n      { \"partNumber\": 2, \"etag\": \"a1b2c3d4e5f678901234567890abcdef\" }\n    ]\n  }'\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -X POST https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fcomplete \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"objectId\": \"cmpfg012a01aco510mrr6u632\",\n    \"parts\": [\n      { \"partNumber\": 1, \"etag\": \"b315b942673d13dbdd2d866e92b0ec13\" },\n      { \"partNumber\": 2, \"etag\": \"a1b2c3d4e5f678901234567890abcdef\" }\n    ]\n  }'\n```\n\n### JavaScript — личный ключ\n\n```javascript\n\u002F\u002F uploadedParts — массив { partNumber, etag }, собранный на шаге PUT-загрузки частей\nconst res = await fetch(\n  'https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fcomplete',\n  {\n    method: 'POST',\n    headers: {\n      'X-Api-Key': 'YOUR_API_KEY',\n      'Content-Type': 'application\u002Fjson',\n    },\n    body: JSON.stringify({\n      objectId: 'cmpfg012a01aco510mrr6u632',\n      parts: uploadedParts,\n    }),\n  }\n)\nconst { object } = await res.json()\nconsole.log('Object ID:', object.id)\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nconst res = await fetch(\n  'https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fcomplete',\n  {\n    method: 'POST',\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n      'Content-Type': 'application\u002Fjson',\n    },\n    body: JSON.stringify({\n      objectId: 'cmpfg012a01aco510mrr6u632',\n      parts: uploadedParts,\n    }),\n  }\n)\nconst { object } = await res.json()\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `object.id` | string | Идентификатор объекта |\n| `object.key` | string | Логический ключ объекта |\n| `object.contentType` | string | MIME-тип файла |\n| `object.sizeBytes` | string | Размер файла в байтах (строка) |\n| `object.sha256` | string | SHA-256 хеш файла или `null` |\n| `object.visibility` | string | Видимость: `PRIVATE` или `PUBLIC` |\n| `object.uploadStatus` | string | Статус загрузки: `COMPLETED` |\n| `object.createdAt` | string | Дата создания (ISO 8601) |\n| `object.deletedAt` | string | Дата удаления или `null` |\n\n## Пример ответа\n\n```json\n{\n  \"object\": {\n    \"id\": \"cmpfg012a01aco510mrr6u632\",\n    \"key\": \"videos\u002Flecture-01.mp4\",\n    \"contentType\": \"video\u002Fmp4\",\n    \"sizeBytes\": \"209715200\",\n    \"sha256\": null,\n    \"visibility\": \"PRIVATE\",\n    \"uploadStatus\": \"COMPLETED\",\n    \"createdAt\": \"2026-05-21T12:03:56.387Z\",\n    \"deletedAt\": null\n  }\n}\n```\n\n## Пример ответа при ошибке\n\n400 — передано неверное количество частей:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"STORAGE_INVALID_PARTS\",\n    \"message\": \"Expected 2 parts, got 1\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|---------|\n| 403 | `STORAGE_SCOPE_REQUIRED` | API-ключу не хватает скоупа `vibe:storage` |\n| 401 | `STORAGE_NO_AUTH_CONTEXT` | Запрос выполнен без авторизации |\n| 400 | `STORAGE_INVALID_PATH` | Идентификатор вызывающего содержит недопустимые символы пути |\n| 400 | `STORAGE_OBJECT_ID_REQUIRED` | Не передано поле `objectId` |\n| 400 | `STORAGE_PARTS_REQUIRED` | Поле `parts` отсутствует или является пустым массивом |\n| 400 | `STORAGE_INVALID_PART` | Элемент массива `parts` содержит недопустимый `partNumber` (не целое в диапазоне 1–10 000, дубликат) или пустой `etag` |\n| 404 | `STORAGE_OBJECT_NOT_FOUND` | Объект с указанным `objectId` не найден или сессия составной загрузки уже завершена |\n| 400 | `STORAGE_INVALID_PARTS` | Количество частей не совпадает с `partCount` из `\u002Fcreate`, либо хранилище отклонило сборку из-за неверных ETag |\n| 503 | `STORAGE_FEATURE_DISABLED` | Хранилище отключено для портала |\n| 503 | `STORAGE_STS_UNAVAILABLE` | Служба выдачи временных учётных данных недоступна |\n| 502 | `STORAGE_BUCKET_ERROR` | Ошибка при взаимодействии с хранилищем |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Смотрите также\n\n- [Загрузка](\u002Fdocs\u002Fstorage\u002Fupload)\n- [Создать составную загрузку](\u002Fdocs\u002Fstorage\u002Fupload\u002Fmultipart-create)\n- [Отменить составную загрузку](\u002Fdocs\u002Fstorage\u002Fupload\u002Fmultipart-abort)\n- [Хранилище](\u002Fdocs\u002Fstorage)\n","## Отменить составную загрузку\n\n`POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fabort`\n\nОтменяет незавершённую сессию составной загрузки: освобождает загруженные части и удаляет запись об объекте. Операция необратима — после отмены восстановить загруженные данные невозможно.\n\n## Поля запроса (body)\n\nТело запроса — JSON.\n\n| Параметр | Тип | Обяз. | По умолч. | Описание |\n|----------|-----|:-----:|-----------|---------|\n| `objectId` | string | да | — | Идентификатор объекта, полученный из ответа `\u002Fmultipart\u002Fcreate` |\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl -X POST https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fabort \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"objectId\": \"cmpfg012a01aco510mrr6u632\"}'\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -X POST https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fabort \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"objectId\": \"cmpfg012a01aco510mrr6u632\"}'\n```\n\n### JavaScript — личный ключ\n\n```javascript\nconst res = await fetch(\n  'https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fabort',\n  {\n    method: 'POST',\n    headers: {\n      'X-Api-Key': 'YOUR_API_KEY',\n      'Content-Type': 'application\u002Fjson',\n    },\n    body: JSON.stringify({ objectId: 'cmpfg012a01aco510mrr6u632' }),\n  }\n)\nconst { aborted } = await res.json()\nconsole.log('Aborted:', aborted) \u002F\u002F true\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nconst res = await fetch(\n  'https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fabort',\n  {\n    method: 'POST',\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n      'Content-Type': 'application\u002Fjson',\n    },\n    body: JSON.stringify({ objectId: 'cmpfg012a01aco510mrr6u632' }),\n  }\n)\nconst { aborted } = await res.json()\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `aborted` | boolean | `true` при успешной отмене |\n\n## Пример ответа\n\n```json\n{\n  \"aborted\": true\n}\n```\n\n## Пример ответа при ошибке\n\n404 — объект не найден или сессия уже завершена:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"STORAGE_OBJECT_NOT_FOUND\",\n    \"message\": \"StorageObject cmpfg012a01aco510mrr6u632 not found\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|---------|\n| 403 | `STORAGE_SCOPE_REQUIRED` | API-ключу не хватает скоупа `vibe:storage` |\n| 401 | `STORAGE_NO_AUTH_CONTEXT` | Запрос выполнен без авторизации |\n| 400 | `STORAGE_INVALID_PATH` | Идентификатор вызывающего содержит недопустимые символы пути |\n| 400 | `STORAGE_OBJECT_ID_REQUIRED` | Не передано поле `objectId` |\n| 404 | `STORAGE_OBJECT_NOT_FOUND` | Объект с указанным `objectId` не найден, не принадлежит текущему вызывающему или сессия уже завершена |\n| 503 | `STORAGE_FEATURE_DISABLED` | Хранилище отключено для портала |\n| 503 | `STORAGE_STS_UNAVAILABLE` | Служба выдачи временных учётных данных недоступна |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n**Незавершённые сессии удаляются автоматически через 24 часа.** Явный вызов `\u002Fabort` освобождает ресурсы немедленно, не дожидаясь автоматической очистки.\n\n## Смотрите также\n\n- [Загрузка](\u002Fdocs\u002Fstorage\u002Fupload)\n- [Создать составную загрузку](\u002Fdocs\u002Fstorage\u002Fupload\u002Fmultipart-create)\n- [Завершить составную загрузку](\u002Fdocs\u002Fstorage\u002Fupload\u002Fmultipart-complete)\n- [Хранилище](\u002Fdocs\u002Fstorage)\n"]