Amba
SDKsFeatures

Storage

Upload files from any SDK. Per-bucket retention, signed URLs, cascade-on-user-delete.

Upload images, documents, and other assets from any SDK with one call. Each file is stored against the signed-in user and surfaced via a CDN URL. Buckets are configured server-side with retention policies; assets are automatically removed when the owning user is deleted.

The client SDKs expose two shapes over the same three-step flow (register → PUT the bytes → finalize): a one-call upload({ bucket, file }) that runs all three for you, and an explicit presign + commit pair for when you want to control the PUT yourself (upload through your own server, apply pre-upload validation, or run the transfer in the background).

Quick start

import { Amba } from '@layers/amba-web';
 
async function onFileChange(e: Event) {
  const file = (e.target as HTMLInputElement).files?.[0];
  if (!file) return;
 
  const asset = await Amba.storage.upload({
    bucket: 'avatars',
    file,
    retentionDays: 30,
  });
 
  console.log(asset.url); // CDN URL
}

Operations

One-call upload (upload)

Available on platforms where the SDK can directly hold the file body (Web, React Native, Swift). Encapsulates the full presign → PUT → commit flow. Use this when the customer is uploading directly from their device.

const asset = await Amba.storage.upload({
  bucket: 'avatars',
  file, // Browser File / Blob, or RN Blob, or platform native data
  filename: 'me.jpg', // optional — defaults to file.name where available
  retentionDays: 30, // optional — defaults to the bucket's policy
});
 
// Returned MediaAsset:
//   {
//     id: 'asset_...',
//     bucket: 'avatars',
//     key: 'user/.../me.jpg',
//     url: 'https://{projectId}.cdn.amba.host/avatars/...',
//     mime_type: 'image/jpeg',
//     size_bytes: 123456,
//     created_at: '2026-05-13T...',
//   }

Two-phase: presign + commit (server-side only)

Use when the upload must flow through your own server (validation, virus scanning, content rewriting), or when you want to control the PUT yourself. Available on every SDK, including web. upload() is the same three steps run for you in one call.

import { AmbaClient } from '@layers/amba-node';
 
const amba = await AmbaClient.configure({
  projectId: process.env.AMBA_PROJECT_ID!,
  clientKey: process.env.AMBA_CLIENT_KEY!,
});
 
// 1. Get a signed PUT URL + an upload id
const presign = await amba.storage.presign({
  bucket: 'invoices',
  filename: `invoice-${id}.pdf`,
  mimeType: 'application/pdf',
  sizeBytes: pdfBuffer.byteLength,
});
 
// 2. PUT the bytes to the signed URL (any HTTP client; the signed
//    URL embeds the auth)
await fetch(presign.upload_url, {
  method: 'PUT',
  headers: Object.fromEntries(presign.upload_headers),
  body: pdfBuffer,
});
 
// 3. Tell the server the upload is done — server validates + indexes
//    + returns the final asset metadata
const asset = await amba.storage.commit(presign.upload_id, presign.asset_id);

Patterns

Per-user avatars

Buckets aren't user-scoped on the server, but every asset's user_id is stamped from the session. The CDN URL is public; if you want privacy-by-design, point clients at the asset id and gate URL issuance through a server function.

// Client uploads
const asset = await Amba.storage.upload({ bucket: 'avatars', file });
 
// Save the asset id (not the URL) against your user profile
await Amba.collections.update('users', userId, { avatar_asset_id: asset.id });

Retention

Pass retentionDays at upload to override the bucket's default. Assets pass their retention deadline are removed by a background sweeper.

Cascade on user delete

When a user is deleted (via the admin API), every asset they own across every bucket is queued for purge. No additional work needed in your app.

Limits

  • Max upload size: 50 MB for the default media bucket. Other buckets carry their own cap, configurable via the admin API.
  • Supported MIME types: each bucket has an allow-list. The default media bucket allows common image, video, and audio types (image/jpeg, image/png, image/webp, image/gif, video/mp4, video/webm, video/quicktime, video/x-m4v, audio/mpeg, audio/aac, audio/ogg, audio/mp4). A mimeType outside the list is rejected with a 400. The server records what you declare; it doesn't transcode or validate content.
  • CDN edge cache: asset responses cache at the CDN for ~5 minutes by default.
  • Buckets are pre-created: defined via the admin API (POST /admin/projects/:projectId/storage/buckets with { "name": "avatars", "public": true }) before the client can upload.
  • Per-asset metadata: only the SDK-supplied fields (bucket, filename, mimeType, sizeBytes, retentionDays) are first-class. For custom metadata, attach it to a collection row referencing asset_id.

Reference

  • Client API — media — presign + commit endpoints.
  • Bucket creation + policy management: POST/GET/PATCH/DELETE /admin/projects/:projectId/storage/buckets[/:name]. Bucket responses include bucket_path (the URL path segment assets are served under; defaults to the bucket name). The legacy r2_bucket_path field is a deprecated alias of bucket_path — still accepted on create and emitted in responses for back-compat, but new integrations should use bucket_path.
  • Auth feature — prerequisite.
  • Per-platform quickstarts: Web, Node, iOS, Android, Flutter, Unity.

On this page