CalmLens JavaScript SDK
The official JavaScript and TypeScript SDK for CalmLens: content moderation and classification for text, images, documents and websites, plus optional storage and CDN delivery.
Installation
npm install calmlens
The same package is also published as @calmlens/sdk, at the same version. Import from the name you installed: calmlens/server with calmlens, or @calmlens/sdk/server with @calmlens/sdk.
The package has two clients, each with its own import:
| Import | Client | Runs | Authenticates with |
|---|---|---|---|
calmlens/server | CalmLensServerClient | On your server: Node.js 22 or later, Bun, Deno, Cloudflare Workers | A project API key |
calmlens/app | CalmLensAppClient | In browsers and React Native apps | An upload preset, with an optional upload token from your server |
API keys are secret, so CalmLensServerClient refuses to start in a web page or app. Upload from browsers and apps with CalmLensAppClient, and serve private content to them with signed URLs. The package ships ES modules and CommonJS with type declarations. The main, /server and /app entry points load no other packages at runtime. The package depends on zod, which its type declarations and testing helpers use, and on pdfjs-dist and hls.js, which the UI viewers load only when they show a document or a stream.
Versions follow semantic versioning: see Versioning and support.
Quick start
Create an API key under Developer → API Keys in the CalmLens portal. The same page shows your Project ID. Keep both on your server.
import { CalmLensServerClient } from "calmlens/server";
const client = new CalmLensServerClient({
apiKey: process.env.CALMLENS_API_KEY!,
projectId: process.env.CALMLENS_PROJECT_ID!,
});
// Text (comments, captions, bios): waits for the decision
const comment = await client.text.classify({ text: "Great photo!", externalId: "comment-42" });
const { status } = comment.classification.moderation;
if (status === "allowed" || status === "limited") {
// publish it; keep "limited" out of recommendations, trending and notifications
} else {
// "age-restricted": show it only behind your own age check; "blocked" or "purged": don't publish it
}
// Images and documents: queued, resolved by webhook or assets.retrieve()
const image = await client.assets.create({
name: "photo.jpg",
content: { data: file, type: "image/jpeg" },
externalId: "post-7",
});
console.log(image.classification.status, image.classification.moderation.status); // "processing" "pending"
classification.status | classification.moderation.status | Meaning |
|---|---|---|
completed | allowed | Safe to show. |
completed | limited | Delivered like allowed; reduce its reach, such as keeping it out of recommendations. |
completed | age-restricted | Delivered only with viewerClaims.ageConfirmed=true. Show it only to age-checked viewers. |
completed | blocked | Your policy blocked it; the CDN doesn't deliver it. Don't show it. |
completed | purged | Your policy blocked it and deleted its content. Don't show it. |
queued or processing | pending | Still being received or classified. |
failed | pending | Processing failed; see assets.retry. |
The latest applied review in classification.moderation.manualReviews takes precedence over the automated decision. Treat a status you don't recognise as not allowed. See How CalmLens works.
What you can do
- Moderate text, including replies in a conversation, and classify images, documents, audio, video and websites.
- Read classification results by category and qualifier, and ask for the complete policy evidence behind a decision.
- Send multipart uploads for large files, from any content payload, with safe retries and idempotency keys.
- Upload from browsers and apps through upload presets and locally signed upload tokens.
- Drop in the upload widget and media component for React, React Native, Vue, Svelte or custom elements.
- Deliver assets from the CDN with lenses and transforms, signed URLs and viewer claims.
- Record reviewer decisions, retry failed processing, and organise assets in folders.
- Verify and parse webhooks, or poll the events feed.
- Handle errors by stable code, and set timeouts and request budgets.
- Manage configuration in code:
uploadPresets.ensure,projectSettings.get/updateandmetadataFields.ensure, each guarded by a revision, or declare the project incalmlens.config.jsonand runcalmlens planandcalmlens applyin CI. - Forward events to a local handler with the bundled
calmlensCLI:npx calmlens listen --forward-to http://localhost:3000/api/webhooks/calmlens.
Every public SDK operation accepts one options object, so call sites stay stable as optional fields are added. The SDK reference lists every option and method.
Testing
calmlens/testing runs the real clients against an in-memory CalmLens API and CDN, with moderation outcomes, recorded requests, injected failures and signed webhook deliveries. See JavaScript testing.
calmlens/test-inputs makes signed test codes and images that the project they are signed for moderates as the scenario you choose. A code counts only as the whole text and an image only as the whole upload. See Generate test inputs.