Skip to main content
@usenaive-sdk/node is the primary way to wire Naive into a multi-tenant app. It mirrors the REST API 1:1 with typed methods and a Stripe-style scoped-client pattern.
import { Naive } from "@usenaive-sdk/node";
const naive = new Naive({ apiKey: process.env.NAIVE_API_KEY! });

Scoped clients — no polymorphic args

Top-level data-plane calls act on your default user:
await naive.cards.create({ spending_limit_cents: 25000 });
await naive.vault.put("instantly.api_key", "key_xyz");
naive.forUser(id) returns the same surface bound to a specific tenant user:
const client = naive.forUser(alice.id);
await client.cards.create({ spending_limit_cents: 25000 });
await client.vault.put("instantly.api_key", "key_xyz");
There is no userId | {args} overloading — vault.put(key, value) always means (key, value). The scope is fixed by which client you got the sub-client from.

Control plane vs data plane

  • Control plane (naive.users, naive.accountKits, naive.plans, naive.toolkits) lives only on the root — these operate at company scope.
  • Data plane (cards, trading, email, verification, formation, domains, social, connections, vault, logs, sessions, images, video, search, clips, llm, browser, profile, seo, aeo, cron, jobs, memory, billing, webhooks, plus the build primitives apps, database, storage, functions, auth) is available on both the root (default user) and on forUser(id).
The build primitives operate on a fullstack app’s Supabase project — naive.apps.create({ name, type: "fullstack" }) first, then naive.database / naive.storage / naive.functions / naive.auth (own project), or naive.forUser(id).database for an end-user’s project.

When to use the SDK vs CLI vs MCP

  • SDK — embedding Naive in your multi-tenant SaaS backend.
  • CLI — you, a developer, using Naive from a terminal (acts on your default user).
  • MCP — handing tools to an MCP-native agent (Claude, Cursor).
The SDK is server-only in v1 (API keys are server secrets).