Choose your integration
Choose the flow that matches what your users submit and who may see it. Your backend owns publication and end-user permissions; CalmLens supplies moderation decisions and can also store and deliver your files.
Start with your use case
| You are building | Submit content | Keep content in CalmLens? | Publish and maintain it |
|---|---|---|---|
| Comments, posts or chat | Classify text on your server. Include conversation context for replies. | Optional. Keep your application’s text; retain CalmLens’s copy if reviewers need it. | Create a pending version before checking. Apply the returned decision and later status events to that version. |
| Profile pictures | Use a signed browser upload, with a new upload ID each time. | Yes, to serve avatar thumbnails. | Promote only the current candidate when allowed or limited. Keep the previous picture while checking. |
| A public photo feed | Sign direct browser uploads, or upload through your API. | Yes if CalmLens serves it; otherwise keep your own copy. | Store the server-confirmed decision. Use the media component, reduce reach for limited posts and gate age-restricted content. |
| Private messages or tenant files | Authenticate the uploader and upload through your server or issue a token for a private preset. | Yes if CalmLens hosts the file. Set private visibility. | Check ownership or tenant access before each proxy request or signed-link issue. Moderation approval does not grant user access. |
| An anonymous form or static site | Use a public upload preset. | Yes to review or display the file later; otherwise only the report remains. | Show the uploader feedback and review submissions in the portal. A shared feed or private delivery needs a backend. |
| An existing file library | Submit bytes or public file URLs from your backend, with unique external IDs. | Optional if you already retain originals. | Keep your own files unavailable until checked. Apply later decisions to your storage and caches. |
| Audio or video submissions | Upload and wait asynchronously. | Yes for CalmLens playback; otherwise retain your own originals. | Handle pending, completed and failed processing. Serve the original resource after approval. |
| Links to web pages | Submit each page URL. | Retain if you need its captured content for review. | Read the combined child decision. It describes the captured page; submit again to check later changes. |
Choose where the bytes travel
- Through your server: your endpoint receives the content, checks the user and submits it with a server-only API key. Your server’s upload limits also apply.
- Directly from the browser, with your server’s approval: create a pending upload record, then sign a single-upload token. The file bypasses your server; your backend still verifies ownership and receives decisions.
- Directly without a server: a public preset accepts anyone within its limits. Its daily limit is per client IP/address group, not a project-wide spending cap. Set organisation usage limits as well.
The quick start has the setup for each route. Never expose an API key in browser or mobile code.
Choose retention and access separately
Retention defaults off. Turn on processingOptions.keepContentAfterProcessing or the preset’s retention setting when CalmLens must serve the file or let reviewers inspect it later. With retention off, the record and report remain but processed content is deleted.
Visibility defaults to private and is independent of retention. Public content can be retrieved by anyone with its eligible URL. Private content needs authorised access. A signed URL is a bearer link until expiry; use an authenticated proxy when your application must check each viewer on every request. See Asset permissions.
Decide what each viewer may see
Store classification.moderation.status as the base decision. Allowed and limited content can be shown; limited content should not be amplified. Keep pending and failed processing unpublished. Hide blocked or purged content, and apply your age check to age-restricted content.
The asset response contains stored moderation decisions. Pass optional viewerClaims on CDN requests: region defaults to the connecting country and ageConfirmed defaults to false. The CDN applies regional restrictions without a separate asset lookup. If you proxy requests, forward the viewer country; if you serve your own bytes, enforce the decisions yourself. See Viewer claims.
Keep your application in sync
Create the pending application record before submitting content. Give every edit or replacement upload a unique externalId, and save the returned asset ID. Subscribe to allowed, limited, age-restricted, blocked, purged and failed events; for regional controls, include asset.region-restricted.
Verify webhook signatures, durably retain early events, deduplicate event IDs and prevent older versions from replacing the current one. Reliable application updates defines the database responsibilities used by the examples. If webhooks are unavailable, use bounded polling and reconcile later decisions through the events feed.
Verify before publishing
Use test inputs and SDK mocks for allowed, limited, age-restricted, blocked and purged outcomes. Also check processing failure, duplicate and early webhooks, two uploads completing out of order, private access denial and an unknown viewer country. Keep originals available when testing recovery.