---
title: "What is the Primitive Node.js SDK?"
canonical: "https://test.abhinandan.one/node-sdk-overview"
markdown_url: "https://test.abhinandan.one/node-sdk-overview.md"
publisher: "Primitive SDKs"
kind: "concept"
content_type: "reference"
category: "Node.js SDK"
description: "@primitivedotdev/sdk is a typed Node.js client with a root import for send/receive/reply and six subpaths for webhooks, payments, and the generated API."
keywords: ["@primitivedotdev/sdk", "primitive.receive", "primitive.client", "subpath exports", "PrimitiveApiClient", "createX402Client"]
last_modified: "2026-08-11T18:54:55.364199+00:00"
published_at: "2026-08-11T18:54:55.194931+00:00"
source_files:
  - "sdk-node/README.md"
sections:
  - {anchor: "the-default-import-is-deliberately-small", title: "The default import is deliberately small"}
  - {anchor: "subpath-export-map", title: "Subpath export map"}
  - {anchor: "why-the-surface-is-split-this-way", title: "Why the surface is split this way"}
  - {anchor: "a-concrete-example-three-subpaths-in-one-handler", title: "A concrete example: three subpaths in one handler"}
  - {anchor: "what-lives-outside-these-subpaths", title: "What lives outside these subpaths"}
  - {anchor: "next-steps", title: "Next steps"}
---

> Documentation index: https://test.abhinandan.one/llms.txt

# What is the Primitive Node.js SDK?

@primitivedotdev/sdk is the official Node.js client for Primitive's inbound/outbound email platform, exposing a small default surface for send/receive/reply plus dedicated subpaths for webhooks, x402 payments, the generated API client, and raw MIME parsing.

