Skip to main content
Uploads use multipart/form-data. The server streams parts through the encryption pipeline as they arrive; it does not buffer the whole file in memory.

Endpoint

The folder segment is optional. When present, the file is placed in that folder. The folder must exist and belong to the target bucket.

Request

To upload into a folder:

Multiple files

You can send up to 10 file parts in one request:
When a request contains multiple files, the success response describes only the first processed file. The other files may still have been stored. List the bucket or folder after a multi-file upload to discover every resulting fileId. Do not assume the response is a complete manifest.

Response

A successful upload returns 200 with:
The warning object, when present, has this shape:
Values are illustrative.

Prerequisites

The owning user context must have active HPKE keys containing an X25519 public key and an ML-KEM public key. Without them the upload fails with 400 before storage. Generate keys in the app, then retry.
Upload is a write operation. Lapsed subscriptions are refused. Trial accounts can upload within trial limits.
The key must have buckets:write and files:write, and must be allowed to target the bucket. The file must fit the remaining storage capacity and the plan’s per-file limit.
If a folder is specified, it must exist and belong to the same bucket. Cross-bucket folder mismatches are rejected.

Versioning behavior

If a file with the same name and extension already exists in the same folder scope, the upload can become a new version of that file. The response then has isUpdate: true. Do not infer version creation from the filename alone. Persist the returned fileId and versionId.

Error behavior during streaming

Validation can happen while the body is still arriving. A rejection may occur after your client has sent megabytes. Handle:
  • a non-2xx response even after the request body started,
  • connection reset when the server drains the body to deliver the error,
  • 413 for trial file-size violations,
  • 402 for insufficient storage or billing,
  • 400 for missing files, multipart errors, missing encryption keys, or validation failures.
Your client must not assume success until it receives a fileId.

Safe file processing

The API stores the bytes you send. It does not decide whether the content is safe for your application.
Treat every uploaded file as untrusted. Validate type and size before upload, scan untrusted content, and never execute uploaded files.
Recommended controls:
  1. Enforce an allowlist of extensions and MIME types in your application.
  2. Verify the declared size before starting a large upload.
  3. Scan untrusted files after upload, before exposing them to other users.
  4. Store the returned fileId, not the user-supplied filename, as the authoritative reference.
  5. Sanitize filenames for display; do not use them as filesystem paths.
  6. If you need integrity verification, compute a hash on your side and compare after download.
There is no documented client-supplied checksum field. Do not send one and assume the server validates it.

JavaScript example

TypeScript example with timeout

Python example

PHP example

Laravel example

Go example

These are examples, not official SDKs. They omit retries, structured error decoding, and secret management for brevity.