#Создать составную загрузку
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 — личный ключ
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-приложение
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 — личный ключ
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-приложение
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 часа |
#Пример ответа
{
"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 ТБ:
{
"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).