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 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" 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
} Rate limiting
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 configured correctly. Once verified, our servers will begin forwarding.
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 -> 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 — partial failures don't fail the request.
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"
}
],
"failed": []
} 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.
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 — partial failures don't fail the request.
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"}
]
}' | 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"
}
],
"failed": [
{
"id": "999999",
"forward": "x@example.com",
"error": "Alias not found."
}
]
} 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 — partial failures don't fail the request.
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"],
"failed": [
{
"id": "12347",
"error": "Alias not found."
}
]
} 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 — partial failures don't fail the request.
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": "jared.dunn@gmail.com"
}
}
]
}' | 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"
}
],
"failed": [
{
"type": "regex",
"config": {
"regex": ".*finance.*",
"scopes": ["subject"],
"forward": "not-an-email"
},
"error": "Invalid forward address."
}
]
} 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 — partial failures don't fail the request.
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": "5742c992-4378-4412-945b-be2177072fc4",
"config": {
"regex": ".*finance.*"
}
}
]
}' | 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"
}
],
"failed": [
{
"id": "00000000-0000-0000-0000-000000000000",
"config": {"regex": ".+"},
"error": "Rule not found."
}
]
} 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 — partial failures don't fail the request.
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"
]
}' | 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"
],
"failed": [
{
"id": "00000000-0000-0000-0000-000000000000",
"error": "Rule not found."
}
]
} 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 the logs for your domain to see all the emails that have been sent and 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 (Send API messages).
|
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 — the id returned
by the Send API (or 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 your domain to send emails from
your domain. I.e. send from richard@piedpiper.com instead of
richard.hendricks@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. Local part of the mailbox (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
}