Skip to main content
env.<BINDING> (a CloudStorageBucket) is the in-function handle to a Cloud Storage bucket, declared with a [storage.cloudstorage.<name>] block. It’s a pre-authenticated wrapper over the bucket — the runtime injects the credential, so your code holds no S3 access key or secret key.
This reference tracks @telnyx/edge-runtime ≥ 0.5.0. Ranged and conditional reads, batch delete, hierarchical listing, SSE-C, and the version / writeHttpMetadata object fields need ≥ 0.4.0; multipart uploads need ≥ 0.5.0.
Key behaviors:
  • Missing keys read as nullget and head resolve to null for a key that doesn’t exist, not an error.
  • A failed conditional read returns a body-less object — when a get onlyIf precondition isn’t met, get resolves to a plain CloudStorageObject (metadata only, no body and no readers) so you can reuse your cached copy. Check for a body before reading it.
  • delete is idempotent — deleting a missing key (single or in a batch) succeeds and resolves to void.
  • put returns partial metadata — the resolved object carries key, etag, httpEtag, version, and any metadata you set, but not size or uploaded. Use head to read those after a write.
  • Custom metadata keys are lower-cased on readx-amz-meta-* header names are stored lower-cased, so customMetadata keys come back lower-cased (uploadedByuploadedby).
  • SSE-C applies to US and APAC (ap-southeast-1) region bucketsssecKey is honored for buckets in US regions.

get(key, options?)

Read an object and its body. Returns null if the key does not exist.
A successful read returns a CloudStorageObjectBody — a CloudStorageObject plus the body stream and one-shot readers arrayBuffer(), text(), json(), and blob().

Ranged reads

Pass range to fetch part of an object instead of the whole thing — byte-range streaming, reading a header, or resuming a download. The resolved object echoes the requested range.

Conditional reads

Pass onlyIf to read only when a precondition holds — cache revalidation and “only fetch if changed.” A CloudStorageConditional maps to If-Match / If-None-Match / If-Unmodified-Since / If-Modified-Since; you can also pass a Headers object directly.
Conditional writes are not supported — onlyIf applies to get/head only.

put(key, body, options?)

Write an object. Resolves to a CloudStorageObject describing the write.
The resolved object carries key, etag (unquoted MD5 for a single-part write), httpEtag (the quoted, header-ready form), version (when bucket versioning is enabled), and the metadata you set. size and uploaded are not populated on the put result — read them back with head if you need them.

head(key, options?)

Read an object’s metadata without its body. Returns null if the key does not exist. Accepts the same onlyIf preconditions as get.
Unlike put, head returns the full CloudStorageObject including size and uploaded.

delete(key | keys)

Remove one object, or many in a single call. Idempotent — deleting a missing key resolves normally.
Passing an array maps to a single S3 batch delete. Deleting more than 1000 keys splits into 1000-key batches automatically.

list(options?)

Enumerate objects (metadata only — list does not return bodies).
When truncated is true, pass the returned cursor back in list({ cursor }) to fetch the next page. By default a list entry carries only key, size, etag, and uploaded. Pass include to also populate httpMetadata and/or customMetadata on each returned object — a heavier listing, so ask for it only when you need it.

Hierarchical (“folder”) listing

Set delimiter to / to browse one level of a key hierarchy: keys below the current level collapse into delimitedPrefixes, and only keys directly at the level appear in objects.

Multipart upload

Upload a large object in parts from inside a function — for objects past the Edge Compute request/response size cap, or for parallel/resumable uploads. Available on US and APAC (ap-southeast-1) region buckets.
  • createMultipartUpload(key, options?) starts the upload and returns a handle. options takes the same httpMetadata / customMetadata / ssecKey as put.
  • uploadPart(partNumber, body, options?) uploads one part and returns its { partNumber, etag }. Parts are numbered from 1; every part except the last must be at least 5 MiB.
  • complete(parts) assembles the object. You may pass the parts in any order — they’re sorted by partNumber.
  • abort() discards an in-progress upload and its parts.
  • resumeMultipartUpload(key, uploadId, options?) rebuilds a handle for an existing uploadId (no server round-trip) so you can upload more parts or complete()/abort() from a later invocation.

Server-side encryption (SSE-C)

Pass ssecKey on get, put, and multipart calls to encrypt with a customer-provided key. The key is a 256-bit (32-byte) AES key, given as an ArrayBuffer or a 64-character hex string. Supply the same key on read that you used on write; the object exposes ssecKeyMd5 (hex) so you can identify which key encrypted it. SSE-C applies to US and APAC (ap-southeast-1) region buckets.

Object types

head and each list entry populate size and uploaded; put’s result does not. The body readers on CloudStorageObjectBody consume the stream once — call a single one per get, and bodyUsed flips to true once you do. writeHttpMetadata is handy for serving an object straight back out of a function with its stored headers: