For AI agents: markdown of this page — /docs-content-en/storage/upload/multipart-complete.md documentation index — /llms.txt
Complete multipart upload
POST /v1/storage/objects/multipart/complete
Finalizes a multipart upload session: assembles the uploaded parts into a single storage object and moves it to status COMPLETED. On replacement, the new bytes and metadata are published under the existing objectId; reads return the old content only until publication actually happens. A successful response confirms the new version. Retrying complete with the same parts finishes the operation when the provider response was already journalled: the server finalizes the published result locally without asking the provider to assemble it again. If complete returns 502 STORAGE_BUCKET_ERROR, publication may have happened without a journalled response: the session is retained and requires operator reconciliation, and a blind retry does not confirm the current version. Until an operator releases it, the object cannot be deleted and owner-data erasure remains pending. Returns the ready object when the result is confirmed.
Request fields (body)
The request body is JSON.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
ParameterobjectId |
Typestring | Requiredyes | Default— | DescriptionObject identifier obtained from the /multipart/create response |
Parameterparts |
Typearray | Requiredyes | Default— | DescriptionNon-empty array of part descriptors with numbers and ETags |
Parameterparts[].partNumber |
Typenumber | Requiredyes | Default— | DescriptionPart number (integer from 1 to 10,000); must match the numbers from the /multipart/create response; duplicates are not allowed |
Parameterparts[].etag |
Typestring | Requiredyes | Default— | DescriptionValue of the ETag header from the response to the part's PUT request; accepted with quotes ("abc...") and without |
Examples
curl — personal key
curl -X POST https://vibecode.bitrix24.com/v1/storage/objects/multipart/complete \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"objectId": "cmpfg012a01aco510mrr6u632",
"parts": [
{ "partNumber": 1, "etag": "b315b942673d13dbdd2d866e92b0ec13" },
{ "partNumber": 2, "etag": "a1b2c3d4e5f678901234567890abcdef" }
]
}'
curl — OAuth application
curl -X POST https://vibecode.bitrix24.com/v1/storage/objects/multipart/complete \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"objectId": "cmpfg012a01aco510mrr6u632",
"parts": [
{ "partNumber": 1, "etag": "b315b942673d13dbdd2d866e92b0ec13" },
{ "partNumber": 2, "etag": "a1b2c3d4e5f678901234567890abcdef" }
]
}'
JavaScript — personal key
// uploadedParts — an array of { partNumber, etag } collected at the part-PUT step
const res = await fetch(
'https://vibecode.bitrix24.com/v1/storage/objects/multipart/complete',
{
method: 'POST',
headers: {
'X-Api-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
objectId: 'cmpfg012a01aco510mrr6u632',
parts: uploadedParts,
}),
}
)
const { object } = await res.json()
console.log('Object ID:', object.id)
JavaScript — OAuth application
const res = await fetch(
'https://vibecode.bitrix24.com/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: 'cmpfg012a01aco510mrr6u632',
parts: uploadedParts,
}),
}
)
const { object } = await res.json()
Response fields
| Field | Type | Description |
|---|---|---|
Fieldobject.id |
Typestring | DescriptionObject identifier |
Fieldobject.key |
Typestring | DescriptionLogical object key |
Fieldobject.contentType |
Typestring | DescriptionFile MIME type |
Fieldobject.sizeBytes |
Typestring | DescriptionFile size in bytes (string) |
Fieldobject.sha256 |
Typestring | DescriptionFile SHA-256 hash or null |
Fieldobject.visibility |
Typestring | DescriptionVisibility: PRIVATE or PUBLIC |
Fieldobject.uploadStatus |
Typestring | DescriptionUpload status: COMPLETED |
Fieldobject.createdAt |
Typestring | DescriptionCreation date (ISO 8601) |
Fieldobject.deletedAt |
Typestring | DescriptionDeletion date or null |
Fieldobject.contentUpdatedAt |
Typestring (ISO 8601) | DescriptionWhen the content last became current: a replacement, or the first completion of the upload. Service updates do not move it. null for objects last written before this field existed |
Response example
{
"object": {
"id": "cmpfg012a01aco510mrr6u632",
"key": "videos/lecture-01.mp4",
"contentType": "video/mp4",
"sizeBytes": "209715200",
"sha256": null,
"visibility": "PRIVATE",
"uploadStatus": "COMPLETED",
"createdAt": "2026-05-21T12:03:56.387Z",
"deletedAt": null
}
}
Error response example
400 — an incorrect number of parts was passed:
{
"success": false,
"error": {
"code": "STORAGE_INVALID_PARTS",
"message": "Expected 2 parts, got 1"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| HTTP403 | CodeSTORAGE_SCOPE_REQUIRED |
DescriptionThe API key lacks the vibe:storage scope |
| HTTP401 | CodeSTORAGE_NO_AUTH_CONTEXT |
DescriptionThe request was made without authorization |
| HTTP400 | CodeSTORAGE_INVALID_PATH |
DescriptionThe caller identifier contains invalid path characters |
| HTTP400 | CodeSTORAGE_OBJECT_ID_REQUIRED |
DescriptionThe objectId field was not provided |
| HTTP400 | CodeSTORAGE_PARTS_REQUIRED |
DescriptionThe parts field is missing or is an empty array |
| HTTP400 | CodeSTORAGE_INVALID_PART |
DescriptionAn element of the parts array contains an invalid partNumber (not an integer in the range 1–10,000, a duplicate) or an empty etag |
| HTTP404 | CodeSTORAGE_OBJECT_NOT_FOUND |
DescriptionThe object with the given objectId was not found or the multipart upload session is already finalized |
| HTTP409 | CodeSTORAGE_KEY_CONFLICT |
DescriptionRetryable conflict: a concurrent write owns the address, or finalization state is changing. Retry complete with the same parts: if the provider response was already journalled, the server finishes the operation locally |
| HTTP400 | CodeSTORAGE_INVALID_PARTS |
DescriptionThe number of parts does not match partCount from /create, or storage rejected the assembly due to invalid ETags |
| HTTP503 | CodeSTORAGE_FEATURE_DISABLED |
DescriptionStorage is disabled for the portal |
| HTTP503 | CodeSTORAGE_STS_UNAVAILABLE |
DescriptionThe temporary credentials issuance service is unavailable |
| HTTP502 | CodeSTORAGE_BUCKET_ERROR |
DescriptionProvider publication may have completed, but its response was not journalled. The session is retained and requires operator reconciliation; until an operator releases it, the object cannot be deleted and owner-data erasure remains pending. Do not treat a blind retry as proof of success |
Full list of common API errors — Errors.