Management API
Programmatically manage your unMTA clusters, domains, and SMTP credentials using the REST API.
Overview
The unMTA API provides programmatic access to manage your mail infrastructure. Use the API to automate domain configuration, manage SMTP credentials, and integrate unMTA into your deployment workflows.
This API is for the unMTA control plane—managing clusters, domains, and credentials. For sending email via HTTP or SMTP, see Sending Messages.
Base URL
All API requests should be made to:
https://app.unmta.com/api/v1Authentication
The API uses Bearer token authentication. Include your API token in the Authorization header of every request:
Authorization: Bearer your-api-tokenGenerating an API Token
- Log in to the unMTA dashboard
- Navigate to API Settings from the user menu
- Click Generate API key
- Copy the token immediately—it's only displayed once
Store your API token securely. If you lose it, you'll need to generate a new one, which will revoke the previous token.
Token Lifecycle
- Each user can have one active API token at a time
- Generating a new token automatically revokes any existing token
- Tokens can be manually revoked from the API Settings page
- Tokens do not expire automatically
Request Format
- All requests must include the
Authorizationheader - Request bodies should be JSON with
Content-Type: application/json - All timestamps are in ISO 8601 format (UTC)
Response Format
All responses return JSON. Successful responses wrap data in a data key:
{
"data": {
"id": "a1b2c3d4",
"hostname": "c-a1b2c3d4.unmta.net"
}
}Collections return an array within the data key:
{
"data": [
{ "id": "a1b2c3d4", "hostname": "c-a1b2c3d4.unmta.net" },
{ "id": "e5f6g7h8", "hostname": "c-e5f6g7h8.unmta.net" }
]
}Error Responses
401 Unauthenticated
Returned when the request lacks a valid API token.
{
"message": "Unauthenticated."
}404 Not Found
Returned when the requested resource doesn't exist or you don't have access to it.
{
"message": "Not Found"
}422 Validation Error
Returned when request data fails validation.
{
"message": "The name field is required.",
"errors": {
"name": ["The name field is required."]
}
}Clusters
Clusters are the top-level organizational unit in unMTA. Each cluster contains its own MTAs, domains, and credentials.
List Clusters
Returns all clusters accessible to the authenticated user.
GET /api/v1/clustersResponse Fields
| Field | Type | Description |
|---|---|---|
id | string | The cluster ID |
hostname | string | The cluster hostname |
region | string | The deployment region |
status | string | The cluster status |
max_message_rate | string | null | The message rate limit applied per MTA, or null if unlimited |
created_at | string | ISO 8601 creation timestamp |
updated_at | string | ISO 8601 last update timestamp |
The max_message_rate field uses the format quantity/period with an optional burst modifier. For example: "500/hr", "1,000/day", "50/hr,max_burst=10", or "500/30min". A value of null means no rate limit is applied—this is the default for most clusters. Rate limits are typically only used during customer trials or IP warming.
The rate limit is applied per MTA. Clusters with multiple MTAs will have an effective total rate of rate × number of MTAs.
Messages are not rejected when the rate limit is exceeded. They are held in a scheduled queue and delivered when the rate window allows.
Response
{
"data": [
{
"id": "a1b2c3d4",
"hostname": "c-a1b2c3d4.unmta.net",
"region": "us-dal-1",
"status": "active",
"max_message_rate": null,
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
]
}Example
curl -X GET https://app.unmta.com/api/v1/clusters \
-H "Authorization: Bearer your-api-token"MTAs
MTAs (Mail Transfer Agents) are the servers that handle email delivery within a cluster.
List MTAs
Returns all MTAs belonging to a cluster.
GET /api/v1/clusters/{cluster}/mtasParameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
Response
{
"data": [
{
"id": "x1y2z3w4",
"hostname": "m-x1y2z3w4.unmta.net",
"primary_ipv4": "203.0.113.10",
"primary_ipv6": "2001:db8::1",
"outbound_ips": [
{
"ipv4": "203.0.113.20",
"ipv6": "2001:db8::10",
"ptr": "ip-203-0-113-20.unmta.net"
},
{
"ipv4": "203.0.113.21",
"ipv6": "2001:db8::11",
"ptr": "ip-203-0-113-21.unmta.net"
}
],
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
]
}Example
curl -X GET https://app.unmta.com/api/v1/clusters/a1b2c3d4/mtas \
-H "Authorization: Bearer your-api-token"Domains
Domains must be added and verified before you can send email through unMTA. Each domain belongs to a single cluster and has its own DKIM keys.
List Domains
Returns all domains belonging to a cluster.
GET /api/v1/clusters/{cluster}/domainsParameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
Response
{
"data": [
{
"name": "example.com",
"status": "verified",
"dkim_public_key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T12:45:00Z"
}
]
}Example
curl -X GET https://app.unmta.com/api/v1/clusters/a1b2c3d4/domains \
-H "Authorization: Bearer your-api-token"Create Domain
Creates a new domain and generates DKIM keys. The response includes DNS records you'll need to configure.
POST /api/v1/clusters/{cluster}/domainsParameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Domain name (e.g., example.com) |
Domain Requirements
- Must be a valid fully-qualified domain name
- Cannot be an IP address
- Cannot use reserved TLDs:
localhost,local,test,invalid,example,localdomain - Must be unique within the cluster
Request
{
"name": "example.com"
}Response (201 Created)
{
"data": {
"name": "example.com",
"status": "pending",
"dkim_public_key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...",
"dns_records": {
"dkim": {
"type": "TXT",
"name": "unmta._domainkey",
"value": "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A..."
},
"dmarc": {
"type": "TXT",
"name": "_dmarc",
"value": "v=DMARC1; p=reject; adkim=s; aspf=r"
}
},
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
}Example
curl -X POST https://app.unmta.com/api/v1/clusters/a1b2c3d4/domains \
-H "Authorization: Bearer your-api-token" \
-H "Content-Type: application/json" \
-d '{"name": "example.com"}'Get Domain
Returns a specific domain with its DNS record configuration.
GET /api/v1/clusters/{cluster}/domains/{domain}Parameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
domain | path | Yes | The domain name (case-insensitive) |
Response
{
"data": {
"name": "example.com",
"status": "verified",
"dkim_public_key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...",
"dns_records": {
"dkim": {
"type": "TXT",
"name": "unmta._domainkey",
"value": "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A..."
},
"dmarc": {
"type": "TXT",
"name": "_dmarc",
"value": "v=DMARC1; p=reject; adkim=s; aspf=r"
}
},
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T12:45:00Z"
}
}Example
curl -X GET https://app.unmta.com/api/v1/clusters/a1b2c3d4/domains/example.com \
-H "Authorization: Bearer your-api-token"Delete Domain
Deletes a domain from the cluster.
DELETE /api/v1/clusters/{cluster}/domains/{domain}Parameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
domain | path | Yes | The domain name (case-insensitive) |
Response: 204 No Content
Deleting a domain is immediate and irreversible. Any email sent from this domain will be rejected after deletion.
Example
curl -X DELETE https://app.unmta.com/api/v1/clusters/a1b2c3d4/domains/example.com \
-H "Authorization: Bearer your-api-token"Credentials
SMTP credentials are used to authenticate when sending email through unMTA. Each credential can be restricted to specific domains and IP addresses.
List Credentials
Returns all SMTP credentials belonging to a cluster.
GET /api/v1/clusters/{cluster}/credentialsParameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
Response
{
"data": [
{
"user": "smtp_user",
"allow_all_domains": false,
"domains": ["example.com", "test.com"],
"allow_all_ips": true,
"allowed_ips": [],
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
}
]
}Example
curl -X GET https://app.unmta.com/api/v1/clusters/a1b2c3d4/credentials \
-H "Authorization: Bearer your-api-token"Create Credential
Creates a new SMTP credential. The password is generated automatically and returned only once in the response.
POST /api/v1/clusters/{cluster}/credentialsParameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
Request Body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
user | string | Yes | — | SMTP username |
allow_all_domains | boolean | No | false | Allow sending from all domains |
domains | array | Conditional | — | Allowed domain names (required if allow_all_domains is false) |
allow_all_ips | boolean | No | true | Allow connections from all IPs |
allowed_ips | array | Conditional | — | Allowed IP addresses/CIDR ranges (required if allow_all_ips is false) |
Username Requirements
- Maximum 255 characters
- Allowed characters: letters, numbers, and
+ = , . @ _ - - Must be unique within the cluster
Request
{
"user": "webapp-production",
"allow_all_domains": false,
"domains": ["example.com", "notifications.example.com"],
"allow_all_ips": false,
"allowed_ips": ["203.0.113.0/24", "198.51.100.5"]
}Response (201 Created)
{
"data": {
"user": "webapp-production",
"allow_all_domains": false,
"domains": ["example.com", "notifications.example.com"],
"allow_all_ips": false,
"allowed_ips": ["203.0.113.0/24", "198.51.100.5"],
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
},
"password": "aB3dEfGhIjKlMnOpQrStUvWxYz123456"
}The password is only returned once when the credential is created. Store it
securely—there's no way to retrieve it later.
Example
curl -X POST https://app.unmta.com/api/v1/clusters/a1b2c3d4/credentials \
-H "Authorization: Bearer your-api-token" \
-H "Content-Type: application/json" \
-d '{
"user": "webapp-production",
"domains": ["example.com"]
}'Update Credential
Updates the domain and/or IP restrictions for an SMTP credential.
PUT /api/v1/clusters/{cluster}/credentials/{user}Parameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
user | path | Yes | The credential username |
Request Body
| Field | Type | Description |
|---|---|---|
allow_all_domains | boolean | Allow sending from all domains |
domains | array | Allowed domain names |
allow_all_ips | boolean | Allow connections from all IPs |
allowed_ips | array | Allowed IP addresses/CIDR ranges |
If you provide domains without allow_all_domains, it automatically sets
allow_all_domains to false. The same applies to allowed_ips and
allow_all_ips.
Request
{
"domains": ["example.com", "new-domain.com"]
}Response
{
"data": {
"user": "webapp-production",
"allow_all_domains": false,
"domains": ["example.com", "new-domain.com"],
"allow_all_ips": true,
"allowed_ips": [],
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T14:20:00Z"
}
}Example
curl -X PUT https://app.unmta.com/api/v1/clusters/a1b2c3d4/credentials/webapp-production \
-H "Authorization: Bearer your-api-token" \
-H "Content-Type: application/json" \
-d '{"allow_all_domains": true}'Delete Credential
Deletes an SMTP credential from the cluster.
DELETE /api/v1/clusters/{cluster}/credentials/{user}Parameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
user | path | Yes | The credential username |
Response: 204 No Content
Deleting a credential is immediate. Any applications using this credential will no longer be able to send email.
Example
curl -X DELETE https://app.unmta.com/api/v1/clusters/a1b2c3d4/credentials/webapp-production \
-H "Authorization: Bearer your-api-token"HTTP Status Codes
| Code | Description |
|---|---|
200 | Success |
201 | Created |
204 | No Content (successful deletion) |
401 | Unauthenticated |
404 | Not Found |
422 | Validation Error |