REST API overview
The SDKs cover most needs, but everything they do is plain HTTPS + JSON you can call from any language. The full, generated reference for every endpoint is in the REST API reference.
Base URL
Section titled “Base URL”https://api.frontmail.devAll endpoints are versioned under /v1. The EmailJS-compatible aliases
POST /api/v1.0/email/send and POST /api/v1.0/email/send-form behave like /v1/send and
/v1/send-form.
Authentication
Section titled “Authentication”| Key | Send as | Allowed endpoints |
|---|---|---|
Public key pk_… |
X-Frontmail-Public-Key: pk_… header, or user_id in the body |
POST /v1/send, POST /v1/send-form, POST /v1/uploads, GET /v1/messages/:id with the X-Frontmail-Status-Token header |
Private key sk_… |
Authorization: Bearer sk_… header, or accessToken in the body – from servers only (a request with an Origin header gets 403 private_key_in_browser) |
all endpoints |
Public-key requests without Origin and Referer (servers, curl, native apps) need
Allow mobile apps; otherwise they get
403 origin_not_allowed.
GET /v1/health and GET /v1/public-config need no key. See
Public and private keys for the security model.
Endpoints
Section titled “Endpoints”| Method & path | Purpose |
|---|---|
POST /v1/send |
Send one email from a template (JSON) |
POST /v1/send-form |
Send one email from multipart/form-data (files become attachments) |
POST /v1/send-batch |
Send up to 100 emails (private key) |
POST /v1/uploads |
Get a presigned URL for a large attachment |
GET /v1/messages/:id |
Status and events of a message |
GET /v1/history |
Paginated message history (private key) |
GET /v1/templates, GET /v1/templates/:id |
Templates with param schemas (private key) |
GET /v1/public-config |
Public configuration, no key needed – Frontmail’s mobile Turnstile site key and page URL, used by @frontmail/react-native (cacheable for 1 hour) |
GET /v1/health |
Health check |
Headers
Section titled “Headers”| Header | Direction | Meaning |
|---|---|---|
Idempotency-Key |
request | Deduplicates retries for 24 h (≤ 255 chars) – see Retries and idempotency |
X-Frontmail-Client |
request | SDK name and version, e.g. @frontmail/browser/0.3.1 (optional, helps support) |
X-Frontmail-Status-Token |
request | status_token from the send response, for GET /v1/messages/:id with a public key. The older ?token= query parameter still works but ends up in access logs – prefer the header |
Retry-After |
response | Seconds to wait, on 429 |
Example
Section titled “Example”curl https://api.frontmail.dev/v1/send \ -H 'Content-Type: application/json' \ -H 'X-Frontmail-Public-Key: pk_4f2a…' \ -H 'Origin: https://example.com' \ -H 'Idempotency-Key: 5f0c6f8e-1d2a-4c55-9f6b-2d7c1f4a9e10' \ -d '{ "service_id": "svc_01J9…", "template_id": "tpl_01J9…", "template_params": { "name": "Jana", "email": "jana@example.com", "message": "Hi!" }, "turnstile_token": "0.AbCd…" }'{ "message_id": "msg_01J9Z3K7Q2", "status": "queued", "status_token": "st_…" }status is queued or held (out of credits in hold mode). Both mean the message was
accepted – the response code is 202.
Errors
Section titled “Errors”All errors share one shape:
{ "error": { "code": "origin_not_allowed", "message": "…", "docs_url": "https://docs.frontmail.dev/reference/errors/#origin-not-allowed", "details": {} } }Possible statuses: 400, 401, 402 (only in reject mode), 403, 404, 409, 413,
422, 429, 451, 5xx. Every code is explained in Error codes.
Limits
Section titled “Limits”- Params: 256 kB of JSON per message; strings 50,000 characters unless the schema says otherwise.
- Batch: 100 messages per request.
- Attachments: per plan, see Plans.
- Requests per second: per plan, see Rate limits.