Node SDK
Server-side quickstart for @layers/amba-node — install, configure, server keys, asUser() per-request scoping, and Connect/Express middleware in under 10 minutes.
@layers/amba-node is the Node.js server SDK. Same surface as @layers/amba-web, idiomatic for long-running Node processes — one client per service, per-request user scoping via asUser(uid) with a server key, and a built-in Connect-style middleware factory.
When to use this SDK:
- Webhook handlers (Stripe, RevenueCat, GitHub) that need to mutate amba state from server context.
- Background workers / cron jobs that call amba on behalf of users without a session token.
- BFFs that proxy specific operations from a browser to amba with extra business logic.
1. Install
Requires Node 20+ (uses native fetch, top-level await, and import.meta.resolve).
ESM only
@layers/amba-node ships as ESM-only ("type": "module" in package.json). It cannot be require()'d from a CommonJS file.
If your project is still CJS, either flip the consuming file to ESM:
…or load the SDK via dynamic import() from CJS:
tsx, ts-node with --esm, Next.js server routes, NestJS (with "type": "module"), Hono, and Cloudflare Workers all default to ESM and require no change.
2. Configure once at boot
AmbaClient.configure() is a one-time async call that returns the configured client. Hold the instance for the life of the process.
Set all three environment variables. AMBA_PROJECT_ID and AMBA_CLIENT_KEY come from your project's dashboard or CLI output. AMBA_SERVER_KEY is a separate credential — see Server keys below.
3. Server keys
A server key (amb_dev_sk_… / amb_live_sk_…) is a project-scoped backend credential analogous to a Firebase service account or Supabase service-role key. It grants access to project-level admin operations without requiring a developer login — making it safe to use in long-running services and CI pipelines.
Generate a server key:
Or via MCP:
Comparison to other credential types:
| Credential | Scope | Use case |
|---|---|---|
Developer PAT (amb_dpat_…) | Your account | One-time setup, project creation, CLI |
Client key (amb_dev_ck_… / amb_live_ck_…) | Project, client-side | Browser SDK, mobile SDK |
Server key (amb_dev_sk_… / amb_live_sk_…) | Project, server-side | Node SDK, asUser(), backend automation |
Server keys can authenticate all project-scoped admin operations but cannot create new projects or list projects across accounts — those require a developer PAT.
4. Per-request user scoping with asUser()
asUser(uid) returns a scoped handle that attributes every API call to the given app_user.id. It uses the server key + an internal on-behalf-of mechanism — no session token is minted or managed per user. This makes it efficient for bulk operations:
Bulk import — no round-trip auth per user:
asUser(uid) is O(1) — each call just captures the userId. The network request happens only when you call a method on the returned handle.
asUser(uid) returns a handle that:
- Wraps every read with the equivalent of
WHERE user_id = uid. - On
insert, sets theuser_idcolumn touid. - On
delete, restricts to rows whereuser_id = uid.
Amba validates that uid exists in your project before acting on any request — a userId from a different project is rejected.
5. First track (post-auth)
Without asUser(), the Node SDK has no user context and user-scoped client endpoints require one. Use asUser() with a server key for every request that needs to act on behalf of a specific user.
5. Connect/Express middleware
For request-handlers that always need the SDK, amba.middleware() returns a Connect-style factory that attaches req.amba to every incoming request:
For a per-request user-scoped handle, chain req.amba.asUser(req.session.userId) inside each handler.
Collections
Same DSL as the web SDK:
For full operator coverage (eq, ne, gt, gte, lt, lte, in, notIn, like, ilike, isNull, isNotNull, and, or, not) see collections.
Storage (presign + commit)
The Node SDK exposes presign and commit directly so the upload itself can flow through your server — useful for buffered uploads, validation, or virus scanning:
Push fan-out
If your service is the source of truth for "send a push to user X", call register() once when the device hands you a token, and use the push campaign API (admin) to fan out from your server:
Counting events
For dashboards, billing aggregations, or any "how many <event> events fired this week" question, hit the admin events/count endpoint with your server key. The Node SDK doesn't wrap this surface (track is the only SDK-side event method; reads are an admin concern).
See admin/events for the full filter shape (per-user, per-project segment, properties match).
SDK version
@layers/amba-node exports a runtime constant for telemetry / debug logging:
SDK_VERSION is also stamped onto every outbound request as X-SDK-Version: amba-node/<version> so the server can correlate behaviour to a specific SDK build.
AI proxy
Same prompt slug catalog as the client SDK — slugs are managed in the console and shared across server + browser usage.
Long-running processes
The Node SDK is safe for long-lived processes:
- The underlying amba core caches HTTP connections.
- Auth token refresh is automatic.
- There's no global state — multiple
AmbaClientinstances (e.g. one per tenant key in a multi-tenant proxy) are isolated.
For high-concurrency scenarios (10k+ rps), pool one AmbaClient per worker process rather than per request.
Common pitfalls
- Calling
AmbaClient.configure()per request — don't. The cold-start init is ~50ms; call once at boot, share the instance. - Forgetting
asUser(uid)in user-context handlers — the default surface is server-trusted; withoutasUseryou can accidentally read or mutate another user's data. Lint rule: every route handler that takes user input should explicitly chooseamba.asUser(uid)oramba(admin). - WebSocket / SSE proxies — auth state isn't shared with the browser; mint a short-lived session in the browser instead of proxying through Node.
See also
- Client API reference — HTTP endpoint reference for every namespace.
- Code samples — same operations side-by-side with the other 7 SDKs.