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.
@opencoredev/email-sdk/primitiveConfigure
Create a Primitive API key (prefixed prim_) and verify the outbound domain you send from.
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 idOne 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 primitivePRIMITIVE_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-runDrop --dry-run for one real smoke send — the only check that proves the API key and sender domain are ready.
