Cookbook
Primitive Cookbook: Email SDK, CLI & x402 Payments
Official Primitive recipes: install the CLI, receive and reply to inbound email with the Node SDK, and run non-custodial x402 USDC payments.
Primitive is an inbound and outbound email platform built for AI agents: you receive an inbound email, inspect a normalized email object, and send, reply, or forward synchronously. This cookbook covers the two surfaces you'll touch first: the primitive CLI (installed with npm install primitive, also available as prim) and the Node.js SDK (@primitivedotdev/sdk), plus the non-custodial x402 USDC payments flow that ships with both.
Every recipe below uses only commands and functions that exist in the Primitive SDKs monorepo today: the CLI binaries primitive/prim, the primitive payments command group, and the SDK's client(), receive(), and reply() calls. For the full REST surface and generated clients, fetch the OpenAPI spec directly, covered in the last recipe.
How to install and explore the Primitive CLI#
You want a terminal-based way to interact with Primitive before wiring the SDK into an application, or you want to run the x402 payments flow interactively.
Prerequisites
- Node.js and npm installed
npm install primitive
# Run the CLI locally (no global install needed)
npx primitive --help
# The CLI also ships under a shorter alias
npx prim --help
npm install primitive installs the Primitive CLI package locally in your project, which exposes two equivalent binaries: primitive and the shorter prim. Since you installed locally rather than globally, run either one through npx (or add ./node_modules/.bin to your PATH). --help is the standard entry point for discovering every top-level command group the installed CLI version ships, including the payments commands covered later in this cookbook.
Expected output
A usage banner followed by a list of available topics and commands (including a `payments` command group), printed to stdout.
Gotchas
- If you installed with
npm install primitive(no-g), theprimitive/primbinaries are not on your global PATH; usenpx primitive ...or referencenode_modules/.bin/primitivedirectly. primitiveandprimare the same CLI under two names, not two different tools.
How to receive an inbound email and reply with the Node.js SDK#
You run a webhook endpoint that needs to accept an inbound email, inspect it, and send an automatic reply in the same request.
Prerequisites
- npm install @primitivedotdev/sdk
- A PRIMITIVE_API_KEY for outbound sending
- A PRIMITIVE_WEBHOOK_SECRET configured for your inbound webhook endpoint
import primitive from "@primitivedotdev/sdk";
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 });
}
primitive.client({ apiKey }) creates the outbound client used to send, reply, or forward. primitive.receive(req, { secret }) verifies and parses the incoming webhook request into a normalized email object, using PRIMITIVE_WEBHOOK_SECRET to confirm the request actually came from Primitive. client.reply(email, "...") sends the reply synchronously as part of the same request, continuing the original thread. This exact shape is the default inbound/outbound workflow for every Primitive SDK, not just Node.js.
Expected output
HTTP 200 response with body `{"ok":true}`, and the sender of the original email receives a reply with the body "Thank you for your email."
Gotchas
primitive.receivewill reject the request ifsecretdoes not match the secret configured for that webhook endpoint, so keepPRIMITIVE_WEBHOOK_SECRETin sync between your deployment and your Primitive webhook configuration.client.replysends synchronously; if it throws, your handler will not return{ ok: true }, so wrap it in error handling for production endpoints.- This route handler shape assumes a framework (e.g. Next.js Route Handlers) that passes a standard
Requestobject toPOST; adapt the request extraction if your framework wraps requests differently.
How to discover the x402 payments commands from the terminal#
You want to run the non-custodial x402 USDC payment flow (register a payout address, request a payment, sign and settle) without writing any code.
Prerequisites
- Primitive CLI installed (
npm install primitive)
npx primitive payments --help
# equivalent, shorter alias
npx prim payments --help
primitive payments is the CLI command group for the same non-custodial x402 flow the SDKs expose: one agent registers a payout address and requests a USDC payment, and the paying agent signs locally with its own key and settles, with private keys never leaving the caller. Run --help on the installed CLI version to see the exact subcommands available to you, since a terminal-first flow is the fastest way to test payments before scripting them into an SDK integration.
Expected output
A usage banner listing the subcommands under the `payments` topic for your installed CLI version.
Gotchas
- The x402 flow supports exactly two networks:
baseandbase-sepolia. Usebase-sepoliafor testing before moving tobasefor mainnet settlement. - Because the flow is non-custodial, whichever key you configure locally for the paying agent is the key that signs and pays; Primitive never holds it.
How to convert USDC amounts into x402 base units#
x402 payment amounts must be passed as token base units, not human-readable decimal amounts, and getting this wrong sends the wrong amount.
Prerequisites
- Node.js installed
const USDC_DECIMALS = 6;
function toBaseUnits(amountInUsdc: number): string {
return Math.round(amountInUsdc * 10 ** USDC_DECIMALS).toString();
}
console.log(toBaseUnits(0.01)); // "10000"
console.log(toBaseUnits(1)); // "1000000"
Every x402 payment amount in Primitive is expressed in token base units as a string, not a decimal number. USDC has 6 decimals, so 0.01 USDC is the string "10000" and 1 USDC is "1000000". Run this conversion before passing an amount into any payments call (SDK or CLI) so you never accidentally send 100x or 1,000,000x the intended amount.
Expected output
10000
1000000
Gotchas
- The amount must be a string (e.g.
"10000"), not a JavaScript number, when you pass it to a payments call. - This conversion is specific to USDC's 6 decimals; a different token with a different decimal count would need a different multiplier.
How to fetch the Primitive OpenAPI spec for advanced integrations#
You need the raw REST API surface (for generating your own client, or covering functionality outside the default receive/client/send/reply/forward flow).
Prerequisites
- curl or an HTTP client
curl -o primitive-openapi.json https://www.primitive.dev/openapi.json
The SDKs cover the default inbound/outbound and payments workflows, but Primitive also publishes its full OpenAPI specification at https://www.primitive.dev/openapi.json. Use this file to generate a client in a language without an official SDK, or to inspect endpoints not covered by the default receive/client/send/reply/forward shape. Pair it with the REST reference at docs.primitive.dev/docs/api and the authentication guide at docs.primitive.dev/docs/auth.
Expected output
A `primitive-openapi.json` file saved in your current directory containing the full OpenAPI document.
Gotchas
- Treat the OpenAPI spec as an advanced/escape-hatch surface; the SDK's default
client()/receive()/reply()flow is the recommended path for standard inbound/outbound automation. - Re-fetch the spec periodically since it reflects the live API and can change between releases.
FAQ#
What is the difference between the primitive CLI and the @primitivedotdev/sdk Node.js package?#
primitive (installed with npm install primitive, aliased as prim) is the terminal CLI for running flows like primitive payments interactively. @primitivedotdev/sdk is the Node.js library you import into your own code to call primitive.client(), primitive.receive(), and client.reply() inside an application.
What does Primitive's default SDK workflow look like?#
Receive an inbound email with receive(...), create an outbound client with client(...), then send new mail with send(...), continue a thread with reply(...), or forward a message with forward(...), all synchronously.
Which blockchain networks does x402 payments support?#
Two networks: base and base-sepolia. Use base-sepolia for testing and base for production settlement.
How are x402 payment amounts specified?#
As a string in token base units. USDC has 6 decimals, so "10000" represents 0.01 USDC.
Is the x402 payments flow custodial?#
No. It is non-custodial: the paying agent signs locally with its own key and settles the payment, and keys never leave the caller.
Key takeaways#
- The default Primitive workflow is receive an inbound email, inspect the normalized object, then send, reply, or forward synchronously.
npm install primitivegives you two equivalent CLI binaries,primitiveandprim.- The Node.js SDK package is
@primitivedotdev/sdk, imported as the default exportprimitive, exposingclient(),receive(), andreply(). - x402 payments are non-custodial, support only
baseandbase-sepolianetworks, and use string amounts in token base units (USDC has 6 decimals). - The
primitive paymentsCLI command group mirrors the SDK's x402 payments flow for terminal-based testing. - For anything outside the default flow, fetch the live OpenAPI spec from
https://www.primitive.dev/openapi.json.