[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"docs-storage\u002Fobjects":3,"docs-tabs-storage\u002Fobjects":6},{"content":4,"lastmod":5},"# Объекты\n\nОперации с объектами хранилища: список, скачивание, получение метаданных, удаление и публичный доступ.\n\n**Скоуп:** `vibe:storage` | **Базовый URL:** `https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1` | **Авторизация:** API-ключ (`X-Api-Key`); публичные эндпоинты работают без авторизации\n\n## Операции\n\n- [Список объектов](.\u002Fobjects\u002Flist.md) — `GET \u002Fv1\u002Fstorage\u002Fobjects`\n- [Скачать объект](.\u002Fobjects\u002Fget.md) — `GET \u002Fv1\u002Fstorage\u002Fobjects\u002F:key`\n- [Метаданные объекта](.\u002Fobjects\u002Fhead.md) — `HEAD \u002Fv1\u002Fstorage\u002Fobjects\u002F:key`\n- [Удалить объект](.\u002Fobjects\u002Fdelete.md) — `DELETE \u002Fv1\u002Fstorage\u002Fobjects\u002F:key`\n- [Публичное скачивание](.\u002Fobjects\u002Fpublic-get.md) — `GET \u002Fv1\u002Fpublic-storage\u002F:portalId\u002F:objectId`\n- [Публичные метаданные](.\u002Fobjects\u002Fpublic-head.md) — `HEAD \u002Fv1\u002Fpublic-storage\u002F:portalId\u002F:objectId`\n\n## Сценарии\n\n**Получение ссылки для скачивания.** `GET \u002Fv1\u002Fstorage\u002Fobjects\u002F:key` возвращает HTTP 302 с заголовком `Location`. Браузеры следуют перенаправлению автоматически. В серверном коде используйте `redirect: 'manual'` и читайте `response.headers.get('location')`. Ссылка действует 10 минут.\n\n**Список по префиксу.** Параметр `prefix` фильтрует объекты по началу ключа. Например, `prefix=users\u002F42` вернёт все объекты с ключами, начинающимися с `users\u002F42`. Для перехода по страницам используйте `cursor` из предыдущего ответа.\n\n**Ключ в URL.** Символы `\u002F` в ключе необходимо кодировать: `encodeURIComponent('users\u002F42\u002Freport.csv')` возвращает `'users%2F42%2Freport.csv'`. Без кодирования запрос направится по другому пути.\n\n**Публичный доступ.** Объект с `visibility=PUBLIC` доступен по постоянному URL без авторизации. URL формируется из `portalId` (идентификатор портала, не `appId`) и `objectId` — это поле `id` объекта из ответов на создание или список, а не логический ключ.\n\n## Смотрите также\n\n- [Хранилище](\u002Fdocs\u002Fstorage)\n- [Загрузка](\u002Fdocs\u002Fstorage\u002Fupload)\n- [Ключи и авторизация](\u002Fdocs\u002Fkeys-auth)\n","2026-07-07",{"objects\u002Flist.md":7,"objects\u002Fget.md":8,"objects\u002Fhead.md":9,"objects\u002Fdelete.md":10,"objects\u002Fpublic-get.md":11,"objects\u002Fpublic-head.md":12},"## Список объектов\n\n`GET \u002Fv1\u002Fstorage\u002Fobjects`\n\nВозвращает список объектов хранилища с фильтрацией по префиксу ключа и навигацией по курсору. В список попадают только завершённые, не удалённые объекты. Результаты отсортированы от новых к старым.\n\n## Параметры\n\n| Параметр | Тип | По умолч. | Описание |\n|----------|-----|-----------|---------|\n| `limit` | number | `50` | Количество объектов на страницу. Максимум 500; значения выше 500 усекаются без ошибки |\n| `prefix` | string | — | Фильтр по началу ключа. Пример: `prefix=reports\u002F2024` вернёт все объекты, ключи которых начинаются с `reports\u002F2024` |\n| `cursor` | string | — | Курсор для перехода на следующую страницу, полученный из поля `cursor` предыдущего ответа |\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects?limit=10&prefix=reports\u002F2024\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects?limit=10&prefix=reports\u002F2024\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — личный ключ\n\n```javascript\nconst res = await fetch(\n  'https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects?limit=10&prefix=reports%2F2024',\n  { headers: { 'X-Api-Key': 'YOUR_API_KEY' } }\n)\nconst { data, cursor, total } = await res.json()\nconsole.log(`Объектов: ${total}`)\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nconst res = await fetch(\n  'https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects?limit=10&prefix=reports%2F2024',\n  {\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n    },\n  }\n)\nconst { data, cursor, total } = await res.json()\n```\n\n## Поля ответа\n\nОтвет не содержит обёртку `success` — возвращается объект напрямую.\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `data` | array | Массив объектов |\n| `data[].id` | string | Идентификатор объекта (CUID) |\n| `data[].key` | string | Ключ объекта в хранилище |\n| `data[].contentType` | string | MIME-тип содержимого |\n| `data[].sizeBytes` | string | Размер в байтах. Передаётся строкой из-за ограничений JSON на большие числа |\n| `data[].sha256` | string \\| null | SHA-256 хэш содержимого, если был вычислен при загрузке |\n| `data[].visibility` | string | Видимость: `PRIVATE` или `PUBLIC` |\n| `data[].uploadStatus` | string | Статус загрузки. В списке всегда `COMPLETED` |\n| `data[].createdAt` | string | Дата создания в формате ISO 8601 |\n| `data[].deletedAt` | null | Всегда `null` — удалённые объекты в список не попадают |\n| `cursor` | string \\| null | Курсор для следующей страницы. `null`, если объектов больше нет |\n| `total` | number | Общее количество объектов, соответствующих запросу |\n\n## Пример ответа\n\n```json\n{\n  \"data\": [\n    {\n      \"id\": \"cmabcdef1234567890abcdef\",\n      \"key\": \"reports\u002F2024\u002Fannual.pdf\",\n      \"contentType\": \"application\u002Fpdf\",\n      \"sizeBytes\": \"204800\",\n      \"sha256\": null,\n      \"visibility\": \"PRIVATE\",\n      \"uploadStatus\": \"COMPLETED\",\n      \"createdAt\": \"2024-06-15T10:30:00.000Z\",\n      \"deletedAt\": null\n    }\n  ],\n  \"cursor\": null,\n  \"total\": 1\n}\n```\n\n## Пример ответа при ошибке\n\n400 — некорректный `limit`:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"STORAGE_INVALID_LIMIT\",\n    \"message\": \"limit must be a positive integer\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|---------|\n| 400 | `STORAGE_INVALID_LIMIT` | Параметр `limit` не является положительным целым числом |\n| 401 | `MISSING_API_KEY` | API-ключ не передан |\n| 403 | `STORAGE_SCOPE_REQUIRED` | У API-ключа нет скоупа `vibe:storage` |\n\nПолный список общих ошибок — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Смотрите также\n\n- [Объекты](\u002Fdocs\u002Fstorage\u002Fobjects)\n- [Скачать объект](\u002Fdocs\u002Fstorage\u002Fobjects\u002Fget)\n- [Метаданные объекта](\u002Fdocs\u002Fstorage\u002Fobjects\u002Fhead)\n- [Загрузка](\u002Fdocs\u002Fstorage\u002Fupload)\n","## Скачать объект\n\n`GET \u002Fv1\u002Fstorage\u002Fobjects\u002F:key`\n\nВозвращает содержимое объекта или временную ссылку для скачивания. Поведение определяется параметрами запроса: по умолчанию — перенаправление, `?inline=true` — содержимое в теле ответа.\n\n## Параметры\n\n**Путь**\n\n| Параметр | Тип | Описание |\n|----------|-----|---------|\n| `key` | string | Ключ объекта. Символы `\u002F` в ключе необходимо кодировать: `users%2F42%2Favatar.png` |\n\n**Запрос**\n\n| Параметр | Тип | По умолч. | Описание |\n|----------|-----|-----------|---------|\n| `inline` | boolean | `false` | `true` или `1` — вернуть содержимое непосредственно в теле ответа (HTTP 200) вместо перенаправления |\n| `inline_render` | boolean | `false` | Только совместно с `?inline=true`. `true` или `1` — убирает заголовок `Content-Disposition`, браузер отображает файл вместо скачивания |\n| `download` | string | — | Имя файла. При переходе по ссылке браузер предложит сохранить файл с указанным именем |\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl -L \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Freports%2F2024%2Fannual.pdf\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  --output annual.pdf\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -L \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Freports%2F2024%2Fannual.pdf\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  --output annual.pdf\n```\n\n### JavaScript — личный ключ\n\n```javascript\n\u002F\u002F Получить временную ссылку (без следования по перенаправлению)\nconst res = await fetch(\n  'https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Freports%2F2024%2Fannual.pdf',\n  {\n    redirect: 'manual',\n    headers: { 'X-Api-Key': 'YOUR_API_KEY' },\n  }\n)\nconst url = res.headers.get('location') \u002F\u002F временная ссылка, действует 10 минут\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nconst res = await fetch(\n  'https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Freports%2F2024%2Fannual.pdf',\n  {\n    redirect: 'manual',\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n    },\n  }\n)\nconst url = res.headers.get('location')\n```\n\n## Ответ\n\nФормат ответа зависит от параметров запроса.\n\n**По умолчанию — перенаправление**\n\nВозвращает `302 Found` с временной ссылкой в заголовке `Location`. Ссылка действует 10 минут. Браузеры следуют перенаправлению автоматически; в серверном коде используйте `redirect: 'manual'` и читайте `response.headers.get('location')`.\n\n```\nHTTP\u002F1.1 302 Found\nLocation: \u003Cвременная ссылка>\nCache-Control: no-store\n```\n\n**`?inline=true` — содержимое в теле ответа**\n\nВозвращает `200 OK` с содержимым объекта непосредственно в теле ответа. По умолчанию браузер сохраняет файл (заголовок `Content-Disposition: attachment`). Чтобы браузер отобразил файл вместо скачивания, добавьте `&inline_render=true`.\n\n```\nHTTP\u002F1.1 200 OK\nContent-Type: application\u002Fpdf\nContent-Length: 204800\nETag: \"e3b0c44298fc1c149afbf4c8996fb92\"\nX-Content-Type-Options: nosniff\nContent-Disposition: attachment; filename=\"annual.pdf\"\n\n\u003Cсодержимое объекта>\n```\n\n**`?download=\u003Cимя>` — скачивание с заданным именем**\n\nВозвращает `302 Found`. При переходе по ссылке из заголовка `Location` хранилище отдаёт файл с заголовком `Content-Disposition: attachment; filename=\"\u003Cимя>\"`, поэтому браузер предложит сохранить его с указанным именем.\n\n```\nHTTP\u002F1.1 302 Found\nLocation: \u003Cвременная ссылка с указанным именем файла>\nCache-Control: no-store\n```\n\n## Пример ответа при ошибке\n\n404 — объект не найден:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"STORAGE_OBJECT_NOT_FOUND\",\n    \"message\": \"Object reports\u002F2024\u002Fannual.pdf not found\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|---------|\n| 401 | `MISSING_API_KEY` | API-ключ не передан |\n| 403 | `STORAGE_SCOPE_REQUIRED` | У API-ключа нет скоупа `vibe:storage` |\n| 404 | `STORAGE_OBJECT_NOT_FOUND` | Объект с указанным ключом не найден |\n| 410 | `STORAGE_OBJECT_DELETED` | Объект был удалён |\n| 502 | `STORAGE_OBJECT_STREAM_FAILED` | Ошибка при передаче содержимого объекта (только для режима `?inline=true`) |\n\nПолный список общих ошибок — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Смотрите также\n\n- [Объекты](\u002Fdocs\u002Fstorage\u002Fobjects)\n- [Список объектов](\u002Fdocs\u002Fstorage\u002Fobjects\u002Flist)\n- [Метаданные объекта](\u002Fdocs\u002Fstorage\u002Fobjects\u002Fhead)\n- [Загрузка](\u002Fdocs\u002Fstorage\u002Fupload)\n","## Метаданные объекта\n\n`HEAD \u002Fv1\u002Fstorage\u002Fobjects\u002F:key`\n\nВозвращает метаданные объекта в заголовках ответа без тела. Используется для проверки существования объекта и получения его характеристик без загрузки содержимого.\n\n## Параметры\n\n| Параметр | Тип | Описание |\n|----------|-----|---------|\n| `key` | string | Ключ объекта. Символы `\u002F` в ключе необходимо кодировать: `users%2F42%2Favatar.png` |\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl -I \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Freports%2F2024%2Fannual.pdf\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -I \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Freports%2F2024%2Fannual.pdf\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — личный ключ\n\n```javascript\nconst res = await fetch(\n  'https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Freports%2F2024%2Fannual.pdf',\n  {\n    method: 'HEAD',\n    headers: { 'X-Api-Key': 'YOUR_API_KEY' },\n  }\n)\nconst contentType = res.headers.get('content-type')\nconst size = res.headers.get('content-length')\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nconst res = await fetch(\n  'https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Freports%2F2024%2Fannual.pdf',\n  {\n    method: 'HEAD',\n    headers: {\n      'X-Api-Key': 'YOUR_APP_KEY',\n      'Authorization': 'Bearer USER_SESSION_TOKEN',\n    },\n  }\n)\nconst contentType = res.headers.get('content-type')\nconst size = res.headers.get('content-length')\n```\n\n## Ответ\n\nТело ответа отсутствует. Метаданные передаются в заголовках.\n\n| Заголовок | Описание |\n|-----------|---------|\n| `Content-Type` | MIME-тип содержимого объекта |\n| `Content-Length` | Размер объекта в байтах |\n| `ETag` | Хэш содержимого в кавычках |\n\n```\nHTTP\u002F1.1 200 OK\nContent-Type: application\u002Fpdf\nContent-Length: 204800\nETag: \"e3b0c44298fc1c149afbf4c8996fb92\"\n```\n\n## Пример ответа при ошибке\n\n404 — объект не найден:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"STORAGE_OBJECT_NOT_FOUND\",\n    \"message\": \"Object reports\u002F2024\u002Fannual.pdf not found\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|---------|\n| 401 | `MISSING_API_KEY` | API-ключ не передан |\n| 403 | `STORAGE_SCOPE_REQUIRED` | У API-ключа нет скоупа `vibe:storage` |\n| 404 | `STORAGE_OBJECT_NOT_FOUND` | Объект с указанным ключом не найден |\n| 410 | `STORAGE_OBJECT_DELETED` | Объект был удалён |\n| 502 | `STORAGE_OBJECT_HEAD_FAILED` | Ошибка при обращении к хранилищу |\n| 502 | `STORAGE_OBJECT_MISSING_IN_BUCKET` | Объект найден в базе данных, но отсутствует в хранилище |\n\nПолный список общих ошибок — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Смотрите также\n\n- [Объекты](\u002Fdocs\u002Fstorage\u002Fobjects)\n- [Список объектов](\u002Fdocs\u002Fstorage\u002Fobjects\u002Flist)\n- [Скачать объект](\u002Fdocs\u002Fstorage\u002Fobjects\u002Fget)\n- [Загрузка](\u002Fdocs\u002Fstorage\u002Fupload)\n","\n## Удалить объект\n\n`DELETE \u002Fv1\u002Fstorage\u002Fobjects\u002F:key`\n\nПомечает объект как удалённый (мягкое удаление). Поле `deletedAt` объекта заполняется датой удаления; физические байты остаются в хранилище до 30 дней, затем удаляются автоматически. Восстановление объекта через API недоступно.\n\n## Параметры\n\n| Параметр | Тип | Обяз. | Описание |\n|----------|-----|:-----:|---------|\n| `key` (path) | string | да | Логический ключ объекта, URL-кодированный. Для ключей с `\u002F` (например `users\u002F42\u002Favatar.png`) передавать как `users%2F42%2Favatar.png` |\n\n## Примеры\n\n### curl — личный ключ\n\n```bash\ncurl -s -X DELETE \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fdocs-test%2Fverify.txt\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\"\n```\n\n### curl — OAuth-приложение\n\n```bash\ncurl -s -X DELETE \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002Fdocs-test%2Fverify.txt\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\"\n```\n\n### JavaScript — личный ключ\n\n```javascript\nconst key = encodeURIComponent('docs-test\u002Fverify.txt')\nconst res = await fetch(`https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002F${key}`, {\n  method: 'DELETE',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n  },\n})\nconst body = await res.json()\nif (body.object?.deletedAt) {\n  console.log('Объект удалён:', body.object.deletedAt)\n}\n```\n\n### JavaScript — OAuth-приложение\n\n```javascript\nconst key = encodeURIComponent('docs-test\u002Fverify.txt')\nconst res = await fetch(`https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fstorage\u002Fobjects\u002F${key}`, {\n  method: 'DELETE',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n  },\n})\nconst body = await res.json()\nif (body.object?.deletedAt) {\n  console.log('Объект удалён:', body.object.deletedAt)\n}\n```\n\n## Поля ответа\n\n| Поле | Тип | Описание |\n|------|-----|---------|\n| `object.id` | string (CUID) | Внутренний идентификатор объекта |\n| `object.key` | string | Логический ключ |\n| `object.contentType` | string | MIME-тип содержимого |\n| `object.sizeBytes` | string | Размер в байтах (строка из-за ограничений JSON на большие числа) |\n| `object.sha256` | string \\| null | SHA-256 содержимого, если был передан при загрузке |\n| `object.visibility` | string | `PRIVATE` или `PUBLIC` |\n| `object.uploadStatus` | string | Статус загрузки (`COMPLETED`) |\n| `object.createdAt` | string (ISO 8601) | Дата создания |\n| `object.deletedAt` | string (ISO 8601) | Дата удаления — заполнено после успешного удаления |\n\n## Пример ответа\n\n```json\n{\n  \"object\": {\n    \"id\": \"cmpfkc57v0akio510qclwfn7t\",\n    \"key\": \"docs-test\u002Fverify.txt\",\n    \"contentType\": \"text\u002Fplain\",\n    \"sizeBytes\": \"40\",\n    \"sha256\": null,\n    \"visibility\": \"PRIVATE\",\n    \"uploadStatus\": \"COMPLETED\",\n    \"createdAt\": \"2026-05-21T14:05:20.092Z\",\n    \"deletedAt\": \"2026-05-21T14:05:36.880Z\"\n  }\n}\n```\n\n## Пример ответа при ошибке\n\n410 — объект уже удалён (повторный вызов):\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"STORAGE_OBJECT_DELETED\",\n    \"message\": \"Object docs-test\u002Fverify.txt was deleted\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|---------|\n| 400 | `STORAGE_INVALID_KEY` | Ключ содержит недопустимые символы, начинается с `\u002F` или `.`, содержит `..` или превышает 1024 символа |\n| 401 | `MISSING_API_KEY` | Не передан заголовок `X-Api-Key` |\n| 403 | `STORAGE_SCOPE_REQUIRED` | API-ключ не имеет скоупа `vibe:storage` |\n| 404 | `STORAGE_OBJECT_NOT_FOUND` | Объект с таким ключом не найден или принадлежит другому владельцу |\n| 409 | `STORAGE_MULTIPART_IN_PROGRESS` | Объект находится в состоянии незавершённой составной загрузки — сначала вызовите [`\u002Fmultipart\u002Fabort`](\u002Fdocs\u002Fstorage\u002Fupload\u002Fmultipart-abort) |\n| 410 | `STORAGE_OBJECT_DELETED` | Объект уже был удалён ранее |\n| 503 | `STORAGE_STS_UNAVAILABLE` | Временная недоступность сервиса выдачи учётных данных хранилища — повторите запрос |\n| 503 | `STORAGE_FEATURE_DISABLED` | Хранилище временно недоступно на платформе |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n- **Ключи с `\u002F` в пути.** Косая черта в ключе не является разделителем маршрута — передавайте её URL-кодированной. В JavaScript используйте `encodeURIComponent(key)`.\n- **Удалённый объект немедленно недоступен.** GET и HEAD по ключу возвращают `410 STORAGE_OBJECT_DELETED` до истечения 30-дневного периода физического удаления. Запрос списка объектов удалённые объекты не включает.\n\n## Смотрите также\n\n- [Получить объект](\u002Fdocs\u002Fstorage\u002Fobjects\u002Fget) — `GET \u002Fv1\u002Fstorage\u002Fobjects\u002F:key`\n- [Список объектов](\u002Fdocs\u002Fstorage\u002Fobjects\u002Flist) — `GET \u002Fv1\u002Fstorage\u002Fobjects`\n- [Отменить составную загрузку](\u002Fdocs\u002Fstorage\u002Fupload\u002Fmultipart-abort) — `POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fmultipart\u002Fabort`\n- [Публичный доступ GET](\u002Fdocs\u002Fstorage\u002Fobjects\u002Fpublic-get) — `GET \u002Fv1\u002Fpublic-storage\u002F:portalId\u002F:objectId`\n","\n## Публичный доступ к объекту\n\n`GET \u002Fv1\u002Fpublic-storage\u002F:portalId\u002F:objectId`\n\nВозвращает содержимое публично доступного объекта в виде перенаправления (302) на временную ссылку. Ключ API не требуется — эндпоинт анонимный. Анонимный доступ включается на уровне портала отдельно; по умолчанию выключен.\n\n## Параметры\n\n| Параметр | Тип | Обяз. | Описание |\n|----------|-----|:-----:|---------|\n| `portalId` (path) | string (UUID) | да | Идентификатор портала в Вайбкод. Формат: `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`. Получить через `GET \u002Fv1\u002Fme` с ключом управления — поле `data.portals[n].id` |\n| `objectId` (path) | string (CUID) | да | Внутренний идентификатор объекта (поле `id` из ответов на запись и список) |\n\n## Примеры\n\n**Ключ не требуется.** Оба примера отправляются без заголовков авторизации — это анонимный эндпоинт.\n\n### curl\n\n```bash\ncurl -L \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fpublic-storage\u002FYOUR_PORTAL_ID\u002FYOUR_OBJECT_ID\"\n```\n\n### JavaScript\n\n```javascript\nconst res = await fetch(\n  'https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fpublic-storage\u002FYOUR_PORTAL_ID\u002FYOUR_OBJECT_ID',\n  { redirect: 'follow' }\n)\nif (!res.ok) {\n  const body = await res.json()\n  console.error(body.error.code, body.error.message)\n  return\n}\n\u002F\u002F res.url — финальный URL файла\n```\n\n## Ответ\n\nПоведение зависит от состояния анонимного доступа на портале:\n\n**Анонимный доступ включён на портале.** Сервер возвращает `302 Found` с заголовком `Location`, указывающим на временную ссылку хранилища. Ссылка действительна 10 минут. Заголовок ответа: `Cache-Control: private, no-store`.\n\n**Анонимный доступ выключен на портале** (значение по умолчанию для нового портала): `503 STORAGE_PUBLIC_GET_DISABLED_FOR_PORTAL`. Включается администратором портала.\n\n## Пример ответа при ошибке\n\n503 — анонимный доступ выключен на портале:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"STORAGE_PUBLIC_GET_DISABLED_FOR_PORTAL\",\n    \"message\": \"Public storage GET is disabled for this portal\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|---------|\n| 404 | `STORAGE_OBJECT_NOT_FOUND` | Объект не найден, имеет видимость `PRIVATE`, принадлежит другому порталу, или `objectId` не совпадает ни с одним объектом |\n| 410 | `STORAGE_OBJECT_DELETED` | Объект был удалён |\n| 429 | `STORAGE_RATE_LIMIT_EXCEEDED` | Превышен лимит 60 запросов в минуту с одного IP-адреса |\n| 503 | `STORAGE_PUBLIC_GET_DISABLED_FOR_PORTAL` | Анонимный доступ выключен на данном портале |\n| 503 | `STORAGE_FEATURE_DISABLED` | Хранилище временно недоступно на платформе |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n- **Анонимный доступ включается отдельно.** Объект с видимостью `PUBLIC` не становится автоматически доступным через этот эндпоинт — администратор портала должен включить анонимный доступ в настройках хранилища.\n- **`objectId` — внутренний идентификатор, не логический ключ.** Используйте поле `id` из ответа на загрузку ([`POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fupload`](\u002Fdocs\u002Fstorage\u002Fupload)) или из [списка объектов](\u002Fdocs\u002Fstorage\u002Fobjects\u002Flist).\n- **Не кешируйте адрес перенаправления** — новая временная ссылка формируется при каждом запросе.\n\n## Смотрите также\n\n- [Публичный доступ HEAD](\u002Fdocs\u002Fstorage\u002Fobjects\u002Fpublic-head) — `HEAD \u002Fv1\u002Fpublic-storage\u002F:portalId\u002F:objectId`\n- [Получить объект (авторизованный)](\u002Fdocs\u002Fstorage\u002Fobjects\u002Fget) — `GET \u002Fv1\u002Fstorage\u002Fobjects\u002F:key`\n- [Список объектов](\u002Fdocs\u002Fstorage\u002Fobjects\u002Flist) — `GET \u002Fv1\u002Fstorage\u002Fobjects`\n- [Удалить объект](\u002Fdocs\u002Fstorage\u002Fobjects\u002Fdelete) — `DELETE \u002Fv1\u002Fstorage\u002Fobjects\u002F:key`\n","\n## Публичные метаданные объекта\n\n`HEAD \u002Fv1\u002Fpublic-storage\u002F:portalId\u002F:objectId`\n\nВозвращает метаданные публично доступного объекта в заголовках ответа без передачи содержимого. Ключ API не требуется — эндпоинт анонимный. Анонимный доступ включается на уровне портала отдельно; по умолчанию выключен.\n\n## Параметры\n\n| Параметр | Тип | Обяз. | Описание |\n|----------|-----|:-----:|---------|\n| `portalId` (path) | string (UUID) | да | Идентификатор портала в Вайбкод. Формат: `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`. Получить через `GET \u002Fv1\u002Fme` с ключом управления — поле `data.portals[n].id` |\n| `objectId` (path) | string (CUID) | да | Внутренний идентификатор объекта (поле `id` из ответов на запись и список) |\n\n## Примеры\n\n**Ключ не требуется.** Оба примера отправляются без заголовков авторизации — это анонимный эндпоинт.\n\n### curl\n\n```bash\ncurl -I \"https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fpublic-storage\u002FYOUR_PORTAL_ID\u002FYOUR_OBJECT_ID\"\n```\n\n### JavaScript\n\n```javascript\nconst res = await fetch(\n  'https:\u002F\u002Fvibecode.bitrix24.tech\u002Fv1\u002Fpublic-storage\u002FYOUR_PORTAL_ID\u002FYOUR_OBJECT_ID',\n  { method: 'HEAD' }\n)\nif (res.ok) {\n  console.log('MIME-тип:', res.headers.get('content-type'))\n  console.log('Размер:', res.headers.get('content-length'))\n}\n```\n\n## Ответ\n\nПоведение зависит от состояния анонимного доступа на портале:\n\n**Анонимный доступ включён на портале.** Сервер возвращает `200 OK` с заголовками:\n\n| Заголовок | Значение |\n|-----------|---------|\n| `Content-Type` | MIME-тип содержимого объекта |\n| `Content-Length` | Размер объекта в байтах |\n| `Cache-Control` | `private, no-store` |\n\nТело ответа отсутствует.\n\n**Анонимный доступ выключен на портале** (текущее состояние тестового стенда): `503 STORAGE_PUBLIC_GET_DISABLED_FOR_PORTAL`.\n\n## Пример ответа при ошибке\n\n503 — анонимный доступ выключен на портале:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"STORAGE_PUBLIC_GET_DISABLED_FOR_PORTAL\",\n    \"message\": \"Public storage GET is disabled for this portal\"\n  }\n}\n```\n\n## Ошибки\n\n| HTTP | Код | Описание |\n|------|-----|---------|\n| 404 | `STORAGE_OBJECT_NOT_FOUND` | Объект не найден, имеет видимость `PRIVATE`, принадлежит другому порталу, или `objectId` не совпадает ни с одним объектом |\n| 410 | `STORAGE_OBJECT_DELETED` | Объект был удалён |\n| 429 | `STORAGE_RATE_LIMIT_EXCEEDED` | Превышен лимит 60 запросов в минуту с одного IP-адреса |\n| 503 | `STORAGE_PUBLIC_GET_DISABLED_FOR_PORTAL` | Анонимный доступ выключен на данном портале |\n| 503 | `STORAGE_FEATURE_DISABLED` | Хранилище временно недоступно на платформе |\n\nПолный список общих ошибок API — [Ошибки](\u002Fdocs\u002Ferrors).\n\n## Известные особенности\n\n- **Анонимный доступ включается отдельно.** Объект с видимостью `PUBLIC` не становится автоматически доступным через этот эндпоинт — администратор портала должен включить анонимный доступ в настройках хранилища.\n- **`objectId` — внутренний идентификатор, не логический ключ.** Используйте поле `id` из ответа на загрузку ([`POST \u002Fv1\u002Fstorage\u002Fobjects\u002Fupload`](\u002Fdocs\u002Fstorage\u002Fupload)) или из [списка объектов](\u002Fdocs\u002Fstorage\u002Fobjects\u002Flist).\n- **Заголовок `Content-Length` содержит реальный размер объекта** из базы данных — не длину сериализованного ответа.\n\n## Смотрите также\n\n- [Публичный доступ GET](\u002Fdocs\u002Fstorage\u002Fobjects\u002Fpublic-get) — `GET \u002Fv1\u002Fpublic-storage\u002F:portalId\u002F:objectId`\n- [Метаданные объекта (авторизованный)](\u002Fdocs\u002Fstorage\u002Fobjects\u002Fhead) — `HEAD \u002Fv1\u002Fstorage\u002Fobjects\u002F:key`\n- [Список объектов](\u002Fdocs\u002Fstorage\u002Fobjects\u002Flist) — `GET \u002Fv1\u002Fstorage\u002Fobjects`\n- [Удалить объект](\u002Fdocs\u002Fstorage\u002Fobjects\u002Fdelete) — `DELETE \u002Fv1\u002Fstorage\u002Fobjects\u002F:key`\n"]