`@primitivedotdev/sdk` is the official Node.js library for [Primitive](https://primitive.dev), an email API for sending and receiving programmatic mail. It gives you a typed client for receiving and verifying inbound webhooks, sending mail, parsing raw MIME, calling the full HTTP API, and moving USDC with x402 payments.

Requires Node.js 22 or newer. Install it with:

```bash
npm install @primitivedotdev/sdk
```

> **Note:** Looking for the terminal instead of application code? The CLI ships as a separate package. Run `npm install -g primitive` (or `npx primitive@latest <command>`); `@primitivedotdev/sdk` no longer ships a `primitive` bin. See [What is the Primitive CLI?](https://test.abhinandan.one/cli-overview.md)

## The default import is deliberately small

The root import (`import primitive from "@primitivedotdev/sdk"`) covers the two things almost every integration needs on day one: receiving inbound webhook deliveries and sending mail.

```typescript
import primitive from "@primitivedotdev/sdk";

export const runtime = "nodejs";
export const maxDuration = 300;

const client = primitive.client({
  apiKey: process.env.PRIMITIVE_API_KEY!,
});

export async function POST(req: Request) {
  const email = await primitive.receive(req, {
    secret: process.env.PRIMITIVE_WEBHOOK_SECRET!,
  });

  await client.reply(email, "Thank you for your email.");

  return Response.json({ ok: true });
}
```

This is the shared receive-then-`send`/`reply`/`forward` model every SDK implements; see [Inbound and Outbound Email Model](https://test.abhinandan.one/email-model.md) for the field-by-field reference.

Everything past that default is reachable through a small set of subpath imports, each scoped to one job.

## Subpath export map

| Subpath | What it's for | Owning page |
| --- | --- | --- |
| `@primitivedotdev/sdk` (root) | `primitive.receive`, `primitive.client`, `client.send`/`reply`/`forward` | [Sending, Replying, and Forwarding Email](https://test.abhinandan.one/node-sdk-sending-email.md), [Receiving Inbound Email](https://test.abhinandan.one/node-sdk-receiving-email.md) |
| `@primitivedotdev/sdk/webhook` | `verifyWebhookSignature`, `handleWebhookEvent`, event type guards, download-token helpers | [Webhook Signature Verification](https://test.abhinandan.one/node-sdk-webhook-signing.md), [Handling Payment and Interaction Webhook Events](https://test.abhinandan.one/node-sdk-webhook-events.md) |
| `@primitivedotdev/sdk/api` | `PrimitiveApiClient`, `createPrimitiveClient`, `client.memories`, `isTrustedSender`, `validateEmailAuth`, `normalizeReceivedEmail`, the Workers-safe surface | [Generated API Client and Primitive Memories](https://test.abhinandan.one/node-sdk-api-client.md), [Verifying Inbound Email Authenticity](https://test.abhinandan.one/node-sdk-email-authenticity.md) |
| `@primitivedotdev/sdk/x402` | `createX402Client`, `parseEmailChallengeFromPart`, the low-level signing primitives | [x402 Payments Overview](https://test.abhinandan.one/x402-payments-overview.md), [Paying a Challenge](https://test.abhinandan.one/x402-payments-overview-04a296ff/node-sdk-x402-paying.md) |
| `@primitivedotdev/sdk/openapi` | The generated OpenAPI document export, for JavaScript consumers that need the raw spec | [OpenAPI Spec Normalization and Codegen Artifacts](https://test.abhinandan.one/openapi-spec-normalization.md) |
| `@primitivedotdev/sdk/contract` | `buildEmailReceivedEvent`, producer-side types for constructing schema-valid webhook fixtures | [Building Webhook Payloads (Contract Module)](https://test.abhinandan.one/node-sdk-contract-module.md) |
| `@primitivedotdev/sdk/parser` | `parseFromHeader`, `parseFromHeaderLoose`, raw MIME address parsing | [Raw MIME Address Parsing (parser/address)](https://test.abhinandan.one/node-sdk-parsing-email/node-sdk-address-parsing.md) |

Two subpaths matter architecturally, not just organizationally:

- **`/api` is Workers-safe.** It re-exports `isTrustedSender`, `validateEmailAuth`, and `normalizeReceivedEmail` specifically so Primitive Functions handlers, which run on an edge runtime, can make trust decisions and normalize inbound events without pulling in `node:crypto`. The root import and `/webhook` both pull `node:crypto` through the Node-crypto signing helpers and break a Workers-style bundle.
- **`/api` also carries the generated HTTP surface.** `PrimitiveApiClient` and the raw generated operations (`setMemory`, `getMemory`, `searchMemories`, `deleteMemory`, `getAccount`, and every other OpenAPI operation) live here, re-exported from the workspace-internal `@primitivedotdev/api-core` package. See [What is API Core?](https://test.abhinandan.one/api-core-overview.md) for how that package is built and bundled.

## Why the surface is split this way

The split mirrors how integrations actually grow. Most handlers start and stay on the root import: receive an email, reply to it, done. Some need signature verification without a standard `Request` object, where the framework hands you raw bytes and headers instead; that's `/webhook`. Some need Primitive Memories or an uncommon operation the high-level client doesn't wrap; that's `/api`. Only integrations doing agent-to-agent payments touch `/x402`, and only tooling that builds or tests webhook fixtures touches `/contract`.

Each subpath is a separate entry point, so a Next.js route that only replies to email never bundles the x402 signing code.

## A concrete example: three subpaths in one handler

A Primitive Function that replies to trusted senders, stores state in Primitive Memories, and settles an x402 payment touches three subpaths at once:

```typescript
import { createPrimitiveClient, isTrustedSender } from "@primitivedotdev/sdk/api";
import { createX402Client } from "@primitivedotdev/sdk/x402";

const client = createPrimitiveClient({ apiKey: process.env.PRIMITIVE_API_KEY! });
const x402 = createX402Client({ apiKey: process.env.PRIMITIVE_API_KEY! });

export default {
  async fetch(request: Request): Promise<Response> {
    const event = await request.json();

    const trust = isTrustedSender(event, { domain: "example.com" });
    if (!trust.trusted) {
      return new Response("untrusted sender", { status: 403 });
    }

    await client.memories.set({ key: "last_seen", value: { at: Date.now() } });

    const challenge = await x402.charge({ amountUsdc: "0.01", network: "base-sepolia" });
    return Response.json({ challenge });
  },
};
```

Every import here comes from `/api` or `/x402` rather than the root. That is exactly the Workers-safe path a Primitive Function needs.

## What lives outside these subpaths

Two capabilities ship as part of the SDK but aren't separate subpaths:

- **Primitive Payloads** (streaming large, end-to-end-encrypted attachments with `pushFile`/`pushBytes`/`pullFile`) backs `client.sendAttachment`, which picks inline delivery versus a payload reference by size for you. Inline attachments are the default under the inline size cap (~25-30 MiB). See [Primitive Payloads: Streaming Large Attachments](https://test.abhinandan.one/node-sdk-payloads.md).
- **Agent accounts** (`client.agent.createAccount`, the email-claim flow) hang off the same `client` object you get from `primitive.client(...)`. See [Agent Accounts](https://test.abhinandan.one/node-sdk-agent-accounts.md).
