Preview — pending review
This reference is generated from the platform API contract and is still under review. Operations, fields, and descriptions can change before publication.
Initiate an object upload into the bucket
Initiates an object upload into the bucket, backing the "Upload" actions in the bucket
detail header and the object-browser toolbar (uploads target the currently browsed
prefix). The backend validates the destination, reserves the upload and returns a
short-lived upload session with a presigned PUT URL the browser streams the file to. Once
the upload completes, the object appears in the browser and the bucket's counters update.
Validation: bucketId must reference an existing, non-deleted bucket in the scope
(unknown → 404 NOT_FOUND); key is required and must be a valid, non-empty object key
(optionally prefixed by the browsed folder); contentType must be a syntactically valid
media type and sizeBytes a positive integer within the per-object size limit (invalid →
422 VALIDATION_FAILED); the subscription's storage quota must accommodate sizeBytes
(exceeded → 409 QUOTA_EXCEEDED); a bucket in its deleting workflow rejects new uploads
(→ 409 CONFLICT); caller must hold owner|admin|contributor on the scope, otherwise 403
FORBIDDEN.
Async & state: Synchronous issuance — returns 200 with the BucketUploadSession; the
data transfer itself then happens out-of-band against uploadUrl until expiresAt. When
the object lands, a resource.updated SSE frame is emitted (kind storage.bucket, patch
{objectCount, sizeBytes, updatedAt}) so open views refresh their counters.
Errors: 401 unauthenticated; 403 caller lacks write permission on the scope; 404
unknown scopeId or bucketId; 409 CONFLICT bucket is mid-deletion; 409 CONFLICT
details.reason=project_suspended the project's Temp-URL keys are withdrawn while it is
suspended; 409 LOCKED the key already exists in a legacy delete-protected
bucket (objectLock: true), an overwrite would replace it; 409 QUOTA_EXCEEDED
storage quota cannot accommodate the declared
size; 422 invalid key, content type or size (an invalid key carries
details.reason=object_key_invalid and details.rule one of
empty|too_long|control_char|folder|edge_unreachable; the key is the exact object name,
never trimmed, at most 1024 UTF-8 bytes, and must not start with / or contain //, a
./.. segment, ; or \ -- the public object-store endpoint refuses such paths);
429 upload-session issuance rate limit exceeded; 500 unexpected backend failure.
Signing key: the URL is signed with the account's Temp-URL-Key (slot 1).
An existing slot-1 key -- including one the customer set -- is reused unchanged; only an
account without one gets a key written, once. Slot 2 and container keys are never written.
Idempotency/Concurrency: This operation does not use Idempotency-Key; it may be omitted
and a sent one is ignored. Every call issues a new upload session (new uploadId, freshly
signed uploadUrl, new expiresAt); nothing is reserved, so a retry simply yields another
session for the same key. The presigned uploadUrl is revealed only in this response and never
in any read model.
bearerTokenAuthorizationBearer <token>An API token (pc_live_…) or a service-account key (sak_live_…), created in Identity & Access Management and sent as Authorization: Bearer <token>. Requests are rate limited per credential and per tenant: every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, and a refused request gets 429 RATE_LIMITED with Retry-After.
scopeId*stringOpaque ownership+authorization scope resolving to tenant + subscription + project.
bucketId*stringIdentifier of the bucket.
application/json- body
Upload initiation payload (destination key plus declared media type and size).
key*stringDestination object key, including the browsed folder prefix when uploading inside one.
contentType*stringsizeBytes*integerDeclared size in bytes; an empty (0-byte) object is a valid upload.
0 <= valueUpload session with a one-time presigned PUT URL.
application/json- response
Short-lived upload session with a one-time presigned PUT URL.
uploadId*stringbucketId*stringkey*stringuploadUrl*stringPresigned PUT URL to stream the file to (revealed only in this response).
method*"PUT""PUT"expiresAt*stringdate-timecurl -X POST "https://example.com/scopes/string/storage/buckets/string/uploads" \ -H "Content-Type: application/json" \ -d '{ "key": "string", "contentType": "string", "sizeBytes": 0 }'{ "uploadId": "string", "bucketId": "string", "key": "string", "uploadUrl": "string", "method": "PUT", "expiresAt": "2019-08-24T14:15:22Z"}