Send API
One endpoint, one key. The same address that receives can send — transactional mail, replies, and broadcasts go out over your own authenticated domain, DKIM-signed and aligned so they land in the inbox.
Send a message
POST /v1/send with an API key.
The from address must be on a verified domain. Pick your language —
the choice is remembered across the docs.
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>"
}' ← 202 Accepted
{ "id": "msg_2Hk9…", "status": "queued" }
A 202 Accepted means the message was queued for delivery. Use the
returned id to look it up later via the
Messages API.
Request fields
| Field | Type | Notes |
|---|---|---|
from | string | Required. An address on a verified domain. |
to | string · array | Required. One address or a list. |
subject | string | Subject line — required unless a template supplies it. |
html | string | HTML body. Provide html, text, or both. |
text | string | Plain-text body. Recommended alongside html. |
templateId | string | Send a saved template — a user template (tpl_…) or base template (base_…); explicit subject/html/text override it. |
templateData | object | Values for the template's {{merge_tags}} (e.g. { "name": "Ann" }). HTML values are auto-escaped. |
cc / bcc | string · array | Optional additional recipients. |
replyTo | string | Optional Reply-To address. |
attachments | array | Each: { filename, url } (fetched by us) or { filename, content } (base64). |
inReplyTo | string | A threadId/Message-ID to reply in-thread. |
Every snippet above is the official client library —
same shape in Node, Python, PHP, Java, Go, and Ruby — or raw curl.
Replying in-thread
To reply to something you received, set inReplyTo to the inbound
event's threadId. The reply threads correctly in the
recipient's client:
reply.json {
"from": "support@myapp.ai",
"to": "ada@example.com",
"subject": "Re: invoice #1042",
"text": "Approved — thanks!",
"inReplyTo": "<a1b2c3@mail.example.com>"
}
Attachments
Attach files two ways:
- By URL —
{ filename, url }. We fetch it at send time. Best for files you already host. - Inline —
{ filename, content, contentType } with base64 content. Best for small, generated files.
Deliverability
Outbound is DKIM-signed and SPF/DMARC-aligned automatically on your verified
domain — there's nothing to configure beyond
publishing your DNS records. Always send a
text part alongside html, keep your
from consistent, and warm new domains gradually for the best
inbox placement.
See every parameter and response in the
API reference.