The official Node.js/TypeScript SDK for the Mailgent API -- identity, mail, vault, calendar, Slack, social posting, and buyer-side x402 payments for AI agents.
- Zero dependencies (native
fetch) - ESM + CJS dual output
- Full TypeScript type definitions
- Node 18+
npm install @mailgent-dev/sdkimport { Mailgent } from "@mailgent-dev/sdk";
const client = new Mailgent({ apiKey: "mgnt-..." });
const { messages } = await client.mail.listMessages({ limit: 10 });Pay any x402-protected URL from your agent's own wallet. The SDK drives the
full handshake against api.mailgent.dev: discover the 402 challenge, check
your mandate caps, sign the EIP-3009 authorization, retry, and record.
const result = await client.payments.pay({ url: "https://api.example.com/paid" });
if (result.ok) {
// payment settled — proceed with result
}Spend caps are enforced server-side via mandates. Create one per project:
await client.payments.mandates.create({
maxPerCallUsdc: "0.10",
dailyCapUsdc: "5.00",
});Use client.payments.activity() for a bank-statement-style feed of payments
sent and received.
Mailgent sends X-Mailgent-Signature: sha256=<hex> (HMAC-SHA256 of the raw
request body) and X-Mailgent-Event / X-Mailgent-Idempotency-Key for
event type and de-duplication. Verify before trusting the body:
import { verifyWebhook } from "@mailgent-dev/sdk/webhook";
app.post(
"/webhooks/mailgent",
express.raw({ type: "application/json" }),
async (req, res) => {
const ok = await verifyWebhook(
req.body.toString(),
req.header("x-mailgent-signature"),
process.env.MAILGENT_WEBHOOK_SECRET!,
);
if (!ok) return res.status(400).send("invalid signature");
// de-dupe on req.header("x-mailgent-idempotency-key"), then handle.
// Today the only event type is `payment.received`.
},
);Web Crypto under the hood — same helper runs on Node, Bun, Deno, and Cloudflare Workers.
Create an API key in the Mailgent Console. Keys are prefixed with mgnt-.
Pass the key directly:
const client = new Mailgent({ apiKey: "mgnt-..." });Or load from an environment variable:
const client = new Mailgent({ apiKey: process.env.MAILGENT_API_KEY });const identity = await client.identity.whoami();The vault is password-manager-style encrypted secret storage (AES-256-GCM at rest). Use client.vault.store() for arbitrary types, or the typed helpers below.
// Simple API key
await client.vault.storeApiKey("stripe", "sk_live_...");
// OAuth-style client credentials (client id + secret)
await client.vault.storeApiKey("twitter", {
clientId: "abc123",
secret: "def456",
});
// Credit card (encrypted at rest — this is a secret vault, not a payment processor)
await client.vault.storeCard("personal-visa", {
cardholder: "Jane Doe",
number: "4242 4242 4242 4242",
expMonth: "12",
expYear: "2029",
cvc: "123",
zip: "94103",
}, { metadata: { brand: "Visa" } });
// Shipping address
await client.vault.storeShippingAddress("home", {
name: "Autonomous Agent",
line1: "1 Demo Way",
city: "San Francisco",
state: "CA",
postcode: "94103",
country: "US",
});Supported credential types: LOGIN, API_KEY, OAUTH, TOTP, SSH_KEY, DATABASE, SMTP, AWS, CERTIFICATE, CARD, SHIPPING_ADDRESS, CUSTOM.
Connect a Slack workspace once, then send and poll messages from your agent. Requires the slack:read / slack:send scopes.
// One-time setup: open installUrl in a browser and authorize the workspace
const { installUrl } = await client.slack.connect();
// Send a message (the bot must be invited to the channel first)
const { ts } = await client.slack.sendMessage({
channel: "C0123456789",
text: "Deploy finished ✅",
});
// Reply in-thread, and poll for inbound messages
await client.slack.sendMessage({ channel: "C0123456789", text: "Details…", threadTs: ts });
const { messages } = await client.slack.listMessages({ channel: "C0123456789", since: "2026-06-01T00:00:00Z" });Use client.slack.connection(), listChannels(), and disconnect() to inspect or remove the workspace connection.
Post to connected social accounts. Requires the social:read / social:write scopes. Connecting accounts is console-only (Settings → Integrations) — agents cannot initiate connections.
const { accounts } = await client.social.listAccounts();
// Post to all connected accounts (or filter by accountIds / platforms)
const { postId } = await client.social.createPost({
text: "We just shipped v2 🚀",
mediaUrls: ["https://example.com/banner.png"],
scheduledAt: "2026-06-15T09:00:00Z", // omit to post immediately
});
// Posting is asynchronous — poll for per-platform results
const { post, results } = await client.social.getPost(postId);The SDK also exposes client.mail, client.calendar, client.logs, and client.did. See the full reference at docs.mailgent.dev for request/response shapes, pagination, and end-to-end examples.
All API errors are thrown as MailgentApiError with structured fields:
import { Mailgent, MailgentApiError } from "@mailgent-dev/sdk";
try {
await client.mail.send({ to: "test@example.com", subject: "Hi", text: "Hello" });
} catch (e) {
if (e instanceof MailgentApiError) {
console.error(e.status); // HTTP status code
console.error(e.code); // API error code
console.error(e.message); // Human-readable message
}
}The SDK exports all request and response types:
import type {
MailgentConfig,
MessageResponse,
ThreadResponse,
ThreadDetailResponse,
PaginatedMessages,
PaginatedThreads,
VaultCredentialType,
CredentialMetadata,
CredentialWithData,
VaultList,
TotpResponse,
IdentityResponse,
ActivityLog,
PaginatedLogs,
LogsStatsResponse,
DidDocument,
} from "@mailgent-dev/sdk";MIT