API Reference Guide
Our HTTP REST API lets you programmatically manage your domains and aliases for email forwarding.
Base URL
The base URL is: https://api.improvmx.com/v3
Versioning
The v4 api was released on Aug 12th, 2026.
The v3 api was released on April 30th, 2020.
The v2 api has been marked as deprecated and was removed on
June 1st 2024.
Authentication
Get your API key from the API page of the dashboard, then use HTTP basic auth with username api and your API key as the password. With
curl, pass them via -u and it will build the
Authorization: Basic header for you:
export API_KEY="your_api_key_here"
curl https://api.improvmx.com/v3/domains \
-u "api:$API_KEY" Parameters
Every endpoint lists its parameters with a TYPE of
query or body, which tells you where each
one goes:
| TYPE | WHERE IT GOES | TYPICAL METHOD |
|---|---|---|
query | In the URL, after ? as key=value. | GET |
body | As JSON in the request body (curl's -d flag). | POST, PUT |
For example, listing domains filters with a query
parameter in the URL:
curl -X GET "https://api.improvmx.com/v3/domains?q=pied" \
-u "api:$API_KEY"
Adding a domain sends a body parameter as JSON:
curl -X POST https://api.improvmx.com/v3/domains \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{ "domain": "piedpiper.com" }' Error codes
| CODE | DESCRIPTION |
|---|---|
| 200 | Success |
| 400 | Bad Request - Incorrect or missing parameter. |
| 401 | Authentication required - Missing or invalid credentials. |
| 403 | Forbidden - Missing permissions, e.g. requires a premium account. |
| 429 | Too Many Requests - You've been rate limited. See Rate limiting. |
| 500 | Server error - We ran into a bug. Let us know and we'll fix it. |
Errors return a JSON body explaining the failure. Example Bad Request:
{
"errors": {
"email": [
"You cannot use your domain in your email."
]
},
"success": false
}
Every error has the same shape: message is always a displayable
string, and errors is always present — a map of field to messages
on validation failures, and {} otherwise. For validation
failures message repeats the first field message, so you can
show it without walking the map.
Rate Limits
Free accounts get 30 requests per minute per endpoint; paid plans get 200.
Every response includes rate-limit headers so you can track your budget:
| HEADER | DESCRIPTION |
|---|---|
X-RateLimit-Limit | Max requests allowed in the current window. |
X-RateLimit-Remaining | Requests left in the current window. |
X-RateLimit-Reset | When the window resets, as a Unix timestamp (seconds). |
Retry-After | On a 429 only — seconds to wait before retrying. |
When you exceed the limit, the API responds 429 Too Many Requests. Back off for Retry-After seconds (or until X-RateLimit-Reset) before trying again.
Account
Get account
GET /account
curl -X GET https://api.improvmx.com/v3/account \
-u "api:$API_KEY" Response:
{
"account": {
"billing_email": null,
"cancels_on": null,
"card_brand": "Visa",
"company_details": "1 Decentralized Street\n92024-2852 California",
"company_name": "PiedPiper Inc.",
"company_vat": null,
"country": "US",
"created": 1512139382000,
"email": "richard.hendricks@gmail.com",
"last4": "1234",
"limits": {
"aliases": 10000,
"daily_quota": 100000,
"daily_send": 200,
"domains": 10000,
"ratelimit": 10,
"redirections": 50,
"subdomains": 2,
"api": 3,
"credentials": 50,
"destinations": 5
},
"lock_reason": null,
"locked": null,
"password": true,
"plan": {
"aliases_limit": 10000,
"daily_quota": 100000,
"display": "Business - $249",
"domains_limit": 10000,
"kind": "enterprise",
"name": "enterprise249",
"price": 249,
"yearly": false
},
"premium": true,
"privacy_level": 1,
"renew_date": 15881622590000
},
"success": true
} {
"account": {
"address": "1 Decentralized Street, 92024 California",
"billing_email": null,
"cancels_at": null,
"company_vat": null,
"country": "US",
"created_at": "2017-12-01T13:23:02Z",
"email": "richard.hendricks@gmail.com",
"email_log_retention_days": 7,
"lock_reason": null,
"locked": null,
"name": "PiedPiper Inc.",
"over_quota": false,
"plan": {
"name": "Enterprise - PiedPiper",
"price": 249,
"billing_cycle": "monthly",
"domains_limit": 10000,
"aliases_limit": 10000,
"rules_limit": 50,
"daily_receive_limit": 100000,
"daily_send_limit": 200,
"monthly_receive_limit": 0,
"monthly_send_limit": 0
},
"privacy_level": 1,
"renews_at": "2020-04-30T07:50:59Z"
}
} List whitelabel domains
GET /account/whitelabels
Lists whitelabels for your domain.
curl -X GET https://api.improvmx.com/v3/account/whitelabels \
-u "api:$API_KEY" Response:
{
"whitelabels": [
{
"name": "piedpiper.com"
}
],
"success": true
} Domains
Add domains to ImprovMX that you want to send/receive emails from.
List domains
GET /domains
curl -X GET "https://api.improvmx.com/v3/domains?q=pied" \
-u "api:$API_KEY" | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
q | query | Filter domains by substring. |
is_active | query |
Active (1) or inactive (0) only.
|
limit | query | Number of domains. Default 50, max 100. |
page | query | Page number (1-based, default 1). |
Limited to 200 aliases per domain. For more, use the list aliases endpoint.
Response:
{
"domains": [
{
"active": true,
"domain": "google.com",
"display": "google.com",
"dkim_selector": "dkimprovmx",
"notification_email": null,
"webhook": null,
"whitelabel": null,
"added": 1559639697000,
"aliases": [
{
"created": 1702393755000,
"forward": "sergey@gmail.com",
"alias": "sergey",
"id": 1
},
{
"created": 1702393755000,
"forward": "larry@gmail.com",
"alias": "larry",
"id": 2
}
]
},
{
"active": false,
"domain": "piedpiper.com",
"display": "piedpiper.com",
"dkim_selector": "dkimprovmx",
"notification_email": null,
"webhook": null,
"whitelabel": null,
"added": 1559639733000,
"aliases": [
{
"created": 1702393755000,
"forward": "richard.hendricks@gmail.com",
"alias": "richard",
"id": 4
},
{
"created": 1702393755000,
"forward": "jared.dunn@gmail.com",
"alias": "jared",
"id": 5
}
]
}
],
"total": 2,
"limit": 50,
"page": 1,
"success": true
}
Use q to filter domains by substring,
as shown in the curl example above. Response:
{
"domains": [
{
"active": true,
"domain": "piedpiper.com",
"display": "piedpiper.com",
"dkim_selector": "dkimprovmx",
"notification_email": null,
"webhook": null,
"whitelabel": null,
"added": 1559639727000,
"daily_quota": 500,
"aliases": [
{
"created": 1702393755000,
"forward": "richard@piedpiper.com",
"alias": "*",
"id": 3
}
]
}
],
"total": 1,
"limit": 50,
"page": 1,
"success": true
} Get domain
GET /domains/:domain
curl -X GET https://api.improvmx.com/v3/domains/piedpiper.com \
-u "api:$API_KEY" Limited to 200 aliases per domain. For more, use the list aliases endpoint.
Response:
{
"domain": {
"active": false,
"domain": "piedpiper.com",
"added": 1559639733000,
"display": "piedpiper.com",
"dkim_selector": "dkimprovmx",
"notification_email": null,
"webhook": null,
"whitelabel": null,
"aliases": [
{
"created": 1702393755000,
"forward": "richard.hendricks@gmail.com",
"alias": "richard",
"id": 4
},
{
"created": 1702393755000,
"forward": "jared.dunn@gmail.com",
"alias": "jared",
"id": 5
}
]
},
"success": true
} Add domain
POST /domains
curl -X POST https://api.improvmx.com/v3/domains \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"domain": "piedpiper.com"
}' | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
domain | body | Required. Domain name. |
notification_email | body | Optionally, where to send notifications. Defaults to your account email. |
whitelabel | body | Parent domain shown in DNS settings. |
Response:
{
"domain": {
"active": false,
"domain": "piedpiper.com",
"display": "piedpiper.com",
"dkim_selector": "dkimprovmx",
"notification_email": null,
"whitelabel": null,
"added": 1559652806000,
"aliases": [
{
"forward": "contact@piedpiper.com",
"alias": "*",
"id": 12
}
]
},
"success": true
} Update domain
PUT /domains/:domain
The domain name cannot be changed.
curl -X PUT https://api.improvmx.com/v3/domains/piedpiper.com \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"notification_email": "richard.hendricks@gmail.com",
"webhook": "https://requestbin.com/r/abc123",
"whitelabel": "hooli.com"
}' | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
notification_email | body | Optionally, where to send notifications. Defaults to your account email. |
webhook | body | Where to POST email events for this domain. |
whitelabel | body | Parent domain owner. |
Response:
{
"domain": {
"active": false,
"domain": "piedpiper.com",
"added": 1559639733000,
"display": "piedpiper.com",
"dkim_selector": "dkimprovmx",
"notification_email": "richard.hendricks@gmail.com",
"webhook": "https://requestbin.com/r/enbwnegkb25v",
"whitelabel": "hooli.com",
"aliases": [
{
"forward": "richard.hendricks@gmail.com",
"alias": "richard",
"id": 4
},
{
"forward": "jared.dunn@gmail.com",
"alias": "jared",
"id": 5
}
]
},
"success": true
} Verify domain
GET /domains/:domain/check
Verifies the domain's MX, SPF, DKIM, and DMARC records are correct. Once verified, we will begin forwarding your emails.
curl -X GET https://api.improvmx.com/v3/domains/piedpiper.com/check \
-u "api:$API_KEY" Response:
{
"records": {
"provider": "cloudflare",
"advanced": true,
"dkim1": {
"expected": "dkimprovmx1.improvmx.com.",
"valid": true,
"values": "dkimprovmx1.improvmx.com."
},
"dkim2": {
"expected": "dkimprovmx2.improvmx.com.",
"valid": true,
"values": "dkimprovmx2.improvmx.com."
},
"dmarc": {
"expected": "v=DMARC1; p=none;",
"valid": false,
"values": null
},
"error": null,
"mx": {
"expected": [
"mx1.improvmx.com",
"mx2.improvmx.com"
],
"valid": true,
"values": [
"mx2.improvmx.com",
"mx1.improvmx.com"
]
},
"spf": {
"expected": "v=spf1 include:someservice.org include:spf.improvmx.com ~all",
"valid": false,
"values": "v=spf1 include:someservice.org ~all"
},
"valid": false
},
"success": true
}
Returns success: true when MX is configured
correctly. error contains the reason when not.
Delete domain
DELETE /domains/:domain
curl -X DELETE https://api.improvmx.com/v3/domains/piedpiper.com \
-u "api:$API_KEY" Response:
{
"success": true
} Aliases
Aliases are mailbox identities under your
domain, i.e. richard@piedpiper.com forwards to richard.hendricks@gmail.com
List aliases
GET /domains/:domain/aliases
curl -X GET "https://api.improvmx.com/v3/domains/piedpiper.com/aliases?q=richard" \
-u "api:$API_KEY" | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
q | query | Filter alias and destination by substring. |
alias | query | Filter alias by prefix. |
limit | query | Number of aliases. Default 20, max 100. |
page | query | Page number (1-based, default 1). |
Response:
{
"aliases": [
{
"created": 1702982672000,
"forward": "richard.hendricks@gmail.com",
"alias": "richard",
"id": 4
},
{
"created": 1702982672000,
"forward": "jared.dunn@gmail.com",
"alias": "jared",
"id": 5
}
],
"limit": 20,
"page": 1,
"total": 2,
"success": true
} Get alias
GET /domains/:domain/aliases/:alias
alias can be a string (richard) or the int id (11) returned at creation.
Resolves by id (the string returned at creation or listing).
curl -X GET https://api.improvmx.com/v3/domains/piedpiper.com/aliases/richard \
-u "api:$API_KEY" Response:
{
"alias": {
"created": 1702982672000,
"forward": "richard.hendricks@protonmail.com",
"alias": "richard",
"id": 11
},
"success": true
} Add alias
POST /domains/:domain/aliases
curl -X POST https://api.improvmx.com/v3/domains/piedpiper.com/aliases \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"alias": "richard",
"forward": "richard.hendricks@gmail.com"
}' | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
alias | body | Required. Local part of the address (e.g. contact, info). |
forward | body | Required. Comma-separated destination emails and/or webhooks. |
Response:
{
"alias": {
"forward": "richard.hendricks@gmail.com",
"alias": "richard",
"id": 11
},
"success": true
} Add aliases
POST /domains/:domain/aliases/batch
Batch-create aliases. Returns successful and failed entries
separately, plus counts. 200 when every entry succeeded,
207 Multi-Status when any failed. Each failed entry is exactly
index (its 0-based position in the array you sent),
message and errors — the submitted item isn't
echoed back.
NOTE: Batch-create requires a paid plan.
curl -X POST https://api.improvmx.com/v3/domains/piedpiper.com/aliases/batch \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"aliases": [
{"alias": "richard", "forward": "richard.hendricks@gmail.com"},
{"alias": "jared", "forward": "jared.dunn@gmail.com"}
]
}' | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
aliases | body | Required. Up to 500 objects, each with alias and forward. |
Response:
{
"added": [
{
"alias": "richard",
"forward": "richard.hendricks@gmail.com",
"id": "12345",
"created_at": "2026-05-05T11:32:00Z",
"updated_at": "2026-05-05T11:32:00Z"
},
{
"alias": "jared",
"forward": "jared.dunn@gmail.com",
"id": "12346",
"created_at": "2026-05-05T11:32:00Z",
"updated_at": "2026-05-05T11:32:00Z"
}
],
"added_count": 2,
"failed": [],
"failed_count": 0
} Update alias
PUT /domains/:domain/aliases/:alias
alias can be a string (richard) or the int id (
11) returned at creation.
curl -X PUT https://api.improvmx.com/v3/domains/piedpiper.com/aliases/richard \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"forward": "richard.hendricks@protonmail.com"
}' | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
forward | body | Required. Comma-separated destination emails and/or webhooks. |
Response:
{
"alias": {
"forward": "richard.hendricks@protonmail.com",
"alias": "richard",
"id": 11
},
"success": true
} Update aliases
POST /domains/:domain/aliases/bulk
Batch-update aliases. Returns successful and failed entries separately — partial failures don't fail the request.
NOTE: Creating with behavior: add requires a paid plan.
curl -X POST https://api.improvmx.com/v3/domains/piedpiper.com/aliases/bulk \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{"aliases":[
{"alias":"richard","forward":"richard.hendricks@gmail.com"},
{"alias":"jared", "forward":"jared.dunn@gmail.com"}]
"behavior": "update"}' | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
aliases | body | Required. Up to 500 objects with alias and forward. |
behavior | body | add (default) fails if alias exists,
update updates an existing alias,
delete deletes specified aliases. |
Response (add/update):
{
"added": [
{
"alias": "richard",
"forward": "richard.hendricks@gmail.com",
"id": 12345
},
{
"alias": "jared",
"forward": "jared.dunn@gmail.com",
"id": 12346
}
],
"failed": [
{
"alias": "monica",
"forward": "monica.hall@gmail.com",
"id": 12347
}
],
"success": true,
"updated": [
{
"alias": "dinesh",
"forward": "dinesh.chugtai@gmail.com",
"id": 12348
},
{
"alias": "bertram",
"forward": "bertram.gilfoyle@gmail.com",
"id": 12349
}
]
} Response (delete):
{
"deleted": [
{
"alias": "test",
"created": 1743462739000,
"forward": "myemail@gmail.com",
"id": 6
}
],
"failed": [
{
"alias": "test1"
}
],
"success": true
} Update aliases
PUT /domains/:domain/aliases/batch
Bulk-update aliases by id. Returns successful and failed entries
separately, plus counts. 200 when every entry succeeded,
207 Multi-Status when any failed. Each failed entry is exactly
index (its 0-based position in the array you sent),
message and errors — the submitted item isn't
echoed back.
curl -X PUT https://api.improvmx.com/v3/domains/piedpiper.com/aliases/batch \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"aliases": [
{"id": "12345", "forward": "richard.hendricks@protonmail.com"},
{"id": "12346", "forward": "jared.dunn@protonmail.com"},
{"id": "999999", "forward": "gilfoyle@piedpiper.com"}
]
}' | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
aliases | body | Required. Up to 500 objects, each with a string
id and the fields to update (e.g. forward). |
Response:
{
"updated": [
{
"alias": "richard",
"forward": "richard.hendricks@protonmail.com",
"id": "12345",
"created_at": "2026-05-05T11:32:00Z",
"updated_at": "2026-05-05T12:00:00Z"
},
{
"alias": "jared",
"forward": "jared.dunn@protonmail.com",
"id": "12346",
"created_at": "2026-05-05T11:32:00Z",
"updated_at": "2026-05-05T12:00:00Z"
}
],
"updated_count": 2,
"failed": [
{
"index": 2,
"message": "Alias not found.",
"errors": {}
}
],
"failed_count": 1
} Delete alias
DELETE /domains/:domain/aliases/:alias
alias can be a string (richard) or the int id (11) returned at creation.
Delete alias by id (the string returned at creation or listing).
curl -X DELETE https://api.improvmx.com/v3/domains/piedpiper.com/aliases/richard \
-u "api:$API_KEY" Response:
{
"success": true
} Delete aliases
DELETE /domains/:domain/aliases/batch
Bulk-delete aliases by id. Returns successful and failed entries
separately, plus counts. 200 when every entry succeeded,
207 Multi-Status when any failed. Each failed entry is exactly
index (its 0-based position in the array you sent),
message and errors — the submitted item isn't
echoed back.
curl -X DELETE https://api.improvmx.com/v3/domains/piedpiper.com/aliases/batch \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{"ids": ["12345", "12346", "12347"]}' | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
ids | body | Required. Up to 500 alias ids (strings) to delete. |
Response:
{
"deleted": ["12345", "12346"],
"deleted_count": 2,
"failed": [
{
"index": 2,
"message": "Alias not found.",
"errors": {}
}
],
"failed_count": 1
} Delete all aliases
DELETE /domains/:domain/aliases/aliases-all
The ?all=true query parameter is required — it's a guard so
a misfired request can't wipe every alias by accident. To delete a specific
set of aliases instead, use the batch endpoint.
curl -X DELETE https://api.improvmx.com/v3/domains/piedpiper.com/aliases/aliases-all \
-u "api:$API_KEY" Response:
{
"deleted": 42
} Response:
{
"success": true
} Rules
Rules are used to route incoming email to specific destinations based on various criteria.
There are several types of rules described below.
Alias rule config
Schema for adding or updating alias rules.
{
"alias": "richard",
"forward": "richard.hendricks@gmail.com"
} | PARAMETER | DESCRIPTION |
|---|---|
alias | Required. Alias this rule matches. |
forward | Required. Comma-separated forwarding destinations. |
Regex rule config
Schema for adding or updating regex rules.
{
"forward": "jared.dunn@live.com",
"regex": ".*jared.*",
"scopes": [
"sender",
"recipient",
"subject",
"body"
]
} | PARAMETER | DESCRIPTION |
|---|---|
regex | Required. Regex pattern to match. |
scopes | Required. Match scopes: sender, recipient, subject, body. |
forward | Required. Comma-separated forwarding destinations. |
CEL rule config
Schema for adding or updating CEL rules.
{
"expression": "subject.contains('finance')",
"forward": "monica@yahoo.com"
} | PARAMETER | DESCRIPTION |
|---|---|
expression | Required. CEL expression to match. |
forward | Required. Comma-separated forwarding destinations. |
List rules
GET /domains/:domain/rules
curl -X GET "https://api.improvmx.com/v3/domains/piedpiper.com/rules?search=richard" \
-u "api:$API_KEY" | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
search | query | Filter rules by substring. |
limit | query | Number of rules. Default 100, max 100. |
page | query | Page number (1-based, default 1). |
Response:
{
"limit": 100,
"page": 1,
"rules": [
{
"active": true,
"config": {
"alias": "richard",
"forward": "richard.hendricks@gmail.com"
},
"created": 1752026028000,
"rank": 1.0,
"id": "447a95d1-bac1-4d6e-8315-22b10f501efb",
"type": "alias"
},
{
"active": true,
"config": {
"forward": "jared.dunn@live.com",
"regex": ".*jared.*",
"scopes": [
"sender"
]
},
"created": 1752467418000,
"rank": 2.0,
"id": "fcadc999-0d3f-45f8-9c62-056e1b98e47a",
"type": "regex"
}
],
"success": true,
"total": 2
} Add rule
POST /domains/:domain/rules
curl -X POST https://api.improvmx.com/v3/domains/piedpiper.com/rules \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"type": "regex",
"config": {
"regex": ".*important.*",
"scopes": [
"subject",
"body"
],
"forward": "richard.hendricks@gmail.com"
}
}' | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
type | body | Required. One of alias, regex, or cel. |
config | body | Required. JSON config for the rule (varies by type). |
rank | body | Rank determining evaluation priority. Defaults to the next largest rank. |
active | body | Whether the rule is active. |
id | body | Rule ID. Auto-generated UUID if omitted. |
Response:
{
"rule": {
"active": true,
"config": {
"alias": "richard",
"forward": "richard.hendricks@gmail.com"
},
"created": 1752026028000,
"rank": 1.0,
"id": "447a95d1-bac1-4d6e-8315-22b10f501efb",
"type": "alias"
},
"success": true
} Add rules
POST /domains/:domain/rules/batch
Bulk-create rules. Returns successful and failed entries separately,
plus counts. 200 when every entry succeeded, 207 Multi-Status when any failed. Each failed entry is exactly
index (its 0-based position in the array you sent),
message and errors — the submitted item isn't
echoed back.
curl -X POST https://api.improvmx.com/v3/domains/piedpiper.com/rules/batch \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"rules": [
{
"type": "alias",
"config": {
"alias": "richard",
"forward": "richard.hendricks@gmail.com"
}
},
{
"type": "regex",
"config": {
"regex": ".*finance.*",
"scopes": ["subject"],
"forward": "not-an-email"
}
}
]
}' | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
rules | body | Required. Up to 500 rule objects, each with type and config (and optionally rank, active, id). |
Response:
{
"added": [
{
"active": true,
"config": {
"alias": "richard",
"forward": "richard.hendricks@gmail.com"
},
"created_at": "2026-05-05T11:32:00Z",
"updated_at": "2026-05-05T11:32:00Z",
"id": "62f9cf67-9005-41a6-8706-843ca8df8932",
"rank": 50.0,
"type": "alias"
}
],
"added_count": 1,
"failed": [
{
"index": 1,
"message": "Invalid forward address.",
"errors": {}
}
],
"failed_count": 1
} Get rule
GET /domains/:domain/rules/:rule
curl -X GET https://api.improvmx.com/v3/domains/piedpiper.com/rules/447a95d1-bac1-4d6e-8315-22b10f501efb \
-u "api:$API_KEY" Response:
{
"active": true,
"config": {
"alias": "richard",
"forward": "richard.hendricks@gmail.com"
},
"created": 1752026028000,
"rank": 1.0,
"id": "447a95d1-bac1-4d6e-8315-22b10f501efb",
"type": "alias"
} Update rule
PUT /domains/:domain/rules/:rule
curl -X PUT https://api.improvmx.com/v3/domains/piedpiper.com/rules/e8417681-3a4c-4f9b-ab93-1ca2529036c9 \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"config": {
"regex": ".*critical.*",
"scopes": [
"subject",
"body"
],
"forward": "richard.hendricks@gmail.com"
}
}' | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
config | body | Required. JSON config for the rule (varies by type). |
rank | body | Rank determining evaluation priority. Defaults to the next largest rank. |
active | body | Whether the rule is active. |
Response:
{
"rule": {
"active": true,
"config": {
"regex": ".*critical.*",
"scopes": [
"subject",
"body"
],
"forward": "richard.hendricks@gmail.com"
},
"created": 1752026028,
"id": "447a95d1-bac1-4d6e-8315-22b10f501efb",
"rank": 1.0,
"type": "alias"
},
"success": true
} Update rules
POST /domains/:domain/rules/bulk
# Add a rule
curl -X POST https://api.improvmx.com/v3/domains/piedpiper.com/rules/bulk \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"behavior": "add",
"rules": [
{
"type": "cel",
"config": {
"expression": "true",
"forward": "richard.hendricks@gmail.com"
}
}
]
}'
# Update 2 rules
curl -X POST https://api.improvmx.com/v3/domains/piedpiper.com/rules/bulk \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"behavior": "update",
"rules": [
{
"id": "62f9cf67-9005-41a6-8706-843ca8df8932",
"config": {
"alias": "gavin.belson@gmail.com"
}
},
{
"id": "5742c992-4378-4412-945b-be2177072fc4",
"config": {
"regex": ".*finance.*"
}
}
]
}'
# Delete 2 rules
curl -X POST https://api.improvmx.com/v3/domains/piedpiper.com/rules/bulk \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"behavior": "delete",
"rules": [
{
"id": "62f9cf67-9005-41a6-8706-843ca8df8932"
},
{
"id": "48ec8f60-ea1f-4509-9c36-43f5e83170b5"
}
]
}' | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
rules | body | Required. List of JSON configs (varies by rule type). |
behavior | body | add (default) fails if rule exists,
update updates existing rules,
delete deletes specified rules. |
Response:
{
"errors": [],
"results": [
{
"operation": "update",
"rule": {
"active": true,
"config": {
"alias": "gavin@gmail.com",
"forward": "gavin.belson@gmail.com"
},
"created": 1752514190,
"id": "62f9cf67-9005-41a6-8706-843ca8df8932",
"rank": 50.0,
"type": "alias"
},
"success": true
},
{
"operation": "update",
"rule": {
"active": true,
"config": {
"forward": "jared.dunn@live.com",
"regex": ".+",
"scopes": [
"subject",
"body"
]
},
"created": 1752510060,
"id": "5742c992-4378-4412-945b-be2177072fc4",
"rank": 40.0,
"type": "regex"
},
"success": true
}
],
"success": true
} Update rules
PUT /domains/:domain/rules/batch
Bulk-update rules by id. Returns successful and failed entries
separately, plus counts. 200 when every entry succeeded,
207 Multi-Status when any failed. Each failed entry is exactly
index (its 0-based position in the array you sent),
message and errors — the submitted item isn't
echoed back.
curl -X PUT https://api.improvmx.com/v3/domains/piedpiper.com/rules/batch \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"rules": [
{
"id": "62f9cf67-9005-41a6-8706-843ca8df8932",
"config": {
"alias": "gavin.belson@gmail.com"
}
},
{
"id": "00000000-0000-0000-0000-000000000000",
"config": {"regex": ".+"}
}
]
}' | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
rules | body | Required. Up to 500 objects, each with a string
id and the fields to update (e.g. config, rank,
active). |
Response:
{
"updated": [
{
"active": true,
"config": {
"alias": "gavin@gmail.com",
"forward": "gavin.belson@gmail.com"
},
"created_at": "2025-07-14T17:29:50Z",
"updated_at": "2026-05-05T11:32:00Z",
"id": "62f9cf67-9005-41a6-8706-843ca8df8932",
"rank": 50.0,
"type": "alias"
}
],
"updated_count": 1,
"failed": [
{
"index": 1,
"message": "Rule not found.",
"errors": {}
}
],
"failed_count": 1
} Delete rule
DELETE /domains/:domain/rules/:rule
curl -X DELETE https://api.improvmx.com/v3/domains/piedpiper.com/rules/e8417681-3a4c-4f9b-ab93-1ca2529036c9 \
-u "api:$API_KEY" Response:
{
"success": true
} Delete rules
DELETE /domains/:domain/rules/batch
Bulk-delete rules by id. Returns successful and failed entries
separately, plus counts. 200 when every entry succeeded,
207 Multi-Status when any failed. Each failed entry is exactly
index (its 0-based position in the array you sent),
message and errors — the submitted item isn't
echoed back.
curl -X DELETE https://api.improvmx.com/v3/domains/piedpiper.com/rules/batch \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"ids": [
"62f9cf67-9005-41a6-8706-843ca8df8932",
"5742c992-4378-4412-945b-be2177072fc4",
"00000000-0000-0000-0000-000000000000"
]
}' | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
ids | body | Required. Up to 500 rule ids (UUID strings) to delete. |
Response:
{
"deleted": [
"62f9cf67-9005-41a6-8706-843ca8df8932",
"5742c992-4378-4412-945b-be2177072fc4"
],
"deleted_count": 2,
"failed": [
{
"index": 2,
"message": "Rule not found.",
"errors": {}
}
],
"failed_count": 1
} Delete all rules
DELETE /domains/:domain/rules-all
The ?all=true query parameter is required — it's a guard so
a misfired request can't wipe every rule by accident. To delete a specific
set of rules instead, use the batch endpoint.
curl -X DELETE https://api.improvmx.com/v3/domains/piedpiper.com/rules-all \
-u "api:$API_KEY" Response:
{
"deleted": 42
} Response:
{
"success": true
} Email Logs
View your domain logs to see emails sent or received.
List email logs
GET /domains/:domain/logs
curl -X GET https://api.improvmx.com/v3/domains/piedpiper.com/logs \
-u "api:$API_KEY" | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
next_cursor | query | Load logs after this log id (e.g. 20201002014128.7ea8ee5b46). Pass next_cursor from the previous response to paginate. |
Response:
{
"logs": [
{
"created": 1579954749000,
"created_raw": 1579954749000,
"events": [
{
"code": 250,
"created": 1579954751000,
"id": "<20200125121911.4a9c2e7b@mail.hooli.com>-0",
"local": "mxb.infra.improvmx.com",
"message": "Queued",
"server": "mail-io1-f54.google.com",
"status": "QUEUED"
},
{
"code": 250,
"created": 1579954752000,
"id": "<20200125121911.4a9c2e7b@mail.hooli.com>-1",
"local": "gmail-smtp-in.l.google.com",
"message": "Sent.",
"server": "mail16.mxc.infra.improvmx.com",
"status": "DELIVERED"
}
],
"forward": {
"email": "richard.hendricks@gmail.com",
"name": "Richard Hendricks"
},
"hostname": "mail-io1-f54.google.com",
"id": "20201002014128.5ea8ee59fa894aa7a9141e9665985b46",
"messageId": "<20200125121911.4a9c2e7b@mail.hooli.com>",
"recipient": {
"email": "richard@piedpiper.com",
"name": "Richard Hendricks"
},
"sender": {
"email": "gavin@hooli.com",
"name": "Gavin Belsonx"
},
"subject": "You are screwed, Piedpiper team!",
"transport": "smtp"
},
{
"created": 1579951841000,
"created_raw": 1579951841000,
"events": [
{
"code": 550,
"created": 1579951842000,
"id": "<20200125113041.7f3a1d8c@mail.hooli.com>-0",
"local": "mxa.infra.improvmx.com",
"message": "5.7.1 Message considered as SPAM (Score of 5.8/5.0 with BAYES_20, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, HTML_MESSAGE, HTML_TAG_BALANCE_BODY, MIME_HEADER_CTYPE_ONLY, NO_RELAYS, URIBL_ABUSE_SURBL, URIBL_DBL_ABUSE_SPAM, URIBL_DBL_SPAM)",
"server": "mail-wm1-f67.google.com",
"status": "REFUSED"
}
],
"forward": null,
"hostname": "mail-wm1-f67.google.com",
"id": "20201002014128.7ea8ee59fa894aa7a91415a6659c5b46",
"messageId": "<20200125113041.7f3a1d8c@mail.hooli.com>",
"recipient": {
"email": "richard@piedpiper.com",
"name": null
},
"sender": {
"email": "spam@hooli.com",
"name": "ThinkTeam"
},
"subject": "Enlarge your (pied)piper!",
"transport": "smtp"
}
],
"success": true
}
Each entry in logs contains a list of events. Possible statuses:
| Status | Description |
|---|---|
QUEUED | Accepted for processing. |
REFUSED | Refused at the SMTP connection. |
DELIVERED | Delivered to the destination. |
SOFT-BOUNCE | Temporarily refused. Retried with backoff. |
HARD-BOUNCE | Rejected by the destination. |
BOUNCED | Delivery failed — a bounce not classified as soft or hard. |
Count email logs
GET /domains/:domain/logs/count
Returns the total number of logs matching the same filters as the list endpoint above.
curl -X GET https://api.improvmx.com/v3/domains/piedpiper.com/logs/count \
-u "api:$API_KEY" -G \
--data-urlencode "sender=gavin@hooli.com" \
--data-urlencode "status=DELIVERED,SOFT-BOUNCE" | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
sender | query | Exact match on sender address (case-insensitive). |
recipient | query | Exact match on recipient address (case-insensitive). |
forward | query | Exact match on forwarding destination (case-insensitive). |
status | query |
Filter to logs that contain an event with this status.
Comma-separated list of QUEUED, DELIVERED,
SOFT-BOUNCE, HARD-BOUNCE, BOUNCED,
REFUSED.
|
transport | query |
Filter by message transport. One of mx (forwarded mail),
smtp (authenticated SMTP sends), or api (messages sent through the API).
|
after | query |
ISO 8601 timestamp (e.g. 2024-07-02T12:00:00Z).
Counts entries received after this time.
|
before | query | ISO 8601 timestamp. Counts entries received before this time. |
Response:
Get email log
GET /domains/:domain/logs/:id
Look up one email by its id — any entry's id from
the list above. Returns that entry, including its full events delivery timeline. Responds with
404 if no log with that id exists for the domain.
curl -X GET https://api.improvmx.com/v3/domains/piedpiper.com/logs/20250330190000.a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 \
-u "api:$API_KEY" Response:
List alias email logs
GET /domains/:domain/logs/:alias
curl -X GET https://api.improvmx.com/v3/domains/piedpiper.com/logs/richard \
-u "api:$API_KEY" Same as the domain logs endpoint, scoped to one alias.
Each entry in logs contains a list of events. Possible statuses:
| PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
next_cursor | query | Load logs after this log id (e.g. 20201002014128.15a6659c5b46). |
Response:
{
"logs": [
{
"created": 1579954749000,
"created_raw": 1579954749000,
"events": [
{
"code": 250,
"created": 1579954751000,
"id": "<20200125121911.4a9c2e7b@mail.hooli.com>-0",
"local": "mxb.infra.improvmx.com",
"message": "Queued",
"server": "mail-io1-f54.google.com",
"status": "QUEUED"
},
{
"code": 250,
"created": 1579954752000,
"id": "<20200125121911.4a9c2e7b@mail.hooli.com>-1",
"local": "gmail-smtp-in.l.google.com",
"message": "Sent.",
"server": "mail16.mxc.infra.improvmx.com",
"status": "DELIVERED"
}
],
"forward": {
"email": "richard.hendricks@gmail.com",
"name": "Richard Hendricks"
},
"hostname": "mail-io1-f54.google.com",
"id": "20201002014128.5ea8ee59fa894aa7a9141e9665985b46",
"messageId": "<20200125121911.4a9c2e7b@mail.hooli.com>",
"recipient": {
"email": "richard@piedpiper.com",
"name": "Richard Hendricks"
},
"sender": {
"email": "gavin@hooli.com",
"name": "Gavin Belsonx"
},
"subject": "You are screwed, Piedpiper team!",
"transport": "smtp"
},
{
"created": 1579951841000,
"created_raw": 1579951841000,
"events": [
{
"code": 550,
"created": 1579951842000,
"id": "<20200125113041.7f3a1d8c@mail.hooli.com>-0",
"local": "mxa.infra.improvmx.com",
"message": "5.7.1 Message considered as SPAM (Score of 5.8/5.0 with BAYES_20, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, HTML_MESSAGE, HTML_TAG_BALANCE_BODY, MIME_HEADER_CTYPE_ONLY, NO_RELAYS, URIBL_ABUSE_SURBL, URIBL_DBL_ABUSE_SPAM, URIBL_DBL_SPAM)",
"server": "mail-wm1-f67.google.com",
"status": "REFUSED"
}
],
"forward": null,
"id": "20201002014128.7ea8ee59fa894aa7a91415a6659c5b46",
"hostname": "mail-wm1-f67.google.com",
"messageId": "<20200125113041.7f3a1d8c@mail.hooli.com>",
"recipient": {
"email": "richard@piedpiper.com",
"name": null
},
"sender": {
"email": "spam@hooli.com",
"name": "ThinkTeam"
},
"subject": "Enlarge your (pied)piper!",
"transport": "smtp"
}
],
"success": true
} Search email logs
GET /domains/:domain/logs/search
Filter logs by timestamp window. Pass Unix seconds in after and before.
curl -X GET https://api.improvmx.com/v3/domains/piedpiper.com/logs/search \
-u "api:$API_KEY" -G \
--data-urlencode "filter=<filter>" \
--data-urlencode "text=<keyword>" \
--data-urlencode "order=<asc_or_desc>" \
--data-urlencode "after=<unix_timestamp_seconds>" \
--data-urlencode "before=<unix_timestamp_seconds>" | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
filter | query | all (default) or failure
(bounces only).
|
text | query | Case-insensitive match on subject, sender, recipient, or destination. |
order | query | desc (default, newest first) or asc.
|
after | query | Required.
Unix seconds. Returns entries with received_at >= after.
|
before | query | Required.
Unix seconds. Returns entries with received_at <= before.
|
To use a human-readable date, convert to Unix seconds first (e.g. date --date='2024-07-02T12:00:00Z' +%s).
Response:
{
"logs": [
{
"created": 1747043118000,
"created_raw": 1747043118000,
"events": [
{
"code": 250,
"created": 1747043120000,
"id": "<20250512094518.7c1a9f3e@mail.raviga.com>-0",
"local": "mx1.improvmx.com",
"message": "Queued",
"server": "mail-yw1-f44.google.com",
"status": "QUEUED"
},
{
"code": 250,
"created": 1747043123000,
"id": "<20250512094518.7c1a9f3e@mail.raviga.com>-1",
"local": "gmail-smtp-in.l.google.com",
"message": "Sent.",
"server": "mail7.mxa.infra.improvmx.com",
"status": "DELIVERED"
}
],
"forward": {
"email": "richard.hendricks@gmail.com",
"name": "Richard Hendricks"
},
"hostname": "mail-yw1-f44.google.com",
"id": "20250512094518.0412c5c8a4f74a82b4d02ea83404a6f1",
"messageId": "<20250512094518.7c1a9f3e@mail.raviga.com>",
"recipient": {
"email": "richard@piedpiper.com",
"name": null
},
"sender": {
"email": "monica@raviga.com",
"name": "Monica Hall"
},
"subject": "Series A term sheet draft",
"transport": "smtp"
},
{
"created": 1747030324000,
"created_raw": 1747030324000,
"events": [
{
"code": 250,
"created": 1747030325000,
"id": "<20250512061204.b4e82d6a@mail.raviga.com>-0",
"local": "mx2.improvmx.com",
"message": "Queued",
"server": "mail-pj1-f32.google.com",
"status": "QUEUED"
},
{
"code": 250,
"created": 1747030327000,
"id": "<20250512061204.b4e82d6a@mail.raviga.com>-1",
"local": "gmail-smtp-in.l.google.com",
"message": "Sent.",
"server": "mail12.mxa.infra.improvmx.com",
"status": "DELIVERED"
}
],
"forward": {
"email": "jared.dunn@gmail.com",
"name": "Jared Dunn"
},
"hostname": "mail-pj1-f32.google.com",
"id": "20250512061204.9f65bc20deab4f71bcedad1dfc513e9a",
"messageId": "<20250512061204.b4e82d6a@mail.raviga.com>",
"recipient": {
"email": "jared@piedpiper.com",
"name": null
},
"sender": {
"email": "laurie@raviga.com",
"name": "Laurie Bream"
},
"subject": "Re: Series A funding timeline",
"transport": "smtp"
}
],
"success": true
} SMTP Credentials
Add SMTP credentials to send emails from your domain,
e.g. send from richard@piedpiper.com instead of
richard@gmail.com.
List credentials
GET /domains/:domain/credentials
curl -X GET https://api.improvmx.com/v3/domains/piedpiper.com/credentials \
-u "api:$API_KEY" | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
limit | query | Number of credentials. Default 20, max 200. |
page | query | Page number (1-based, default 1). |
Response:
{
"credentials": [
{
"created": 1581604970000,
"usage": 0,
"username": "richard"
},
{
"created": 1581607028000,
"usage": 0,
"username": "monica"
}
],
"success": true
} Add credential
POST /domains/:domain/credentials
curl -X POST https://api.improvmx.com/v3/domains/piedpiper.com/credentials \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"username": "bighead",
"password": "abc123"
}' | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
username | body | Required. Alias name (e.g. bighead for bighead@piedpiper.com). |
password | body | Required. SMTP credential password. |
Response:
{
"credential": {
"created": 1588236952000,
"usage": 0,
"username": "bighead"
},
"requires_new_mx_check": false,
"success": true
} requires_new_mx_check is true on your first credential. First-time
SMTP setup requires two new DKIM CNAMEs and a DMARC TXT entry in your DNS;
sending is blocked until they're added.
Update credential
PUT /domains/:domain/credentials/:username
curl -X PUT https://api.improvmx.com/v3/domains/piedpiper.com/credentials/bighead \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"password": "abcd1234"
}' Response:
{
"credential": {
"created": 1588236952000,
"usage": 0,
"username": "bighead"
},
"success": true
} Delete credential
DELETE /domains/:domain/credentials/:username
curl -X DELETE https://api.improvmx.com/v3/domains/piedpiper.com/credentials/russ \
-u "api:$API_KEY" Response:
{
"success": true
} Send APIBeta
Send emails from your domain through the same infrastructure as SMTP credentials.
NOTE: Sending is a premium feature, and is for transactional email only. Marketing email is not supported and will get your account blocked.
Send emailBeta
POST /domains/:domain/emails/outbound
curl -X POST https://api.improvmx.com/v3/domains/piedpiper.com/emails/outbound \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"from": "richard",
"to": "gilfoyle@example.com",
"subject": "Hello from the API",
"text": "This is a plain text email sent via the ImprovMX API.",
"html": "Hello! This is an HTML email sent via the ImprovMX API."
}' | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
from | body | Required. Local part of the sender address (e.g.
richard →
richard@piedpiper.com). |
to | body | Required. Recipient(s). String or array of strings. |
subject | body | Required*. Email subject. *Optional when template provides one. Supports Mustache variables. |
text | body | Plain text body. Required (along with or instead of html) when template is not used. |
html | body | HTML body. Required (along with or instead of text) when
template is not used. |
template | body | Name of a saved template. Its subject, html_body, and text_body are rendered with variables. Request-level text / html are ignored; subject overrides
the template's. |
variables | body | Mustache variable substitutions. Only used with template. |
cc | body | CC recipient(s). String or array of strings. |
bcc | body | BCC recipient(s). String or array of strings. |
reply_to | body | Reply-To email address. |
attachments | body | Each object needs filename and content (base64). Optional: content_type (inferred from filename)
and content_id for inline CID images (e.g. <img src="cid:logo">). Max 25 attachments, 10 MB total. Executable extensions (exe,
bat, js, vbs, ps1, scr, etc.) are blocked. |
Response:
{
"id": "20250330190000.a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
"message_id": "<174336120000.1560119.13026979903154377804@piedpiper.com>",
"success": true
}
Track delivery by looking up the returned id via Get email log (or find it in your domain's email logs) — it's the log entry's id (one entry per recipient).
message_id is the message's RFC 5322 Message-ID, matching the
logs message_id field.
Example: multiple recipients with CC and BCC
curl -X POST https://api.improvmx.com/v3/domains/piedpiper.com/emails/outbound \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"from": "richard",
"to": [
"gilfoyle@example.com",
"dinesh@example.com"
],
"cc": [
"jared@example.com"
],
"bcc": [
"bighead@example.com"
],
"reply_to": "support@piedpiper.com",
"subject": "Team update",
"text": "Here is the latest update.",
"html": "Here is the latest update.
"
}' Example: sending with a template
Render a saved template with variables.
curl -X POST https://api.improvmx.com/v3/domains/piedpiper.com/emails/outbound \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"from": "richard",
"to": "gilfoyle@example.com",
"template": "welcome",
"variables": {
"first_name": "Gilfoyle",
"company": "Pied Piper"
}
}' Example: sending with attachments
Pass each attachment with base64 content. content_type is inferred from the filename if omitted.
curl -X POST https://api.improvmx.com/v3/domains/piedpiper.com/emails/outbound \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"from": "richard",
"to": "gilfoyle@example.com",
"subject": "Q4 Report",
"text": "Please find the report attached.",
"attachments": [
{
"filename": "report.pdf",
"content": "JVBERi0xLjQg...",
"content_type": "application/pdf"
}
]
}' Example: inline image with content_id
Embed inline images via cid: references using content_id.
curl -X POST https://api.improvmx.com/v3/domains/piedpiper.com/emails/outbound \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"from": "richard",
"to": "gilfoyle@example.com",
"subject": "Check out our new logo",
"html": "<p>Here is our logo:</p><img src=\"cid:logo\">",
"attachments": [
{
"filename": "logo.png",
"content": "iVBORw0KGgo...",
"content_type": "image/png",
"content_id": "logo"
}
]
}' Error responsesBeta
| CODE | DESCRIPTION |
|---|---|
| 400 | Missing required fields - from,
to, or subject is missing. |
| 400 | No body content - text or
html is required. |
| 400 | Invalid email addresses - Invalid address in
to, cc, bcc, or reply_to. |
| 400 | Invalid variables - variables
must be a JSON object. |
| 400 | Invalid Mustache template - Malformed Mustache syntax in the template's subject or body. |
| 400 | Invalid attachment - Missing filename
or content, invalid base64, invalid content_type, or attachments is not an array. |
| 400 | Blocked file type - Blocked extension (e.g. exe, bat, js, vbs, ps1, scr). |
| 400 | Attachment size limit - Over 10 MB total or more than 25 attachments. |
| 403 | Premium required - A premium plan is required to send emails via API. |
| 403 | Domain not configured for sending - The domain's
DNS settings are not configured for sending. Visit https://app.improvmx.com/domains/:domain/dns to complete setup. |
| 404 | Domain not found - Not in your account. |
| 404 | Template not found - No template with
that name on this domain. |
| 429 | Rate limited - Exceeded 10 requests/minute. |
Send API TemplatesBeta
Save reusable templates per domain and reference them by name when sending. Subject and body support Mustache variables filled from the request's variables object.
Requires a premium plan. Up to 200 templates per domain.
NOTE: Templates are for transactional email only, not marketing campaigns.
Template objectBeta
{
"name": "welcome",
"description": "Welcome email for new signups",
"subject": "Welcome, {{first_name}}!",
"html_body": "<p>Hi {{first_name}}, welcome to {{company}}.</p>",
"text_body": "Hi {{first_name}}, welcome to {{company}}.",
"created_at": "2025-03-30T19:00:00Z",
"updated_at": "2025-03-30T19:00:00Z"
} | PARAMETER | TYPE | DESCRIPTION |
|---|---|---|
name | String | Required. Unique within the domain. Lowercase letters, numbers, hyphens, underscores; must start with a letter or number. Max 250 chars. |
description | String | Description (max 500 chars). |
subject | String | Default subject (max 250 chars). Supports Mustache. |
html_body | String | HTML body (max 100,000 chars). Supports Mustache. |
text_body | String | Plain text body (max 100,000 chars). Supports Mustache. |
List templatesBeta
GET /domains/:domain/templates
curl -X GET https://api.improvmx.com/v3/domains/piedpiper.com/templates \
-u "api:$API_KEY"
Returns summary fields (name, description, subject, created_at, updated_at) only. Fetch a
single template to get its bodies.
{
"success": true,
"templates": [
{
"name": "welcome",
"description": "Welcome email for new signups",
"subject": "Welcome, {{first_name}}!",
"created_at": "2025-03-30T19:00:00Z",
"updated_at": "2025-03-30T19:00:00Z"
}
]
} Get templateBeta
GET /domains/:domain/templates/:name
curl -X GET https://api.improvmx.com/v3/domains/piedpiper.com/templates/welcome \
-u "api:$API_KEY" Response:
{
"success": true,
"template": {
"name": "welcome",
"description": "Welcome email for new signups",
"subject": "Welcome, {{first_name}}!",
"html_body": "<p>Hi {{first_name}}, welcome to {{company}}.</p>",
"text_body": "Hi {{first_name}}, welcome to {{company}}.",
"created_at": "2025-03-30T19:00:00Z",
"updated_at": "2025-03-30T19:00:00Z"
}
} Create templateBeta
POST /domains/:domain/templates
curl -X POST https://api.improvmx.com/v3/domains/piedpiper.com/templates \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"name": "welcome",
"description": "Welcome email for new signups",
"subject": "Welcome, {{first_name}}!",
"html_body": "Hi {{first_name}}, welcome to {{company}}.
",
"text_body": "Hi {{first_name}}, welcome to {{company}}."
}' Response:
{
"success": true,
"template": {
"name": "welcome",
"description": "Welcome email for new signups",
"subject": "Welcome, {{first_name}}!",
"html_body": "<p>Hi {{first_name}}, welcome to {{company}}.</p>",
"text_body": "Hi {{first_name}}, welcome to {{company}}.",
"created_at": "2025-03-30T19:00:00Z",
"updated_at": "2025-03-30T19:00:00Z"
}
} Error responses
| CODE | DESCRIPTION |
|---|---|
| 400 | Validation error - Missing name,
invalid name format, field too long, or invalid Mustache syntax. |
| 400 | Template already exists - name is taken
on this domain. |
| 400 | Limit reached - 200 templates per domain. |
| 403 | Premium required - Templates require a premium plan. |
| 404 | Domain not found - Not in your account. |
Update templateBeta
PUT /domains/:domain/templates/:name
Only included fields are updated. Pass a new name to rename.
curl -X PUT https://api.improvmx.com/v3/domains/piedpiper.com/templates/welcome \
-u "api:$API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"subject": "Welcome to {{company}}, {{first_name}}!"
}' Response:
{
"success": true,
"template": {
"name": "welcome",
"description": "Welcome email for new signups",
"subject": "Welcome to {{company}}, {{first_name}}!",
"html_body": "<p>Hi {{first_name}}, welcome to {{company}}.</p>",
"text_body": "Hi {{first_name}}, welcome to {{company}}.",
"created_at": "2025-03-30T19:00:00Z",
"updated_at": "2025-03-30T19:05:00Z"
}
} Error responses
| CODE | DESCRIPTION |
|---|---|
| 400 | Validation error - Invalid name format, field too long, or invalid Mustache syntax. |
| 400 | Template already exists - New name
is taken by another template. |
| 404 | Domain or template not found - Not in your account. |
Delete templateBeta
DELETE /domains/:domain/templates/:name
curl -X DELETE https://api.improvmx.com/v3/domains/piedpiper.com/templates/welcome \
-u "api:$API_KEY" Response:
{
"success": true
}