#Создать составную загрузку

POST /v1/storage/objects/multipart/create

Открывает сессию составной загрузки для файлов до 5 ТБ. Возвращает идентификатор объекта, идентификатор сессии и предподписанные URL для загрузки частей. После загрузки всех частей вызовите `POST /v1/storage/objects/multipart/complete`, чтобы собрать объект.

#Поля запроса (body)

Тело запроса — JSON.

Параметр Тип Обяз. По умолч. Описание
key string да Логический ключ объекта: от 1 до 1024 символов, допустимы a-z, A-Z, 0-9, ., _, /, -; не начинать с / или ., не содержать ..
contentType string да MIME-тип файла, например video/mp4 или application/zip
totalSize number да Общий размер файла в байтах; положительное целое число; не более 5 ТБ (5 497 558 138 880 байт)
partSize number нет 8388608 Размер одной части в байтах; от 5 МБ (5 242 880) до 5 ГБ (5 368 709 120); последняя часть может быть меньше минимума
visibility string нет PRIVATE Видимость объекта: PRIVATE или PUBLIC

#Примеры

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

Terminal
curl -X POST https://vibecode.bitrix24.tech/v1/storage/objects/multipart/create \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "videos/lecture-01.mp4",
    "contentType": "video/mp4",
    "totalSize": 209715200
  }'

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

Terminal
curl -X POST https://vibecode.bitrix24.tech/v1/storage/objects/multipart/create \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "videos/lecture-01.mp4",
    "contentType": "video/mp4",
    "totalSize": 209715200
  }'

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

javascript
const file = fileInput.files[0]

// Шаг 1 — открыть сессию составной загрузки
const createRes = await fetch(
  'https://vibecode.bitrix24.tech/v1/storage/objects/multipart/create',
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      key: 'videos/lecture-01.mp4',
      contentType: file.type,
      totalSize: file.size,
    }),
  }
)
const { objectId, parts } = await createRes.json()

// Шаг 2 — загрузить части параллельно, сохранить ETag из заголовков ответов
const PART_SIZE = 8 * 1024 * 1024
const uploadedParts = await Promise.all(
  parts.map(async ({ partNumber, uploadUrl }) => {
    const start = (partNumber - 1) * PART_SIZE
    const end = Math.min(start + PART_SIZE, file.size)

    const putRes = await fetch(uploadUrl, {
      method: 'PUT',
      body: file.slice(start, end),
    })
    const etag = putRes.headers.get('ETag')
    return { partNumber, etag }
  })
)

// Шаг 3 — завершить сборку объекта
const completeRes = await fetch(
  'https://vibecode.bitrix24.tech/v1/storage/objects/multipart/complete',
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ objectId, parts: uploadedParts }),
  }
)
const { object } = await completeRes.json()
console.log('Object ID:', object.id)

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

javascript
const file = fileInput.files[0]

const createRes = await fetch(
  'https://vibecode.bitrix24.tech/v1/storage/objects/multipart/create',
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      key: 'videos/lecture-01.mp4',
      contentType: file.type,
      totalSize: file.size,
    }),
  }
)
const { objectId, parts } = await createRes.json()

const PART_SIZE = 8 * 1024 * 1024
const uploadedParts = await Promise.all(
  parts.map(async ({ partNumber, uploadUrl }) => {
    const start = (partNumber - 1) * PART_SIZE
    const end = Math.min(start + PART_SIZE, file.size)

    const putRes = await fetch(uploadUrl, { method: 'PUT', body: file.slice(start, end) })
    const etag = putRes.headers.get('ETag')
    return { partNumber, etag }
  })
)

const completeRes = await fetch(
  'https://vibecode.bitrix24.tech/v1/storage/objects/multipart/complete',
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ objectId, parts: uploadedParts }),
  }
)
const { object } = await completeRes.json()

#Поля ответа

Поле Тип Описание
objectId string Идентификатор объекта в хранилище
uploadId string Идентификатор сессии составной загрузки
partCount number Количество частей, рассчитанное из totalSize и partSize
parts array Массив описателей частей
parts[].partNumber number Номер части (начиная с 1)
parts[].uploadUrl string Предподписанный URL для загрузки части методом PUT
parts[].expiresAt string Срок действия URL (ISO 8601); совпадает со сроком сессии — 24 часа

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

JSON
{
  "objectId": "cmpfg012a01aco510mrr6u632",
  "uploadId": "00065252B4EA33D1",
  "partCount": 2,
  "parts": [
    {
      "partNumber": 1,
      "uploadUrl": "https://storage.example.com/upload?partNumber=1&uploadId=00065252B4EA33D1&...",
      "expiresAt": "2026-05-22T12:03:56.398Z"
    },
    {
      "partNumber": 2,
      "uploadUrl": "https://storage.example.com/upload?partNumber=2&uploadId=00065252B4EA33D1&...",
      "expiresAt": "2026-05-22T12:03:56.398Z"
    }
  ]
}

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

413 — файл превышает ограничение 5 ТБ:

JSON
{
  "success": false,
  "error": {
    "code": "STORAGE_OBJECT_TOO_LARGE",
    "message": "Object exceeds 5 TB cap"
  }
}

#Ошибки

HTTP Код Описание
403 STORAGE_SCOPE_REQUIRED API-ключу не хватает скоупа vibe:storage
401 STORAGE_NO_AUTH_CONTEXT Запрос выполнен без авторизации
400 STORAGE_INVALID_PATH Идентификатор вызывающего содержит недопустимые символы пути
400 STORAGE_KEY_REQUIRED Не передано поле key
400 STORAGE_INVALID_KEY Значение key нарушает правила формата
400 STORAGE_CONTENT_TYPE_REQUIRED Не передано поле contentType
400 STORAGE_INVALID_VISIBILITY Недопустимое значение visibility
400 STORAGE_INVALID_TOTAL_SIZE totalSize не является положительным целым числом
400 STORAGE_INVALID_PART_SIZE partSize выходит за пределы допустимого диапазона (5 МБ – 5 ГБ) или не является положительным целым числом
413 STORAGE_OBJECT_TOO_LARGE totalSize превышает 5 ТБ
400 STORAGE_TOO_MANY_PARTS Рассчитанное количество частей превышает 10 000 — увеличьте partSize
402 BILLING_INSUFFICIENT Недостаточно средств на балансе
503 STORAGE_FEATURE_DISABLED Хранилище отключено для портала
503 STORAGE_STS_UNAVAILABLE Служба выдачи временных учётных данных недоступна
502 STORAGE_BUCKET_ERROR Ошибка при взаимодействии с хранилищем

Полный список общих ошибок API — Ошибки.

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

Предподписанные URL для частей не требуют заголовков авторизации. Запросы PUT на эти URL отправляются напрямую в хранилище без X-Api-Key или Authorization — все необходимые учётные данные уже подписаны в самом URL.

Срок действия сессии — 24 часа. По истечении срока предподписанные URL становятся недействительными, незагруженные части удаляются автоматически. Для досрочного освобождения ресурсов вызовите `POST /v1/storage/objects/multipart/abort`.

Файлы меньшего размера. Для файлов до 10 МБ используйте прямую загрузку (Путь A). Для файлов до 5 ГБ — предподписанный URL (Путь B).

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