Email SDK
Adapters

Primitive

Send through Primitive's email API for AI agents over fetch — base64 attachments and idempotent retries, with fail-fast validation for fields it cannot represent.

The Primitive adapter calls Primitive's POST /v1/send-mail endpoint over fetch — no extra dependency. Primitive is email infrastructure for AI agents: a REST API for sending and receiving mail, with idempotency, typed errors, and an async delivery model. The adapter maps the normalized EmailMessage straight onto its send payload.

Primitive logo
Primitive
@opencoredev/email-sdk/primitive
OfficialAPI testedRequest tested
Open website

Configure

Create a Primitive API key (prefixed prim_) and verify the outbound domain you send from.

lib/email.ts
import { createEmailClient } from "@opencoredev/email-sdk";
import { primitive } from "@opencoredev/email-sdk/primitive";

export const email = createEmailClient({
  adapters: [primitive({ apiKey: process.env.PRIMITIVE_API_KEY! })],
});

Prop

Type

Send

Primitive's send API targets a single recipient and accepts html, text, and attachments. Attachments are base64-encoded automatically.

const result = await email.send({
  from: "Acme <hello@acme.com>",
  to: "user@example.com",
  subject: "Welcome to Acme",
  html: "<p>Thanks for joining Acme.</p>",
  text: "Thanks for joining Acme.",
});

console.log(result.id); // Primitive sent-email id

One recipient, no CC or BCC

Primitive's send-mail accepts exactly one recipient and has no CC or BCC field. The adapter fails fast with an EmailValidationError when a message carries more than one recipient, cc, or bcc, so route fan-out to multiple people as separate sends.

No custom headers, tags, or metadata

Primitive's send API has no custom-header, tags, or metadata field, so the adapter rejects headers, tags, and metadata with an EmailValidationError before the request. Check field support before using Primitive in a fallback route.

From a verified outbound domain

The sender domain in from must be a verified outbound domain for your Primitive organization, and recipient eligibility depends on your account's outbound entitlements.

Idempotent sends

Pass an idempotencyKey and the adapter forwards it as Primitive's Idempotency-Key header, so a retried send with the same key and body replays the original result instead of sending twice.

await email.send(message, { idempotencyKey: "receipt:order_123" });

Verify from the CLI

PRIMITIVE_API_KEY="prim_..." npx email-sdk doctor --adapter primitive
PRIMITIVE_API_KEY="prim_..." npx email-sdk send \
  --adapter primitive \
  --from "Acme <hello@acme.com>" \
  --to user@example.com \
  --subject "Primitive smoke test" \
  --text "It works" \
  --dry-run

Drop --dry-run for one real smoke send — the only check that proves the API key and sender domain are ready.

On this page