API Reference
PostMTA exposes a RESTful HTTP API for all operations: sending email, managing domains and IP pools, querying analytics, configuring webhooks, and administering your workspace. All requests and responses use JSON.
Base URL
https://api.postmta.comAll API paths are relative to this base URL. The current API version is v1. Breaking changes are never introduced within v1; new optional fields and new endpoints are added periodically.
Authentication
API Key Header
Every request must include an Authorization header with a Bearer token:
Authorization: Bearer pmta_l_01HXABC123DEF456GHI789JKL012MNO345PQRAPI keys are created from the dashboard under /app/access. Keys are scoped to a workspace and can be restricted to specific permission sets.
Key Scopes
| Scope | Description |
|---|---|
keys:read | List and retrieve API key metadata |
domains:manage | Add, verify, and remove sending domains |
domains:verify | Initiate and check domain verification (DKIM, SPF, DMARC) |
messages:send | Inject messages into the delivery pipeline |
messages:read | Look up message status and delivery events |
analytics:read | Read aggregate analytics and export data |
webhooks:manage | Create, update, and delete webhook endpoints |
webhooks:read | View webhook configurations and delivery logs |
ip-pools:manage | Create and manage IP pools and assignment |
credits:read | View credit balance and transaction history |
credits:write | Top up credits and configure auto-reload |
workspace:admin | Full workspace administration (owners only) |
Rate Limits
| Limit | Value | Scope |
|---|---|---|
| API requests | 1,000 req/min | Per API key |
| Messages (inject) | Varies by plan | Per workspace |
| Webhook deliveries | 200 delivery attempts/min | Per endpoint |
| Suppression imports | 1 import job/hour | Per workspace |
Rate limit status is returned in every response header:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1750272030Pagination
List endpoints return paginated results using cursor-based pagination. Pass cursor from the previous response to retrieve the next page:
GET /v1/keys?limit=25
GET /v1/keys?limit=25&after=cursor_01HXABC123DEF456Response envelope:
{
"data": [ ... ],
"pagination": {
"has_more": true,
"next_cursor": "cursor_01HXABC123DEF456",
"total": 142
}
}Error Response Schema
All errors follow a consistent envelope. See the Error Codes page for the full code reference.
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "You have exceeded the rate limit of 1000 requests per minute.",
"status": 429,
"details": {
"limit": 1000,
"window": "1m",
"retry_after_seconds": 12
},
"request_id": "req_01HXABC123DEF456"
}
}Key Endpoints
API Keys
| Method | Path | Description |
|---|---|---|
GET | /v1/keys | List all API keys in the workspace |
POST | /v1/keys | Create a new API key |
GET | /v1/keys/:id | Retrieve a specific key |
DELETE | /v1/keys/:id | Revoke a key immediately |
List Keys
curl https://api.postmta.com/v1/keys \
-H "Authorization: Bearer pmta_l...xxxx"{
"data": [
{
"id": "key_01HXABC123DEF456",
"name": "Production Send Key",
"scopes": ["messages:send", "messages:read"],
"workspace_id": "ws_01HXABC123DEF456",
"created_at": "2026-01-15T09:23:41Z",
"last_used_at": "2026-07-18T14:02:17Z",
"expires_at": null
}
],
"pagination": { "has_more": false, "total": 1 }
}Create Key
curl -X POST https://api.postmta.com/v1/keys \
-H "Authorization: Bearer pmta_l...xxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "Analytics Read-Only Key",
"scopes": ["analytics:read"]
}'{
"data": {
"id": "key_01HXABC789GHI012",
"name": "Analytics Read-Only Key",
"scopes": ["analytics:read"],
"key": "pmta_l_01HXABC789GHI012LMN345OPQ678RST901UVW",
"workspace_id": "ws_01HXABC123DEF456",
"created_at": "2026-07-18T15:00:00Z"
}
}Sending Domains
| Method | Path | Description |
|---|---|---|
GET | /v1/domains | List all sending domains |
POST | /v1/domains | Add and verify a sending domain |
GET | /v1/domains/:id | Retrieve domain status and DNS records |
DELETE | /v1/domains/:id | Remove a sending domain |
Add Domain
curl -X POST https://api.postmta.com/v1/domains \
-H "Authorization: Bearer pmta_l...xxxx" \
-H "Content-Type: application/json" \
-d '{
"domain": "mail.example.com",
"dkim_selector": "pmta"
}'{
"data": {
"id": "dom_01HXABC123DEF456",
"domain": "mail.example.com",
"dkim_selector": "pmta",
"verification_status": "pending",
"dns_records": {
"dkim": {
"name": "pmta._domainkey.mail.example.com",
"type": "TXT",
"value": "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEB...="
},
"spf": {
"name": "mail.example.com",
"type": "TXT",
"value": "v=spf1 include:spf.postmta.com ~all"
}
},
"created_at": "2026-07-18T16:00:00Z"
}
}Messages
| Method | Path | Description |
|---|---|---|
POST | /v1/messages | Inject a single message |
POST | /v1/messages/batch | Inject up to 1,000 messages in one request |
GET | /v1/messages/:id | Retrieve message status and events |
Send a Message
curl -X POST https://api.postmta.com/v1/messages \
-H "Authorization: Bearer pmta_l...xxxx" \
-H "Content-Type: application/json" \
-d '{
"from": "sender@example.com",
"to": "recipient@example.com",
"subject": "Your Monthly Statement",
"html": "<html><body>...</body></html>",
"text": "Plain text version",
"tags": ["statement", "july"],
"custom_args": { "user_id": "12345" },
"send_at": "2026-07-20T09:00:00Z"
}'{
"data": {
"id": "msg_01HXABC123DEF456",
"from": "sender@example.com",
"to": "recipient@example.com",
"status": "accepted",
"created_at": "2026-07-18T16:30:00Z",
"send_at": "2026-07-20T09:00:00Z"
}
}Batch Send
curl -X POST https://api.postmta.com/v1/messages/batch \
-H "Authorization: Bearer pmta_l...xxxx" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"from": "sender@example.com",
"to": "recipient1@example.com",
"subject": "Campaign One",
"html": "<html>...</html>"
},
{
"from": "sender@example.com",
"to": "recipient2@example.com",
"subject": "Campaign One",
"html": "<html>...</html>"
}
]
}'{
"data": {
"accepted": 2,
"rejected": 0,
"messages": [
{ "id": "msg_01HXABC123DEF456", "to": "recipient1@example.com", "status": "accepted" },
{ "id": "msg_01HXABC789GHI012", "to": "recipient2@example.com", "status": "accepted" }
]
}
}Webhooks
| Method | Path | Description |
|---|---|---|
GET | /v1/webhooks | List all webhook endpoints |
POST | /v1/webhooks | Register a new webhook endpoint |
PUT | /v1/webhooks/:id | Update an existing endpoint |
DELETE | /v1/webhooks/:id | Delete a webhook endpoint |
Create Webhook
curl -X POST https://api.postmta.com/v1/webhooks \
-H "Authorization: Bearer pmta_l...xxxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/webhooks/postmta",
"events": ["message.delivered", "message.bounced", "message.complained"],
"secret": "whsec_your_signing_secret"
}'{
"data": {
"id": "whk_01HXABC123DEF456",
"url": "https://yourapp.com/webhooks/postmta",
"events": ["message.delivered", "message.bounced", "message.complained"],
"status": "active",
"created_at": "2026-07-18T17:00:00Z"
}
}Templates
| Method | Path | Description |
|---|---|---|
GET | /v1/templates | List all templates |
POST | /v1/templates | Create a new template |
GET | /v1/templates/:id | Retrieve a template |
PUT | /v1/templates/:id | Update a template |
DELETE | /v1/templates/:id | Delete a template |
Create Template
curl -X POST https://api.postmta.com/v1/templates \
-H "Authorization: Bearer pmta_l...xxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "July Newsletter",
"subject": "Your July Update from {{company_name}}",
"html": "<html><body><h1>Hello {{first_name}}</h1><p>...</p></body></html>",
"text": "Hello {{first_name}}, ...",
"tags": ["newsletter", "july"]
}'{
"data": {
"id": "tmpl_01HXABC123DEF456",
"name": "July Newsletter",
"subject": "Your July Update from {{company_name}}",
"version": 1,
"tags": ["newsletter", "july"],
"created_at": "2026-07-18T17:30:00Z",
"updated_at": "2026-07-18T17:30:00Z"
}
}Analytics
| Method | Path | Description |
|---|---|---|
GET | /v1/analytics/summary | Aggregate metrics for a date range |
GET | /v1/analytics/timeseries | Time-series metrics at hourly/daily/weekly resolution |
GET | /v1/analytics/export | Export analytics data as CSV or JSON |
Summary
curl "https://api.postmta.com/v1/analytics/summary?start=2026-07-01&end=2026-07-18" \
-H "Authorization: Bearer pmta_l...xxxx"{
"data": {
"period": { "start": "2026-07-01", "end": "2026-07-18" },
"metrics": {
"sent": 145293,
"delivered": 143418,
"bounced": 362,
"complained": 28,
"suppressed": 1485,
"unique_opens": 87204,
"unique_clicks": 21801
},
"rates": {
"deliver_rate": 98.71,
"bounce_rate": 0.25,
"complaint_rate": 0.02,
"open_rate": 60.80,
"click_rate": 15.20
}
}
}OpenAPI Specification
The full OpenAPI 3.1 specification is available at:
https://api.postmta.com/openapi.jsonYou can import this into Postman, Insomnia, or any OpenAPI-compatible tooling to get a fully-typed, interactive API client.
SDK Availability
Official SDKs wrap the REST API in idiomatic language bindings. All SDKs are generated from the OpenAPI spec and support the full API surface.
| Language | Package | Repository |
|---|---|---|
| Node.js / TypeScript | @postmta/node | github.com/postmta/postmta-node |
| Python | postmta-python | github.com/postmta/postmta-python |
| Go | github.com/postmta/postmta-go | github.com/postmta/postmta-go |
| Ruby | postmta | github.com/postmta/postmta-ruby |
See the SDKs & Libraries page for installation and usage examples for each language.