SDKs
Browser SDK @erasurehq/anumati — install, init, methods, HTTP, and troubleshooting.
SDKs
The public client SDK is @erasurehq/anumati.
It loads published consent configuration, shows the notice UI, and posts receipts. It authenticates with a publishable key only—never an operator session.
Derived from product docs: app_docs/guide/sdk.md, app_docs/sdk/GettingStarted.md, app_docs/sdk/API.md.
When to use it
- Marketing sites, SPAs, and multi-page apps that need a consent banner
- After you have published consent and a publishable key
How it works
Anumati.init({ publicKey, apiBaseUrl? })
│
▼ GET /api/sdk/v1/config (Bearer pk_live_…)
Published snapshot + ETag
│
▼ Banner / preferences UI
│
▼ POST /api/sdk/v1/consent
Receipt stored → optional project webhook (consent.updated)| Rule | Detail |
|---|---|
| Auth | Publishable key only—not operator session |
| Draft | Never returned from config |
| Storage | Choices in localStorage (package Storage docs) |
| Privacy | Receipts do not store IP or email |
Path to live
Publish consent → Create publishable key → Install SDK → First receipt → Live| Step | Where | Done when |
|---|---|---|
| 1. Publish | Consent | Immutable version exists |
| 2. Key | Develop | pk_live_… created |
| 3. Install | Your app | Anumati.init runs in the browser |
| 4. Receipt | Develop / Receipts | First row appears |
The first successful receipt is the integration milestone—not “SDK installed.”
Install
npm install @erasurehq/anumati
# pnpm add @erasurehq/anumati
# yarn add @erasurehq/anumati
# bun add @erasurehq/anumatiEnvironment
apiBaseUrl is the origin only—never include /api/....
Local
# .env
NEXT_PUBLIC_ANUMATI_PUBLIC_KEY=pk_live_…
NEXT_PUBLIC_ANUMATI_API_BASE_URL=http://localhost:3000Production
# .env
NEXT_PUBLIC_ANUMATI_PUBLIC_KEY=pk_live_…
NEXT_PUBLIC_ANUMATI_API_BASE_URL=https://your-erasure-originSame-origin apps (site and Erasure on one host) may omit apiBaseUrl.
Product guide examples sometimes use the option name baseUrl; the package Getting Started path documents apiBaseUrl. Use the option name your installed package documents; the value is always the Erasure origin.
Initialize
Instance client (documented npm API)
import { Anumati } from "@erasurehq/anumati";
const client = await Anumati.init({
publicKey: "pk_live_…",
apiBaseUrl: "https://your-erasure-origin", // optional if same-origin
onReady?: (client) => { /* … */ },
onError?: (error) => { /* … */ },
});Next.js (App Router — client only)
"use client";
import { useEffect } from "react";
import { Anumati } from "@erasurehq/anumati";
export function ConsentBootstrap() {
useEffect(() => {
void Anumati.init({
publicKey: process.env.NEXT_PUBLIC_ANUMATI_PUBLIC_KEY!,
apiBaseUrl: process.env.NEXT_PUBLIC_ANUMATI_API_BASE_URL,
});
}, []);
return null;
}React (Vite)
useEffect(() => {
void Anumati.init({
publicKey: import.meta.env.VITE_ANUMATI_PUBLIC_KEY!,
apiBaseUrl: import.meta.env.VITE_ANUMATI_API_BASE_URL,
});
}, []);Plain HTML / CDN
<script type="module">
import { Anumati } from "https://esm.sh/@erasurehq/anumati";
await Anumati.init({
publicKey: "pk_live_…",
apiBaseUrl: "http://localhost:3000",
});
</script>Express / Fastify
The SDK does not run on the server. Serve the publishable key to the browser. Optionally verify webhooks with X-Anumati-Signature (HMAC-SHA256 of the raw body). Console Develop includes Express / Fastify tabs for examples.
Client surface (core runtime)
From the SDK API surface documented for the shipped core:
| Member | Behaviour |
|---|---|
init(options) | Returns Promise<AnumatiClient>. Idempotent for the same publicKey. |
client.hasConsent(purposeKey) | true only if a current local decision exists for a matching consentHash and that purpose is granted. Unknown key → false. Before ready → false (fail closed). |
client.getConsent() | Returns choices, consentHash, versionNumber, needsConsent. |
client.showPreferences() | Opens preference modal (banner Manage + hosted preferences center). |
client.destroy() | Tear down the instance. |
onReady / onError | Optional callbacks on init. |
Init options (documented):
| Option | Notes |
|---|---|
publicKey | Required. pk_live_… |
apiBaseUrl | Optional API origin |
onReady / onError | Optional hooks |
Visitor identity (v1): the SDK auto-generates an installationId in localStorage. There is no public API to set or read it. Receipts and webhooks receive it automatically. There is no public subjectId option in v1.
Deferred / not to treat as guaranteed in core API design docs: additional managed-UI helpers such as a separate show() / hide() / clearLocal() surface and some callback variants may appear in package docs or later slices—rely on methods present in your installed package version.
Behavioral principles (from SDK design)
- One initialization path per project key.
- One SDK instance manages one project (one publishable key → one
projectId). - Instance client is the supported npm API (not a bag of mutable fields on a global).
initis idempotent for the same key.- Framework agnostic (vanilla TypeScript/JS).
- No hidden background work after ready—no silent polling or re-POST of receipts without user action or a new init.
- Optional purposes default to not granted until accepted.
- Re-prompt decisions use
consentHash, not wall-clock alone.
HTTP used by the SDK
GET /api/sdk/v1/config
Auth: Authorization: Bearer pk_live_…
Compatibility only (not recommended): ?key= may be accepted by the server. The SDK package does not send query keys.
Caching: ETag from content hash; Cache-Control: public, max-age=60, stale-while-revalidate=600; If-None-Match → 304.
200 (shape):
{
"projectId": "…",
"version": {
"id": "…",
"number": 3,
"publishedAt": "ISO-8601",
"contentHash": "…",
"consentHash": "…"
},
"config": {
"purposes": [
{
"id": "…",
"key": "analytics",
"name": "…",
"description": "…",
"required": false,
"categoryId": "…",
"sortOrder": 0
}
],
"categories": [{ "id": "…", "name": "Essential", "sortOrder": 0 }],
"notice": {
"title": "…",
"description": "…",
"acceptLabel": "…",
"rejectLabel": "…",
"manageLabel": "…",
"companyName": "…",
"logoUrl": "…",
"primaryColor": "…"
}
}
}| code | HTTP |
|---|---|
invalid_key | 401 |
revoked_key | 403 |
no_published_version | 404 |
rate_limited | 429 |
POST /api/sdk/v1/consent
Auth: Bearer publishable key.
Purpose: append-only consent receipt.
Body:
{
"versionId": "…",
"consentHash": "…",
"choices": { "analytics": true, "marketing": false },
"timestamp": "2026-01-01T00:00:00.000Z",
"sdkVersion": "0.1.0"
}timestampmay be accepted but is not stored; servercreatedAtis authoritative.- Do not send IP, email, fingerprint, or session identifiers.
consentHashmust match the version’s computed consent surface.- Receipts are append-only (never update/delete).
201: { "ok": true, "id": "…", "createdAt": "…" }
| code | HTTP |
|---|---|
invalid_key | 401 |
revoked_key | 403 |
invalid_body | 400 |
invalid_version | 400 |
consent_hash_mismatch | 400 |
Publishable key management (console session)
| Method | Path |
|---|---|
POST | /api/platform/projects/:projectId/api-keys |
GET | /api/platform/projects/:projectId/api-keys |
DELETE | /api/platform/projects/:projectId/api-keys/:keyId |
Full secret shown once on create; thereafter prefix only. Soft revoke via revokedAt.
Hosted preferences
Product docs reference a hosted preferences surface: /preferences?key=pk_live_… (see SDK Getting Started “what happens next”).
Error handling
| Situation | Guidance |
|---|---|
| 401/403 invalid or revoked key | Rotate key in Develop; update env |
| 404 no published version | Publish consent first |
| Network / CORS | SDK endpoints allow CORS *; check origin / apiBaseUrl |
| Rate limited 429 | Back off; honor Retry-After |
Best practices
- Publish before shipping the key to production.
- One key per environment if possible.
- Prefer Bearer; avoid query-string keys.
- Treat first receipt as go-live, not “script loaded”.
- Init only in the browser (
useEffect/'use client').
Troubleshooting
| Symptom | Check |
|---|---|
| No banner | Init errors; publish exists; key not revoked |
| No receipts | Network tab POST consent; versionId/hash match; rate limits |
| Stale config | ETag/cache; republish and hard-refresh |
no_published_version | Publish in Consent |
| Init on server | Move to client-only code |
Related
Publish consent guide · API · SDK · Publishable keys · Webhooks