[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"docs-storage\u002Fupload\u002Fpresigned":3,"docs-tabs-storage\u002Fupload\u002Fpresigned":6},{"content":4,"lastmod":5},"## Создать предподписанный 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","2026-07-07",{}]