mailkite
v0.20.0
Published
Official MailKite SDK for Node.js — send and manage email over your own authenticated domain.
Maintainers
Readme
Read-only mirror. This repo is a generated, release-time mirror of the MailKite monorepo (the private source of truth) — development doesn't happen here. Install from npm and open issues against the MailKite docs.
Install
npm install mailkiteQuickstart
import { MailKite } from "mailkite";
const mk = new MailKite(process.env.MAILKITE_API_KEY);
const { id, status } = await mk.send({
from: "[email protected]",
to: "[email protected]",
subject: "Your invoice #1042",
html: "<p>Thanks! Receipt attached.</p>",
});Self-hosted server
Point the SDK at an OSS MailKite Server with the same API key and a custom base URL. Both the positional form and the options form are supported:
const mk = new MailKite({
apiKey: process.env.MAILKITE_API_KEY, // mk_local_…
baseUrl: "https://mail.example.com",
});The server exposes the compatible send/receive surface at /v1/send, /v1/send/batch,
/v1/me, and /api/messages. See the OSS server's developer API documentation
for supported fields, self-hosted differences, and the planned full API scope.
Templates
A message body can come from three places, interchangeably with plain html/text.
A saved template, rendered server-side. {{merge_tags}} are filled from templateData:
await mk.send({
from: "[email protected]",
to: "[email protected]",
templateId: "tpl_a878c1",
templateData: { name: "Ada", invoice: "1042" },
});A React component, rendered in your process. Install the optional peer dependency @react-email/render (or @react-email/components) to use this — the SDK itself stays dependency-free:
import { Welcome } from "./emails/welcome";
await mk.send({
from: "[email protected]",
to: "[email protected]",
subject: "Welcome aboard",
react: <Welcome name="Ada" />,
});The plaintext part is derived from the same component automatically, so you get a proper multipart message without writing the body twice. Pass text yourself to override it.
A local file — .html, .htm or .txt, read off disk (Node only):
await mk.send({
from: "[email protected]",
to: "[email protected]",
subject: "Welcome aboard",
templateFile: "./emails/welcome.html", // ./emails/welcome.txt becomes the text part
templateData: { name: "Ada" },
});react and templateFile are resolved inside the SDK: the API only ever sees html/text. Both work on sendBatch (rendered once for the whole batch), createTemplate and createBroadcast too — so createTemplate({ react: <Welcome /> }) turns a component into a stored tpl_… id the dashboard, sequences and every other MailKite SDK can send.
{{merge_tags}} left in a rendered component or file are still substituted from templateData by the API, exactly as they are in a stored template.
Examples
Runnable examples live in examples/ — send mail, verify webhooks, build an AI email agent, and log users in:
| Example | What it shows |
| --- | --- |
| examples/01-send-email.mjs | Send an email over a verified domain — the 10-second "it works". |
| examples/02-receive-webhook.mjs | Receive inbound email as a webhook — and VERIFY the signature before trusting it. |
| examples/03-agent-email-reply.mjs | An AI email agent in ~40 lines: inbound email → Claude drafts a reply → MailKite sends it, |
| examples/04-give-your-agent-an-inbox.mjs | Give your agent its own email address — let MailKite's built-in inbox agent answer mail |
| examples/05-server-login.mjs | Server-side login + register — let YOUR users sign into THEIR own MailKite account. |
| examples/06-react-email-template.mjs | Send a React email — and a local .html file — with the same call. |
API methods
Every method is documented on its own page under docs/. The full surface:
| Method | What it does |
| --- | --- |
| send | Send a message over a verified domain. Pass templateId (+ optional templateData) to… |
| sendBatch | Send one personalized message per recipient (up to 50) in a single call. Shared fields… |
| sendEvent | Record one application-level fact about a user — user.created, trial.expiring… |
| listEvents | List recorded events, newest first — the surface for confirming a POST landed and for… |
| listEventNames | List the distinct event names this account works with, so an editor can offer them… |
| listSequences | List your sequences, newest first, each with live enrollment counts. Archived sequences… |
| createSequence | Create a sequence: a declared input shape, the steps a contact walks over time, and zero… |
| getSequence | Get one sequence with its definition and live enrollment counts. |
| updateSequence | Edit a sequence. Changing the STEPS bumps its version and contacts already in flight keep… |
| deleteSequence | Delete a sequence and retire every contact still walking it. The response reports how… |
| listTriggers | List the triggers attached to a sequence — the doors into it. |
| createTrigger | Attach a trigger: when this event arrives, enroll the contact it is about. Attaching… |
| updateTrigger | Edit a trigger, or toggle enabled to switch the door off without deleting it. Either… |
| deleteTrigger | Detach a trigger. Stops future enrollments through that door and nothing else. |
| startSequence | Start a sequence for one contact, directly — when your code already knows WHICH sequence… |
| stopSequence | Stop whatever is chasing someone. Pass the cancelKey you set when starting — so you… |
| listEnrollments | List who is in a sequence and where each of them is. Filter with status. |
| getEnrollment | Get one enrollment — which sequence, which step, and what happens next. |
| listEnrollmentRuns | Every step this enrollment has executed, with the outcome and the reason for it. This is… |
| cancelEnrollment | Cancel one specific run by its enrollment id — the per-row action when you are looking at… |
| uploadAttachment | Upload a file to MailKite storage and get back a secure, time-limited URL. Reference the… |
| listTemplates | List your saved email templates (light metadata only — no body). Use getTemplate for the… |
| listBaseTemplates | List the premade base templates (light metadata). Clone one with createTemplate({ baseId… |
| getTemplate | Get one template (full: subject, html, text, theme). Works for your templates (tpl_…) and… |
| createTemplate | Create a template. Pass baseId to clone a base template into your own, or provide… |
| listDomains | List your domains, each with its webhook URL. |
| createDomain | Add a domain. Returns the domain + DNS records. Paid plans may pass email_provider_id… |
| suggestSubdomain | Suggest a free, currently-unclaimed subdomain label to prefill the input with, plus the… |
| checkSubdomain | Check whether a free subdomain label can be claimed. Read-only and cheap — call it as the… |
| claimSubdomain | Claim a free MailKite subdomain — a <label>.<base> host on a zone we run (call… |
| getDomain | Get one domain with DNS records + webhook. |
| deleteDomain | Remove a domain. |
| verifyDomain | Check DNS and update status. |
| setWebhook | Set or replace the domain's catch-all webhook. |
| setTrackingWebhook | Set or replace the domain's dedicated tracking-event webhook: an HTTPS endpoint that… |
| deleteTrackingWebhook | Remove the domain's tracking-event webhook (engagement events stop). |
| setWebhookEvents | Opt the domain's inbound webhook into engagement events — one webhook, all events. Pass… |
| deleteWebhookEvents | Opt the domain's inbound webhook back out of engagement events (inbound email.received… |
| deleteWebhook | Remove the domain's webhook. |
| getWebhookSecret | Get this domain's webhook signing secret (whsec_…) — the per-route secret used to verify… |
| testWebhook | Send a signed test event to the domain's webhook. |
| checkDomainAvailability | Check whether a domain is available to register, and at what price. Read-only — no charge. |
| registerDomain | Register (buy) a domain on the customer's behalf; provisions mail DNS and adds it to the… |
| listRoutes | List inbound routing rules. |
| createRoute | Create a route (match, action, destination). |
| deleteRoute | Delete an inbound routing rule by id. Pair with createRoute to register and tear down a… |
| agent | Send a message to one of your inbox agents and get its reply. Defaults to the account's… |
| route | Route a message to one of your registered routes (by routeId or address), running… |
| listMessages | List stored messages, newest first. Optionally filter with search (matches sender… |
| getMessage | Get a message with deliveries + attachments. |
| retryDelivery | Re-deliver a stored message to its webhook. |
| retryDeliveries | Replay a whole selection of webhook deliveries in one call — the bulk form of… |
| listDeliveryAttempts | Every captured attempt for one delivery, newest first: the request headers and payload we… |
| deliverToRoute | POST stored messages to one webhook route — including messages that arrived BEFORE the… |
| listRouteCandidates | Stored inbound messages this route could be asked to deliver, newest first — the preview… |
| createRealtimeToken | Mint a short-lived, single-use token that authorises one Realtime API connection. For… |
| listLists | List your contact lists (static, curated broadcast audiences), each with its member count. |
| createList | Create a contact list. Returns the list with its id (lst_…); add contacts with… |
| getList | Get one contact list with its member count. |
| updateList | Rename a contact list. |
| deleteList | Delete a contact list. The list is removed; the contacts themselves are kept. |
| listListContacts | List the contacts that are members of a list, newest first. Optionally page with before… |
| addListContacts | Add contacts (by id, ctr_…) to a list. Returns how many were newly added; contacts… |
| removeListContact | Remove one contact from a list (the contact itself is kept). |
| listBroadcasts | List your broadcasts (one-to-many sends) with status and send stats. |
| createBroadcast | Create a broadcast draft. from is required; set audience to { type: "all" } or {… |
| getBroadcast | Get one broadcast with its status and recipient summary. |
| updateBroadcast | Edit a draft broadcast (any of from/subject/audience/html/… ). Drafts only. |
| deleteBroadcast | Delete a broadcast draft. |
| sendBroadcast | Send a broadcast now, or pass an ISO 8601 scheduledAt to schedule it. A one-click… |
| verifyWebhook | Verify the x-mailkite-signature header on an inbound webhook delivery. Runs entirely… |
| replyOk | The acknowledgement body a webhook consumer returns to confirm it processed the event —… |
| replySpam | Control-mode reply a webhook consumer returns to tell MailKite to mark the message as… |
| replyDrop | Control-mode reply a webhook consumer returns to tell MailKite to drop (discard) the… |
| replyBlockSender | Control-mode reply a webhook consumer returns to tell MailKite to block the sender — the… |
| encrypt | Encrypt a UTF-8 string to a domain's RSA public key (SPKI/PEM), returning the at-rest… |
| decrypt | Decrypt a MailKite at-rest envelope JSON with your RSA private key (PKCS8/PEM), returning… |
| semanticSearch | Semantic search over the MailKite documentation — returns the most relevant doc sections… |
| registerOauthClient | Register an OAuth client for this installation (RFC 7591 dynamic client registration) —… |
| exchangeOauthToken | Exchange an authorization code for an access token (or rotate a refresh token) — step 3… |
| getApiKey | Get the account's unrestricted API key (mk_live_…). Read-or-create: the first call mints… |
| rotateApiKey | Rotate the account API key: the old key stops working immediately and a fresh one is… |
| listScopedKeys | List the account's domain-scoped API keys. A scoped key can send and manage only its one… |
| createScopedKey | Create a key scoped to one domain. Ideal for per-site installs (e.g. a WordPress plugin)… |
| deleteScopedKey | Revoke a domain-scoped key. Takes effect immediately. |
| listAppPasswords | List the account's app passwords. Each one opens a mailbox over IMAP and/or the mailbox… |
| createAppPassword | Create an app password for one domain and address pattern. Hand it to a mail client or an… |
| updateAppPassword | Change what an app password covers — its label, address pattern, or protocols. The domain… |
| rotateAppPassword | Replace an app password's secret, keeping its scope. The old secret stops authenticating… |
| deleteAppPassword | Revoke an app password. Takes effect immediately — any IMAP session or API call using it… |
| listMailboxMessages | List a mailbox's messages, newest first. Authenticated with an app password granting… |
| getMailboxMessageRaw | Fetch one message's raw RFC822 bytes from a mailbox. Same app password auth as the list. |
| setMailboxMessageFlags | Replace a message's IMAP flags (e.g. mark it Seen). Flags set here are the same ones an… |
| getUsage | Current billing-period usage: emails used vs the plan's included bucket (null =… |
| listSuppressions | List suppressed addresses (unsubscribes, hard bounces, spam complaints, manual). Sends to… |
| addSuppression | Suppress an address so this account never sends to it again (reason defaults to manual). |
| removeSuppression | Remove an address from the suppression list (URL-encode the email in the path). Removing… |
| register | Create a MailKite account from just an email — no password. Returns the new account's API… |
| me | The account behind this credential: email, whether it is verified (sending is blocked… |
Use it from an AI agent — MCP + Agent connectors
MailKite speaks the Model Context Protocol: every API method is a tool your AI assistant (Claude, Cursor, …) can call — send mail, manage domains, search the docs, and give an agent its own inbox. Full guide: https://mailkite.dev/docs/ai-agents.
Hosted (recommended) — one-click OAuth, no key to copy:
claude mcp add --transport http mailkite https://mcp.mailkite.dev/mcpIn Claude Code you can also install the plugin:
/plugin marketplace add mailkite/claude-code
/plugin install mailkite@mailkiteAny chat/UI agent: "Add the MCP server at https://mcp.mailkite.dev/mcp and authenticate in the browser when prompted."
Local (static key, offline / CI):
{ "mcpServers": { "mailkite": { "command": "npx", "args": ["-y", "@mailkite/mcp"], "env": { "MAILKITE_API_KEY": "mk_live_…" } } } }Give an agent its own inbox. Route inbound mail to a built-in inbox agent (the agent route action) and it answers, files, or escalates on its own — see https://mailkite.dev/docs/ai-agents.
All MailKite libraries
Same contract, every language — pick the one for your stack (full list: https://mailkite.dev/docs/libraries):
| Library | Repo | Distribution |
| --- | --- | --- |
| MailKite for Node.js (this repo) | mailkite-node | npm |
| MailKite for Python | mailkite-python | PyPI |
| MailKite for Ruby | mailkite-ruby | RubyGems |
| MailKite for Java | mailkite-java | Maven Central |
| MailKite for PHP | mailkite-php | Packagist |
| MailKite for Go | mailkite-go | Go modules |
| @mailkite/cli | mailkite-cli | npm |
| @mailkite/mcp | mailkite-mcp | npm |
| @mailkite/client | mailkite-js | npm |
| @mailkite/expo | mailkite-expo | npm |
| MailKiteClient | mailkite-swift | Swift Package Manager |
| dev.mailkite:mailkite-client | mailkite-kotlin | Maven Central |
| mailkite_client | mailkite-flutter | pub.dev |
Docs & links
- 📚 Documentation: https://mailkite.dev/docs
- 📦 This library's guide: https://mailkite.dev/docs/libraries
- 🤖 AI agents (MCP + inbox agents): https://mailkite.dev/docs/ai-agents
- 🌐 Website: https://mailkite.dev
- 🧭 All libraries: https://mailkite.dev/docs/libraries
Generated from the shared MailKite API contract. © MailKite.
