API reference
Create an account, verify your sender domain, then use the core transactional email endpoints. Account endpoints issue API keys and track quota/credits; top-up is available after onboarding.
Answer first: create an account, submit your domain/sender, complete verification, then use the transactional email API under https://api.mailbot.id. The core endpoints are POST /v1/send, GET /v1/status, and POST /v1/test-email.
Endpoints at a glance
Core transactional email endpoints
| Method | Path | Purpose | Auth |
|---|---|---|---|
| POST | /v1/send | Send one transactional email. | Bearer key |
| GET | /v1/status | Service health and account-safe send status. | Optional Bearer |
| POST | /v1/test-email | Send the standard Mailbot test email. | Bearer key |
Marketing / education capture endpoints (not transactional)
| Method | Path | Purpose | Auth |
|---|---|---|---|
| POST | /api/waitlist | Capture a product inquiry from the public site. | None |
| POST | /api/newsletter | Capture a blog newsletter subscriber. | None |
Self-serve account and top-up endpoints
| Method | Path | Purpose | Auth |
|---|---|---|---|
| POST | /api/account/signup | Create an account, API key, access code, and session. | None |
| POST | /api/account/login | Log in with email and account access code. | None |
| GET | /api/account/me | Read account email, free quota, usage, paid credits, packages, and purchase state. | Session cookie |
| POST | /api/topup/create-order | Create an IDR top-up checkout for more credits. | Session cookie |
All other HTTP methods on these routes return 405 Method not allowed.
POST /v1/send
Authenticate a developer key, validate one transactional email payload, check limits, and return an accepted response for the send.
Auth: required Authorization: Bearer <MAILBOT_API_KEY>. Create a self-serve account, then verify your sender domain before production use.
Request fields
| Field | Type | Required | Notes |
|---|---|---|---|
to | string | Yes | One recipient email address. |
subject | string | Yes | Up to 998 characters. |
text | string | One required | Plain-text body (or send html). |
html | string | One required | HTML body (or send text). Both may be sent. |
from | string | No | Verified sender. If omitted, Mailbot uses the sender configured for your account. |
idempotency_key | string | No | Up to 128 characters. Use a stable value for sends you may retry. |
{
"from": "noreply@yourdomain.com",
"to": "user@example.com",
"subject": "Receipt for order #1042",
"text": "Thanks! Your payment was received.",
"html": "<p>Thanks! Your payment was received.</p>",
"idempotency_key": "receipt-1042"
}
Responses
The same status terms are used on the homepage, API docs, and dashboard: validated means the request is valid but not sent in test/safe mode; queued means Mailbot accepted it into the delivery queue; sent means it entered the mail pipeline; failed means Mailbot could not process it.
{ "ok": true, "id": "msg_3f8c1a...", "status": "queued" }
{ "ok": true, "id": "msg_...", "status": "validated",
"note": "Validated by Mailbot ID. No email was sent." }
{ "ok": true, "id": "msg_...", "delivery_id": "delivery-...", "status": "sent" }
Error codes
| Status | Meaning |
|---|---|
400 | Invalid payload. Body includes details. |
401 | Missing, unknown, or revoked API key. |
402 | No free monthly quota or paid credits remaining for a billing-enforced self-serve key. |
403 | Recipient or sender is not allowed for this account. |
429 | Daily or monthly send limit reached. |
502 | Delivery handoff could not be completed. |
503 | Mailbot is temporarily unable to accept the send. |
idempotency_key can be correlated safely, so another account cannot claim your retry value.GET /v1/status
Returns safe, non-secret service health for dashboards and machine clients. Never returns API key or delivery secret values.
Auth: optional. Without a key it returns compact public status; with a valid Bearer key it can include account-safe detail.
curl https://api.mailbot.id/v1/status
{
"ok": true,
"service": "mailbot-id",
"status": "ready"
}
POST /v1/test-email
Builds a standardized Mailbot test message and sends it through the same validation path as /v1/send. This is the safe answer to "can Mailbot send a test email?"
Auth: required Authorization: Bearer <MAILBOT_API_KEY>.
| Field | Type | Required | Notes |
|---|---|---|---|
to | string | Yes | Recipient address you control. |
from | string | No | Verified sender. |
label | string | No | Appears in the fixed test subject line. |
idempotency_key | string | No | Up to 128 characters. |
/v1/send for real transactional content.curl https://api.mailbot.id/v1/test-email \
-H "Authorization: Bearer $MAILBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "to": "safe@yourdomain.com", "label": "Smoke test" }'
Self-Serve Account And API Key
Create an account from the onboarding page or with POST /api/account/signup. Signup creates your account, starts a session, stores non-secret onboarding fields for domain/sender verification, and returns the API key plus account access code once. Raw secrets are not stored.
{ "email": "user@example.com" }
GET /api/account/me returns account email/status, 1,000 free monthly credits, current monthly usage, paid credits, IDR package metadata, and the current purchase state.
Custom sender domain
POST /api/account/verify-domain with { "domain": "example.com" } generates account-scoped DKIM material and returns the ownership, SPF, DKIM, and DMARC DNS records. Publish every record, then call it again with { "action": "check" }. After verification, that account may use addresses such as noreply@example.com in the from field; another account cannot use the domain.
POST /api/topup/create-order
Creates an IDR top-up order for one of the packages returned to the logged-in account. Public pricing starts from Rp30rb; the Dashboard shows the current package choices. The response includes a payment URL when checkout is available, and credits are added only after payment succeeds.
{ "package_id": "starter_30k" }
{ "ok": true, "status": "waiting_for_payment", "payment_url": "https://...", "order_id": "ord_...", "currency": "IDR", "amount": "30000", "credits": 2000 }
POST /api/waitlist lead capture
This endpoint is used only by the public site to capture a product inquiry email address. It is not part of the transactional email API and most integrations never call it.
Auth: none. Body: { "email": "user@example.com" }. Returns { "ok": true } for both new and duplicate submissions (responses never reveal whether an address is already on the list), 400 for an invalid email, and 429 when the per-client signup rate limit is exceeded.
POST /api/newsletter newsletter capture
This endpoint is used by the blog to store readers who want practical Mailbot updates. It stores subscribers; it does not send broadcasts and is not part of the transactional email API.
Auth: none. Body: { "email": "reader@example.com", "role": "Founder / OTP", "source": "blog_index" }. role is optional. Returns { "ok": true } for both new and duplicate submissions, 400 for an invalid email, and 429 when the per-client subscription rate limit is exceeded.