Skip to main content

Features

REST API

One authenticated POST sends an email. A single endpoint, a key scoped to a verified domain, and delivery events pushed back to you as webhooks.

A single send endpoint

Sending is one endpoint, POST /emails, on the base URL https://api.mailkube.com/mta/v1. A send carries raw content, html or text or both, or a saved template referenced by template_id. There is nothing else to learn before the first message goes out.

curl -X POST https://api.mailkube.com/mta/v1/emails \
  -H "Authorization: Bearer mk_<key_id>_<secret>" \
  -H "Content-Type: application/json" \
  -H "User-Agent: acme-billing/1.4" \
  -d '{
    "from": "Acme <hello@yourdomain.com>",
    "to": "customer@example.com",
    "subject": "Your order has shipped",
    "html": "<h1>On its way</h1><p>Track your order at...</p>"
  }'

A successful send returns 200 with two identifiers:

{
  "id": "8f1d2c3b-4a5e-6f70-8910-a1b2c3d4e5f6",
  "message_id": "<8f1d2c3b-4a5e-6f70-8910-a1b2c3d4e5f6@msg.mailkube.com>"
}

id is the mailkube message id, and message_id is the RFC Message-ID header the message was sent with. Echo the second one in In-Reply-To and References on a later send and the reply threads in the recipient’s client.

Authentication

An API key looks like mk_<key_id>_<secret> and is created in the dashboard against a domain you have verified. Send it as a Bearer token. The secret is displayed once, at creation. Store it in a secrets manager or an environment variable before you close the page.

This is a server-to-server API. Every request needs a User-Agent identifying your integration. A request without one is rejected with 400 missing_user_agent, and one that originated in a browser with 403 browser_not_allowed. The SDKs set a compliant User-Agent for you.

Delivery events

Delivery, bounce, open and click events are pushed to your server as webhooks, within seconds of the event itself. That push is the only way the API reports on a message it has accepted. There is no send-status resource to poll. For history rather than live events, the dashboard keeps your delivery logs.

Rate limits

Requests are rate limited per API key. Going over returns 429 rate_limit_exceeded with a Retry-After header giving the seconds to wait. A client that respects it needs no other backoff logic. Your plan also sets how many messages your organization can have accepted per second. That ceiling is counted across every domain, key and SMTP credential you own.

Retries without duplicates

A request that times out leaves you unsure whether the message went out. Attach an Idempotency-Key header and the answer stops mattering. A repeat of the same key and body returns the original result rather than sending a second message.

Errors

Errors return a compact envelope with the HTTP status mirrored in the body.

{ "name": "validation_error", "message": "...", "statusCode": 422 }

name is the stable machine-readable code to branch on. message explains the failure and is meant for a human reading a log.

Reference and SDKs