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"Tracking Domains
Tracking domains brand the open and click-tracking URLs in your outbound email under a subdomain you control. Each tracking domain belongs to a single cluster and is verified by a single CNAME record.
See Tracking for the full conceptual overview.
List Tracking Domains
Returns all tracking domains belonging to a cluster.
GET /api/v1/clusters/{cluster}/tracking-domainsParameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
Response
{
"data": [
{
"name": "track.example.com",
"status": "active",
"is_default": true,
"verification_hostname": "v-deadbeef.track.unmta.net",
"verified_at": "2025-01-15T10:42:00Z",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:42:00Z"
}
]
}Example
curl -X GET https://app.unmta.com/api/v1/clusters/a1b2c3d4/tracking-domains \
-H "Authorization: Bearer your-api-token"Create Tracking Domain
Creates a new tracking domain and issues a unique CNAME verification target. The response includes the CNAME record you'll need to configure.
POST /api/v1/clusters/{cluster}/tracking-domainsParameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
Request Body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes | — | Tracking domain name (e.g., track.example.com) |
is_default | boolean | No | false | If true, this becomes the cluster's default tracking domain and the previous default (if any) is automatically unset |
Tracking Domain Requirements
- Must be a valid subdomain — at least three labels, not an apex domain
- Cannot be an IP address
- Cannot use reserved TLDs:
localhost,local,test,invalid,example,localdomain - Must be unique within the cluster
Request
{
"name": "track.example.com",
"is_default": true
}Response (201 Created)
{
"data": {
"name": "track.example.com",
"status": "pending",
"is_default": true,
"verification_hostname": "v-deadbeef.track.unmta.net",
"verified_at": null,
"dns_records": {
"cname": {
"type": "CNAME",
"name": "track.example.com",
"value": "v-deadbeef.track.unmta.net"
}
},
"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/tracking-domains \
-H "Authorization: Bearer your-api-token" \
-H "Content-Type: application/json" \
-d '{"name": "track.example.com"}'Get Tracking Domain
Returns a specific tracking domain with its CNAME record configuration.
GET /api/v1/clusters/{cluster}/tracking-domains/{domain}Parameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
domain | path | Yes | The tracking domain name (case-insensitive) |
Response
{
"data": {
"name": "track.example.com",
"status": "active",
"is_default": true,
"verification_hostname": "v-deadbeef.track.unmta.net",
"verified_at": "2025-01-15T10:42:00Z",
"dns_records": {
"cname": {
"type": "CNAME",
"name": "track.example.com",
"value": "v-deadbeef.track.unmta.net"
}
},
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:42:00Z"
}
}Example
curl -X GET https://app.unmta.com/api/v1/clusters/a1b2c3d4/tracking-domains/track.example.com \
-H "Authorization: Bearer your-api-token"Update Tracking Domain
Updates a tracking domain. Currently only the is_default flag is mutable.
PATCH /api/v1/clusters/{cluster}/tracking-domains/{domain}Parameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
domain | path | Yes | The tracking domain name (case-insensitive) |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
is_default | boolean | Yes | If true, this becomes the cluster's default tracking domain and the previous default (if any) is automatically unset. Pass false to clear the default. |
At most one tracking domain per cluster can be the default. It's also valid to have no default — messages without a tracking host override will fall back to the unMTA-owned hostname.
Request
{
"is_default": true
}Response
{
"data": {
"name": "track.example.com",
"status": "active",
"is_default": true,
"verification_hostname": "v-deadbeef.track.unmta.net",
"verified_at": "2025-01-15T10:42:00Z",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T14:20:00Z"
}
}Example
curl -X PATCH https://app.unmta.com/api/v1/clusters/a1b2c3d4/tracking-domains/track.example.com \
-H "Authorization: Bearer your-api-token" \
-H "Content-Type: application/json" \
-d '{"is_default": true}'Verify Tracking Domain
Triggers an on-demand check of the tracking domain's CNAME record. On success, a pending domain is promoted to active and verified_at is set. The endpoint always returns 200; check verification.verified to determine the outcome.
POST /api/v1/clusters/{cluster}/tracking-domains/{domain}/verifyParameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
domain | path | Yes | The tracking domain name (case-insensitive) |
Response
{
"data": {
"name": "track.example.com",
"status": "active",
"is_default": false,
"verification_hostname": "v-deadbeef.track.unmta.net",
"verified_at": "2025-01-15T10:42:00Z",
"dns_records": {
"cname": {
"type": "CNAME",
"name": "track.example.com",
"value": "v-deadbeef.track.unmta.net"
}
},
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:42:00Z"
},
"verification": {
"verified": true,
"error": null
}
}When the CNAME doesn't resolve to the issued target, verification.verified is false and verification.error carries a human-readable reason:
{
"data": { "...": "..." },
"verification": {
"verified": false,
"error": "No CNAME record found."
}
}Example
curl -X POST https://app.unmta.com/api/v1/clusters/a1b2c3d4/tracking-domains/track.example.com/verify \
-H "Authorization: Bearer your-api-token"Delete Tracking Domain
Deletes a tracking domain from the cluster.
DELETE /api/v1/clusters/{cluster}/tracking-domains/{domain}Parameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
domain | path | Yes | The tracking domain name (case-insensitive) |
Response: 204 No Content
Deleting a tracking domain is immediate and irreversible. Tracking links in any already-delivered mail that pointed at this domain will stop working.
Example
curl -X DELETE https://app.unmta.com/api/v1/clusters/a1b2c3d4/tracking-domains/track.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"Bot Signatures
Bot signatures suppress open and click-tracking events generated by bots, security scanners, AI crawlers, and inbox-preview services. See Bot Signatures for the full conceptual overview.
Signatures come in two flavors: defaults (shared across all clusters, managed by unMTA, but individually toggleable per cluster) and custom (per cluster, fully managed by you). Each signature has a match type of user_agent (case-insensitive substring match against the User-Agent header), ip_exact (single IPv4/IPv6 address), or ip_cidr (CIDR block).
Changes to bot signatures propagate to the MTAs as part of the normal config-sync cycle. Expect up to 15 minutes before every MTA is matching on the updated set.
List Default Signatures
Returns the default signatures available to the cluster, with a per-cluster enabled flag showing whether each one is currently active.
GET /api/v1/clusters/{cluster}/bot-signatures/defaultsParameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
Query Parameters
| Name | Type | Description |
|---|---|---|
source | string | Filter by source (e.g. apple, microsoft, security, google, yahoo, ai, crawler) |
q | string | Search term matched against key, pattern, and label |
enabled | boolean | Filter to only enabled (true) or disabled (false) defaults for this cluster |
per_page | integer | Page size. Default 50, maximum 200 |
page | integer | Page number. Default 1 |
Response Fields
| Field | Type | Description |
|---|---|---|
key | string | Unique identifier for the default signature (e.g. apple:17.0.0.0/8, ua:googleimageproxy) |
type | string | Match type: user_agent, ip_exact, or ip_cidr |
pattern | string | The pattern matched against the incoming request |
source | string | Category the signature belongs to |
label | string | null | Human-readable description |
enabled | boolean | Whether the signature is currently active for this cluster |
Response
{
"data": [
{
"key": "ua:googleimageproxy",
"type": "user_agent",
"pattern": "GoogleImageProxy",
"source": "google",
"label": "Google Image Proxy",
"enabled": true
},
{
"key": "apple:17.0.0.0/8",
"type": "ip_cidr",
"pattern": "17.0.0.0/8",
"source": "apple",
"label": "Apple Private Relay",
"enabled": true
}
],
"meta": {
"current_page": 1,
"per_page": 50,
"total": 12000
}
}Example
curl -X GET "https://app.unmta.com/api/v1/clusters/a1b2c3d4/bot-signatures/defaults?source=security&per_page=100" \
-H "Authorization: Bearer your-api-token"Get Default Signature
Returns a single default signature with its per-cluster enabled flag.
GET /api/v1/clusters/{cluster}/bot-signatures/defaults/{key}Parameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
key | path | Yes | The default signature key |
Response
{
"data": {
"key": "ua:googleimageproxy",
"type": "user_agent",
"pattern": "GoogleImageProxy",
"source": "google",
"label": "Google Image Proxy",
"enabled": true
}
}Example
curl -X GET https://app.unmta.com/api/v1/clusters/a1b2c3d4/bot-signatures/defaults/ua:googleimageproxy \
-H "Authorization: Bearer your-api-token"Update Default Signature
Enables or disables a default signature for the cluster. The signature itself is not modified — only its per-cluster active state.
PATCH /api/v1/clusters/{cluster}/bot-signatures/defaults/{key}Parameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
key | path | Yes | The default signature key |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
enabled | boolean | Yes | true to enable the signature for the cluster, false to disable it |
Request
{
"enabled": false
}Response
{
"data": {
"key": "ua:googleimageproxy",
"type": "user_agent",
"pattern": "GoogleImageProxy",
"source": "google",
"label": "Google Image Proxy",
"enabled": false
}
}Example
curl -X PATCH https://app.unmta.com/api/v1/clusters/a1b2c3d4/bot-signatures/defaults/ua:googleimageproxy \
-H "Authorization: Bearer your-api-token" \
-H "Content-Type: application/json" \
-d '{"enabled": false}'List Custom Signatures
Returns all custom bot signatures belonging to a cluster.
GET /api/v1/clusters/{cluster}/bot-signatures/customParameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
Response Fields
| Field | Type | Description |
|---|---|---|
id | string | UUID identifier |
type | string | Match type: user_agent, ip_exact, or ip_cidr |
pattern | string | The pattern matched against the incoming request |
source | string | Always custom for user-defined signatures |
kind | string | One of proxy or automation. Defaults to automation. |
label | string | null | Human-readable description |
created_at | string | ISO 8601 creation timestamp |
updated_at | string | ISO 8601 last update timestamp |
Response
{
"data": [
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"type": "user_agent",
"pattern": "InternalScanner/1.0",
"source": "custom",
"kind": "automation",
"label": "Corporate link scanner",
"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/bot-signatures/custom \
-H "Authorization: Bearer your-api-token"Create Custom Signature
Creates a new custom bot signature for the cluster.
POST /api/v1/clusters/{cluster}/bot-signatures/customParameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Match type. One of user_agent, ip_exact, ip_cidr |
pattern | string | Yes | Pattern to match. Max 1000 characters |
label | string | null | No | Optional description. Max 255 characters |
kind | string | No | One of proxy or automation. Defaults to automation. |
Pattern Requirements
user_agent— any non-empty string up to 1000 characters, matched case-insensitively as a substring of the request'sUser-Agentheaderip_exact— a valid IPv4 or IPv6 addressip_cidr— a valid CIDR block. IPv4 prefixes must be/0–/32; IPv6 prefixes must be/0–/128kind—automationfor scanners, AI crawlers, and generic HTTP clients (the usual choice for custom rules);proxyonly for mailbox-provider image or link proxies fetching on behalf of a real recipient
Request
{
"type": "user_agent",
"pattern": "InternalScanner/1.0",
"label": "Corporate link scanner"
}Response (201 Created)
{
"data": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"type": "user_agent",
"pattern": "InternalScanner/1.0",
"source": "custom",
"kind": "automation",
"label": "Corporate link scanner",
"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/bot-signatures/custom \
-H "Authorization: Bearer your-api-token" \
-H "Content-Type: application/json" \
-d '{
"type": "ip_cidr",
"pattern": "198.51.100.0/24",
"label": "Office egress range"
}'Get Custom Signature
Returns a single custom bot signature.
GET /api/v1/clusters/{cluster}/bot-signatures/custom/{id}Parameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
id | path | Yes | The custom signature UUID |
Response
{
"data": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"type": "user_agent",
"pattern": "InternalScanner/1.0",
"source": "custom",
"kind": "automation",
"label": "Corporate link scanner",
"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/bot-signatures/custom/123e4567-e89b-12d3-a456-426614174000 \
-H "Authorization: Bearer your-api-token"Delete Custom Signature
Deletes a custom bot signature from the cluster.
DELETE /api/v1/clusters/{cluster}/bot-signatures/custom/{id}Parameters
| Name | Location | Required | Description |
|---|---|---|---|
cluster | path | Yes | The cluster ID |
id | path | Yes | The custom signature UUID |
Response: 204 No Content
Example
curl -X DELETE https://app.unmta.com/api/v1/clusters/a1b2c3d4/bot-signatures/custom/123e4567-e89b-12d3-a456-426614174000 \
-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 |