For AI agents: markdown of this page — /docs-content-en/storage/upload/complete.md documentation index — /llms.txt

Complete upload

POST /v1/storage/objects/complete

The second step of the presigned-URL upload — captures the actual file size and type from storage and moves the object to status COMPLETED.

Request fields (body)

Field Type Required Default Description
objectId string yes Object identifier from the POST /v1/storage/objects response

Examples

curl — personal key

Terminal
curl -X POST https://vibecode.bitrix24.com/v1/storage/objects/complete \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"objectId":"cmpf9b1gp003omr0zkc0qjojn"}'

curl — OAuth application

Terminal
curl -X POST https://vibecode.bitrix24.com/v1/storage/objects/complete \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"objectId":"cmpf9b1gp003omr0zkc0qjojn"}'

JavaScript — personal key

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/storage/objects/complete', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ objectId: 'cmpf9b1gp003omr0zkc0qjojn' }),
})

if (!res.ok) {
  const { error } = await res.json()
  console.error(error.code, error.message)
  return
}
const { object } = await res.json()
console.log('Upload complete, key:', object.key)

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/storage/objects/complete', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ objectId: 'cmpf9b1gp003omr0zkc0qjojn' }),
})

const { object } = await res.json()

Response fields

Field Type Description
object.id string Object identifier
object.key string Logical object key
object.contentType string Actual file MIME type (captured from storage)
object.sizeBytes string Actual file size in bytes (string)
object.sha256 string File SHA-256 hash or null
object.visibility string Visibility: PRIVATE or PUBLIC
object.uploadStatus string Upload status: COMPLETED
object.createdAt string Creation date (ISO 8601)
object.deletedAt string Deletion date or null

Response example

JSON
{
  "object": {
    "id": "cmpf9b1gp003omr0zkc0qjojn",
    "key": "users/42/avatar.png",
    "contentType": "image/png",
    "sizeBytes": "20480",
    "sha256": null,
    "visibility": "PRIVATE",
    "uploadStatus": "COMPLETED",
    "createdAt": "2026-05-21T08:56:32.809Z",
    "deletedAt": null
  }
}

Error response example

409 — the file was not sent to the presigned URL:

JSON
{
  "success": false,
  "error": {
    "code": "STORAGE_UPLOAD_NOT_FOUND_IN_BUCKET",
    "message": "..."
  }
}

Errors

HTTP Code Description
403 STORAGE_SCOPE_REQUIRED The API key lacks the vibe:storage scope
401 STORAGE_NO_AUTH_CONTEXT The request was made without authorization
400 STORAGE_OBJECT_ID_REQUIRED The objectId field was not provided
404 STORAGE_OBJECT_NOT_FOUND No object found with the given objectId
409 STORAGE_UPLOAD_NOT_PENDING The object was already completed earlier
409 STORAGE_UPLOAD_NOT_FOUND_IN_BUCKET The file was not sent to the presigned URL
415 STORAGE_FORBIDDEN_CONTENT_TYPE For PUBLIC objects, a MIME type was detected that is disallowed for security reasons; the object is deleted
503 STORAGE_FEATURE_DISABLED Storage is disabled for the portal
503 STORAGE_STS_UNAVAILABLE The temporary credentials issuance service is unavailable
502 STORAGE_BUCKET_ERROR Error while interacting with storage

Full list of common API errors — Errors.

Known specifics

Type check for PUBLIC objects. The actual MIME type is determined from the storage data, not from the contentType field passed at the object-creation step. The types text/html, application/javascript, application/x-javascript, image/svg+xml are forbidden.

See also