Client libraries
The MailKite API is plain JSON over HTTPS, so any stack works
— reach for curl or your language's HTTP client and you're done.
For the common languages we also ship thin official libraries with one shared
shape: a low-level request() plus one function per endpoint.
Supported languages
| Language | Package | Install |
|---|---|---|
| Node.js | mailkite | npm install mailkite |
| Python | mailkite | pip install mailkite |
| Go | github.com/mailkite/mailkite-go | go get github.com/mailkite/mailkite-go |
| PHP | mailkite/mailkite | composer require mailkite/mailkite |
| Java | dev.mailkite:mailkite | Maven |
| Ruby | mailkite | gem install mailkite |
| Any other | — | Raw HTTP (curl tab below) |
Quick start
Create an API key in the dashboard
(mk_live_…), set it as MAILKITE_API_KEY, then install
and send. Pick your language once — every example on this page (and across the
docs) follows your choice.
Install
npm install mailkitepip install mailkitecomposer require mailkite/mailkite<!-- pom.xml -->
<dependency>
<groupId>dev.mailkite</groupId>
<artifactId>mailkite</artifactId>
<version>0.1.0</version>
</dependency>go get github.com/mailkite/mailkite-gogem install mailkite# nothing to install — curl is enough Send a message
Dashboard → Send
From hello@myapp.ai
To ada@example.com
Subject Your invoice #1042
Body Thanks! Receipt attached.
Click [ Send ]Email ada@example.com from hello@myapp.ai
with subject "Your invoice #1042" and body "Thanks! Receipt attached."import { MailKite } from "mailkite";
const mk = new MailKite(process.env.MAILKITE_API_KEY);
const { id, status } = await mk.send({
from: "hello@myapp.ai",
to: "ada@example.com",
subject: "Your invoice #1042",
html: "<p>Thanks! Receipt attached.</p>",
});import os
from mailkite import MailKite
mk = MailKite(os.environ["MAILKITE_API_KEY"])
res = mk.send({
"from": "hello@myapp.ai",
"to": "ada@example.com",
"subject": "Your invoice #1042",
"html": "<p>Thanks! Receipt attached.</p>",
})<?php
$mk = new \MailKite\Client(getenv('MAILKITE_API_KEY'));
$res = $mk->send([
'from' => 'hello@myapp.ai',
'to' => 'ada@example.com',
'subject' => 'Your invoice #1042',
'html' => '<p>Thanks! Receipt attached.</p>',
]);MailKite mk = new MailKite(System.getenv("MAILKITE_API_KEY"));
Object res = mk.send(Map.of(
"from", "hello@myapp.ai",
"to", "ada@example.com",
"subject", "Your invoice #1042",
"html", "<p>Thanks! Receipt attached.</p>"
));mk := mailkite.New(os.Getenv("MAILKITE_API_KEY"))
res, err := mk.Send(mailkite.Message{
From: "hello@myapp.ai",
To: "ada@example.com",
Subject: "Your invoice #1042",
HTML: "<p>Thanks! Receipt attached.</p>",
})require "mailkite"
mk = Mailkite::Client.new(ENV["MAILKITE_API_KEY"])
res = mk.send(
"from" => "hello@myapp.ai",
"to" => "ada@example.com",
"subject" => "Your invoice #1042",
"html" => "<p>Thanks! Receipt attached.</p>"
)curl https://api.mailkite.dev/v1/send \
-H "Authorization: Bearer $MAILKITE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "hello@myapp.ai",
"to": "ada@example.com",
"subject": "Your invoice #1042",
"html": "<p>Thanks! Receipt attached.</p>"
}'
The curl tab is always there if there's no library for your
language — every endpoint is a plain JSON request with a Bearer
token. See the API reference for the rest.
One shape, every language
Each library exposes the same surface — a low-level request(method, path, body)
and one thin method per endpoint. Only naming adapts to each language's
convention (Go exports methods in PascalCase, e.g.
mk.Send(…)).
| send(message) | POST | /v1/send |
| listDomains() | GET | /api/domains |
| createDomain({ domain }) | POST | /api/domains |
| getDomain(id) | GET | /api/domains/:id |
| deleteDomain(id) | DELETE | /api/domains/:id |
| verifyDomain(id) | POST | /api/domains/:id/verify |
| setWebhook(id, { url }) | PUT | /api/domains/:id/webhook |
| deleteWebhook(id) | DELETE | /api/domains/:id/webhook |
| testWebhook(id) | POST | /api/domains/:id/webhook/test |
| listRoutes() | GET | /api/routes |
| createRoute({ match, action, destination }) | POST | /api/routes |
| listMessages() | GET | /api/messages |
| getMessage(id) | GET | /api/messages/:id |
| retryDelivery(id) | POST | /api/deliveries/:id/retry |
| verifyWebhook(signature, payload, secret) | local | — HMAC check, no request |
Tested against one contract
Every library is held to the same contract. A shared set of
JSON-Schema-validated test cases lives alongside the SDKs, and a
cross-language conformance harness drives each library through them — checking
that the HTTP request it produces matches the schema and that responses and
errors are parsed identically. So the Python send() and the Go
Send() are guaranteed to put the same bytes on the wire.
AI agents: MCP server
@mailkite/mcp is a
Model Context Protocol
server that exposes MailKite to LLM agents — Claude Desktop, Claude Code,
Cursor, and any MCP client. It's a thin layer over the same contract the SDKs
use: one tool per endpoint (mailkite_send,
mailkite_create_domain, …), with inputs validated against the
shared JSON Schemas before any request is made.
In Claude Code, one command adds it (use -s user for every project):
claude mcp add mailkite -e MAILKITE_API_KEY=mk_live_… -- npx -y @mailkite/mcp For Claude Desktop, Cursor, or any other client, add this to its MCP config and restart:
{
"mcpServers": {
"mailkite": {
"command": "npx",
"args": ["-y", "@mailkite/mcp"],
"env": { "MAILKITE_API_KEY": "mk_live_…" }
}
}
} Full per-client steps and the tool list are on Agent inboxes & MCP.
Terminal: the CLI
Prefer the command line? @mailkite/cli is
a wrangler-style client built on the same Node SDK — sign in, add domains, set
DNS + webhooks, send mail, and tail inbound messages, all from your shell.
npx @mailkite/cli send --from hello@mail.myapp.ai \
--to you@example.com --subject "It works" --html "<p>Hi</p>" Next: the CLI reference, the full API reference, or the Send API for attachments and in-thread replies.