Delivering assets

The CalmLens CDN serves stored asset content and previews, so your app can show moderated files without hosting them itself. This guide covers asset URLs, signed URLs for private assets, and caching. For the signing endpoint and URL formats, see the CDN reference.

CDN URLs live under:

https://cdn.calmlens.com/v1

Before you serve a file

  • Retain it: set processingOptions.keepContentAfterProcessing: true when uploading.
  • Check the decision: rejected, failed, removed and safety-held content cannot be served. Enable Block assets until moderation finishes to block pending content too.
  • Choose access: use public visibility for public files or a signed URL for private files in browsers.

Asset URLs

Asset content is served from GET /assets/:projectId/:assetIdentifier/content.

Asset previews are served from GET /assets/:projectId/:assetIdentifier/preview.

assetIdentifier can be the asset ID or the asset's externalId. The asset must have finished uploading and its content must have been retained with processingOptions.keepContentAfterProcessing: true. Public assets can then be requested directly.

Rejected assets, assets whose processing failed (error), safety-held assets and assets with removed content are never served. Assets whose moderation is still pending are served by default; enable Block assets until moderation finishes in the project settings (settings.blockUnmoderatedAssets) to serve only moderated content. See Delivery while moderation runs.

const response = await client.cdn.serve({
  assetIdentifier: assetId,
});

Private assets require one of the following:

  • An authenticated CalmLens browser session belonging to the asset owner.
  • A short-lived signed URL.

For direct private reads, enable Download assets (assets:download) on a project API key and send it in the X-Api-Key header. This permission only grants access within that key's project.

HEIC and HEIF previews

The preview endpoint automatically converts HEIC and HEIF image assets to WebP so they can be displayed in browsers that do not support Apple's source formats. This applies to image/heic, image/heif, and their sequence variants. Converted previews fit within 1920 × 1920 pixels, preserve their aspect ratio, and are never enlarged.

/assets/:projectId/:assetIdentifier/preview

The content endpoint continues to serve the original stored file. Lenses and direct transforms also work on the browser-friendly preview.

Signed URLs

Signed URLs let untrusted clients access one private resource for a limited time without receiving an API key or application session. Prefer them for browsers and other clients you do not control.

Create a signed URL from the public API:

import { CalmLensClient } from "@calmlens/sdk";

const client = new CalmLensClient({
  apiKey: "your-api-key",
  projectId: "your-project-id"
});

const response = await client.assets.createSignedUrl({
  "resource": "content",
  "expiresInSeconds": 900,
  "assetId": "your-asset-id"
});

The response contains:

{
  "url": "https://cdn.calmlens.com/v1/assets/.../content?exp=...&sig=...",
  "expiresAt": 1760000000000
}

With your SDK:

const signedUrl = await client.assets.createSignedUrl({
  assetId,
  resource: "content",
  expiresInSeconds: 900,
});

Supported request body fields:

FieldTypeDefaultDescription
resource"content" or "preview""content"Which CDN resource to sign.
lensstringomittedOptional lens identifier, such as thumbnail.
transformstringomittedOptional direct transform selector, such as imageTransform[format=png,width=1024].
expiresInSecondsnumber900Signed URL lifetime, from 1 second to 24 hours.

Provide either lens or transform, never both. The signature is scoped to the project, asset identifier, resource, selected lens or transform, and expiry. Changing any of those values invalidates the URL.

Lenses and transforms

Use Lenses & Transformation for named lenses, private lens URLs, direct image transforms, supported options, and versioned custom definitions.

Caching and availability

Public derived responses are cacheable. Private responses remain private and require authorization on each unsigned request. Signed URL parameters, selected resource, lens or transform, asset visibility, asset status, and lens version all participate in authorization or cache identity.

Changing a signed URL, transform, or lens selector invalidates its signature. Every CDN request, including one answered from cache, checks the asset's status, visibility and stored content first, and rejecting an asset, placing a safety hold, removing its content or deleting it purges cached copies across the CDN, so delivery stops within seconds in every region. Browsers and other HTTP caches outside CalmLens may keep a copy they already downloaded until its Cache-Control lifetime ends. Requests for unavailable private assets generally return 404 to avoid revealing their existence; assets blocked by their status return 403 asset/not-available.

Signing in

Signing out

Cookies on CalmLens

We use essential cookies to keep you signed in and the site secure. With your permission, we'll also use functional cookies to remember preferences such as your layout and documentation language, and to offer Google One Tap sign-in. We don't use analytics or advertising cookies. Manage cookies