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: a one-call upload({ bucket, file }) flow, and a two-phase presign + commit flow for when you want to upload through your own server or apply pre-upload validation.

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:
//   {
//     asset_id: 'asset_...',
//     url: 'https://cdn.amba.host/...',
//     mime_type: 'image/jpeg',
//     size_bytes: 123456,
//     created_at: '2026-05-13T...',
//   }

Two-phase: presign + commit

Use when the upload must flow through your own server (validation, virus scanning, content rewriting) or when the SDK doesn't expose a one-call form.

// 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.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: up to 100 MB per single PUT.
  • Supported MIME types: any. The server records what you declare; it doesn't transcode or validate content.
  • CDN edge cache: signed-URL responses cache at the CDN for ~5 minutes by default; pass cache: false in headers on the commit if you need freshness.
  • Buckets are pre-created: defined via the CLI (amba storage create-bucket avatars --public) or the admin API 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

On this page