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/v4

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/v4/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/v4/domains?query=pied" \
  -u "api:$API_KEY"

Adding a domain sends a body parameter as JSON:

curl -X POST https://api.improvmx.com/v4/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:

{
    "message": "You cannot use your domain in your email.",
    "errors": {
        "email": [
            "You cannot use your domain in your email."
        ]
    }
}

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/v4/account \
  -u "api:$API_KEY"

Response:

{
    "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": "[email protected]",
        "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"
    }
}

Domains

Add domains to ImprovMX that you want to send/receive emails from.

List domains

GET /domains

curl -X GET "https://api.improvmx.com/v4/domains?query=pied" \
  -u "api:$API_KEY"
PARAMETER TYPE DESCRIPTION
query query Filter domains by substring.
forwarding_ready query Only domains whose MX records resolve to ImprovMX (true) or not (false).
send_ready query Only domains ready (true) or not ready (false) to send outbound mail.
whitelabel query Filter by whitelabel: a specific brand (e.g. hooli.com) matches that whitelabel exactly, null matches domains without one. Omit to not filter.
routing_engine query Filter by routing engine: alias or rules matches that engine exactly, null matches domains with routing disabled. Omit to not filter.
order query Sort order: name_asc (default), name_desc, created_asc, or created_desc.
limit query Number of domains. Default 20, max 200.
page query Page number (1-based, default 1).

Response:

{
    "domains": [
        {
            "domain": "google.com",
            "forwarding_ready": true,
            "send_ready": false,
            "banned": false,
            "notification_email": null,
            "notify_when_spam_blocked": false,
            "routing_engine": null,
            "rules_fallback_email": null,
            "strict_mxes": true,
            "whitelabel": null,
            "created_at": "2019-06-04T09:14:57Z",
            "updated_at": "2019-06-04T09:14:57Z"
        },
        {
            "domain": "piedpiper.com",
            "forwarding_ready": false,
            "send_ready": false,
            "banned": false,
            "notification_email": null,
            "notify_when_spam_blocked": false,
            "routing_engine": null,
            "rules_fallback_email": null,
            "strict_mxes": true,
            "whitelabel": null,
            "created_at": "2019-06-04T09:15:33Z",
            "updated_at": "2019-06-04T09:15:33Z"
        }
    ],
    "total": 2,
    "limit": 20,
    "page": 1
}

Use query to filter domains by substring, as shown in the curl example above. Response:

{
    "domains": [
        {
            "domain": "piedpiper.com",
            "forwarding_ready": true,
            "send_ready": false,
            "banned": false,
            "notification_email": null,
            "notify_when_spam_blocked": false,
            "routing_engine": null,
            "rules_fallback_email": null,
            "strict_mxes": true,
            "whitelabel": null,
            "created_at": "2019-06-04T09:15:27Z",
            "updated_at": "2019-06-04T09:15:27Z"
        }
    ],
    "total": 1,
    "limit": 20,
    "page": 1
}

Get domain

GET /domains/:domain

curl -X GET https://api.improvmx.com/v4/domains/piedpiper.com \
  -u "api:$API_KEY"

Response:

{
    "domain": {
        "domain": "piedpiper.com",
        "forwarding_ready": false,
        "send_ready": false,
        "banned": false,
        "notification_email": null,
        "notify_when_spam_blocked": false,
        "routing_engine": null,
        "rules_fallback_email": null,
        "strict_mxes": true,
        "whitelabel": null,
        "created_at": "2019-06-04T09:15:33Z",
        "updated_at": "2019-06-04T09:15:33Z"
    }
}

Add domain

POST /domains

curl -X POST https://api.improvmx.com/v4/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": {
        "domain": "piedpiper.com",
        "forwarding_ready": false,
        "send_ready": false,
        "banned": false,
        "notification_email": null,
        "notify_when_spam_blocked": false,
        "routing_engine": null,
        "rules_fallback_email": null,
        "strict_mxes": true,
        "whitelabel": null,
        "created_at": "2019-06-04T12:53:26Z",
        "updated_at": "2019-06-04T12:53:26Z"
    }
}

Update domain

PUT /domains/:domain

The domain name cannot be changed.

curl -X PUT https://api.improvmx.com/v4/domains/piedpiper.com \
  -u "api:$API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
      "notification_email": "[email protected]",
      "whitelabel": "hooli.com"
  }'
PARAMETER TYPE DESCRIPTION
notification_email body Optionally, where to send notifications. Defaults to your account email.
whitelabel body Parent domain owner.

Response:

{
    "domain": {
        "domain": "piedpiper.com",
        "forwarding_ready": false,
        "send_ready": false,
        "banned": false,
        "notification_email": "[email protected]",
        "notify_when_spam_blocked": false,
        "routing_engine": null,
        "rules_fallback_email": null,
        "strict_mxes": true,
        "whitelabel": "hooli.com",
        "created_at": "2019-06-04T09:15:33Z",
        "updated_at": "2026-05-06T12:00:00Z"
    }
}

Verify domain

POST /domains/:domain/verify

Verifies the domain's MX, SPF, DKIM, and DMARC records are correct. Once verified, we will begin forwarding your emails.

curl -X POST https://api.improvmx.com/v4/domains/piedpiper.com/verify \
  -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
    }
}

The error field contains the reason when MX is not configured correctly.

Delete domain

DELETE /domains/:domain

curl -X DELETE https://api.improvmx.com/v4/domains/piedpiper.com \
  -u "api:$API_KEY"

Returns 204 No Content on success.

Aliases

Aliases are mailbox identities under your domain, i.e. [email protected] forwards to [email protected]

List aliases

GET /domains/:domain/aliases

curl -X GET "https://api.improvmx.com/v4/domains/piedpiper.com/aliases?query=richard" \
  -u "api:$API_KEY"
PARAMETER TYPE DESCRIPTION
query query Filter alias and destination by substring.
order query Sort order: name_asc (default), name_desc, created_asc, or created_desc.
limit query Number of aliases. Default 20, max 200.
page query Page number (1-based, default 1).

Response:

{
    "aliases": [
        {
            "created_at": "2023-12-19T10:44:32Z",
            "updated_at": "2023-12-19T10:44:32Z",
            "forward": "[email protected]",
            "alias": "richard",
            "id": "4"
        },
        {
            "created_at": "2023-12-19T10:44:32Z",
            "updated_at": "2023-12-19T10:44:32Z",
            "forward": "[email protected]",
            "alias": "jared",
            "id": "5"
        }
    ],
    "limit": 20,
    "page": 1,
    "total": 2
}

Get alias

GET /domains/:domain/aliases/:id

Resolves by id (the string returned at creation or listing).

curl -X GET https://api.improvmx.com/v4/domains/piedpiper.com/aliases/11 \
  -u "api:$API_KEY"

Response:

{
    "alias": {
        "created_at": "2023-12-19T10:44:32Z",
        "updated_at": "2023-12-19T10:44:32Z",
        "forward": "[email protected]",
        "alias": "richard",
        "id": "11"
    }
}

Add alias

POST /domains/:domain/aliases

curl -X POST https://api.improvmx.com/v4/domains/piedpiper.com/aliases \
  -u "api:$API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
      "alias": "richard",
      "forward": "[email protected]"
  }'
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": "[email protected]",
        "alias": "richard",
        "id": "11",
        "created_at": "2026-05-05T11:32:00Z",
        "updated_at": "2026-05-05T11:32:00Z"
    }
}

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/v4/domains/piedpiper.com/aliases/batch \
  -u "api:$API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
      "aliases": [
          {"alias": "richard", "forward": "[email protected]"},
          {"alias": "jared", "forward": "[email protected]"}
      ]
  }'
PARAMETER TYPE DESCRIPTION
aliases body Required. Up to 500 objects, each with alias and forward.

Response:

{
    "added": [
        {
            "alias": "richard",
            "forward": "[email protected]",
            "id": "12345",
            "created_at": "2026-05-05T11:32:00Z",
            "updated_at": "2026-05-05T11:32:00Z"
        },
        {
            "alias": "jared",
            "forward": "[email protected]",
            "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/:id

Alias must be the numeric id 11 returned at creation or listing.

curl -X PUT https://api.improvmx.com/v4/domains/piedpiper.com/aliases/11 \
  -u "api:$API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
      "forward": "[email protected]"
  }'
PARAMETER TYPE DESCRIPTION
forward body Required. Comma-separated destination emails and/or webhooks.

Response:

{
    "alias": {
        "forward": "[email protected]",
        "alias": "richard",
        "id": "11",
        "created_at": "2026-05-05T11:32:00Z",
        "updated_at": "2026-05-05T11:38:00Z"
    }
}

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/v4/domains/piedpiper.com/aliases/batch \
  -u "api:$API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
      "aliases": [
          {"id": "12345", "forward": "[email protected]"},
          {"id": "12346", "forward": "[email protected]"},
          {"id": "999999", "forward": "[email protected]"}
      ]
  }'
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": "[email protected]",
            "id": "12345",
            "created_at": "2026-05-05T11:32:00Z",
            "updated_at": "2026-05-05T12:00:00Z"
        },
        {
            "alias": "jared",
            "forward": "[email protected]",
            "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/:id

Delete alias by id (the string returned at creation or listing).

curl -X DELETE https://api.improvmx.com/v4/domains/piedpiper.com/aliases/11 \
  -u "api:$API_KEY"

Returns 204 No Content on success.

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/v4/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?all=true

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/v4/domains/piedpiper.com/aliases?all=true \
  -u "api:$API_KEY"

Response:

{
    "deleted": 42
}

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": "[email protected]"
}
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": "[email protected]",
    "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": "[email protected]"
}
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/v4/domains/piedpiper.com/rules?query=richard" \
  -u "api:$API_KEY"
PARAMETER TYPE DESCRIPTION
query query Filter rules by substring.
order query Sort order: rank_asc (default), rank_desc, created_asc, or created_desc.
limit query Number of rules. Default 20, max 200.
page query Page number (1-based, default 1).

Response:

{
    "limit": 20,
    "page": 1,
    "rules": [
        {
            "active": true,
            "config": {
                "alias": "richard",
                "forward": "[email protected]"
            },
            "created_at": "2025-07-09T01:53:48Z",
            "updated_at": "2025-07-09T01:53:48Z",
            "rank": 1.0,
            "id": "447a95d1-bac1-4d6e-8315-22b10f501efb",
            "type": "alias"
        },
        {
            "active": true,
            "config": {
                "forward": "[email protected]",
                "regex": ".*jared.*",
                "scopes": [
                    "sender"
                ]
            },
            "created_at": "2025-07-14T04:30:18Z",
            "updated_at": "2025-07-14T04:30:18Z",
            "rank": 2.0,
            "id": "fcadc999-0d3f-45f8-9c62-056e1b98e47a",
            "type": "regex"
        }
    ],
    "total": 2
}

Add rule

POST /domains/:domain/rules

curl -X POST https://api.improvmx.com/v4/domains/piedpiper.com/rules \
  -u "api:$API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
      "type": "regex",
      "config": {
          "regex": ".*important.*",
          "scopes": [
              "subject",
              "body"
          ],
          "forward": "[email protected]"
      }
  }'
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": "[email protected]"
        },
        "created_at": "2025-07-09T01:53:48Z",
        "updated_at": "2025-07-09T01:53:48Z",
        "rank": 1.0,
        "id": "447a95d1-bac1-4d6e-8315-22b10f501efb",
        "type": "alias"
    }
}

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/v4/domains/piedpiper.com/rules/batch \
  -u "api:$API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
      "rules": [
          {
              "type": "alias",
              "config": {
                  "alias": "richard",
                  "forward": "[email protected]"
              }
          },
          {
              "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": "[email protected]"
            },
            "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/v4/domains/piedpiper.com/rules/447a95d1-bac1-4d6e-8315-22b10f501efb \
  -u "api:$API_KEY"

Response:

{
    "rule": {
        "active": true,
        "config": {
            "alias": "richard",
            "forward": "[email protected]"
        },
        "created_at": "2025-07-09T01:53:48Z",
        "updated_at": "2025-07-09T01:53:48Z",
        "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/v4/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": "[email protected]"
      }
  }'
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": "[email protected]"
        },
        "created_at": "2025-07-09T01:53:48Z",
        "updated_at": "2026-05-05T11:32:00Z",
        "id": "447a95d1-bac1-4d6e-8315-22b10f501efb",
        "rank": 1.0,
        "type": "alias"
    }
}

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/v4/domains/piedpiper.com/rules/batch \
  -u "api:$API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
      "rules": [
          {
              "id": "62f9cf67-9005-41a6-8706-843ca8df8932",
              "config": {
                  "alias": "[email protected]"
              }
          },
          {
              "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": "[email protected]",
                "forward": "[email protected]"
            },
            "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/v4/domains/piedpiper.com/rules/e8417681-3a4c-4f9b-ab93-1ca2529036c9 \
  -u "api:$API_KEY"

Returns 204 No Content on success.

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/v4/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=true

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/v4/domains/piedpiper.com/rules?all=true \
  -u "api:$API_KEY"

Response:

{
    "deleted": 42
}

Email Logs

View your domain logs to see emails sent or received.

List email logs

GET /domains/:domain/logs

Returns email statuses. All filter parameters are optional and combine with AND.

curl -X GET https://api.improvmx.com/v4/domains/piedpiper.com/logs \
  -u "api:$API_KEY" -G \
  --data-urlencode "[email protected]" \
  --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).
order query created_desc (default, most recent first) or created_asc.
after query ISO 8601 timestamp (e.g. 2024-07-02T12:00:00Z ). Returns entries received after this time.
before query ISO 8601 timestamp. Returns entries received before this time.
limit query Number of entries per page. Default 100, max 200.
cursor query Load logs starting from this log id (e.g. 20201002014128.7ea8ee5b46). Pass next_cursor from the previous response to paginate.

Response:

{
    "logs": [
        {
            "created_at": "2020-01-25T12:19:09Z",
            "events": [
                {
                    "code": 250,
                    "created_at": "2020-01-25T12:19:11Z",
                    "id": "<[email protected]>-0",
                    "local": "mxb.infra.improvmx.com",
                    "message": "Queued",
                    "server": "mail-io1-f54.google.com",
                    "status": "QUEUED"
                },
                {
                    "code": 250,
                    "created_at": "2020-01-25T12:19:12Z",
                    "id": "<[email protected]>-1",
                    "local": "gmail-smtp-in.l.google.com",
                    "message": "Sent.",
                    "server": "mail16.mxc.infra.improvmx.com",
                    "status": "DELIVERED"
                }
            ],
            "forward": {
                "email": "[email protected]",
                "name": "Richard Hendricks"
            },
            "hostname": "mail-io1-f54.google.com",
            "id": "20201002014128.5ea8ee59fa894aa7a9141e9665985b46",
            "message_id": "<[email protected]>",
            "recipient": {
                "email": "[email protected]",
                "name": "Richard Hendricks"
            },
            "sender": {
                "email": "[email protected]",
                "name": "Gavin Belsonx"
            },
            "subject": "You are screwed, Piedpiper team!",
            "transport": "smtp"
        },
        {
            "created_at": "2020-01-25T11:30:41Z",
            "events": [
                {
                    "code": 550,
                    "created_at": "2020-01-25T11:30:42Z",
                    "id": "<[email protected]>-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",
            "message_id": "<[email protected]>",
            "recipient": {
                "email": "[email protected]",
                "name": null
            },
            "sender": {
                "email": "[email protected]",
                "name": "ThinkTeam"
            },
            "subject": "Enlarge your (pied)piper!",
            "transport": "smtp"
        }
    ],
    "limit": 100,
    "cursor": "20201002014128.5ea8ee59fa894aa7a9141e9665985b46",
    "next_cursor": "20201002014128.7ea8ee59fa894aa7a91415a6659c5b46"
}

next_cursor is the cursor of the next page, or null when there are no more results. Pass it back as cursor to fetch the next page.

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/v4/domains/piedpiper.com/logs/count \
  -u "api:$API_KEY" -G \
  --data-urlencode "[email protected]" \
  --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:

{
    "total": 1337
}

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/v4/domains/piedpiper.com/logs/20250330190000.a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 \
  -u "api:$API_KEY"

Response:

{
    "created_at": "2025-03-30T19:00:00Z",
    "events": [
        {
            "code": 250,
            "created_at": "2025-03-30T19:00:00Z",
            "id": "<[email protected]>-0",
            "local": "api.improvmx.com",
            "message": "2.0.0 Email queued for delivery.",
            "server": "mail-io1-f54.google.com",
            "status": "QUEUED"
        },
        {
            "code": 250,
            "created_at": "2025-03-30T19:00:12Z",
            "id": "<[email protected]>-1",
            "local": "gmail-smtp-in.l.google.com",
            "message": "2.0.0 OK",
            "server": "mail16.mxc.infra.improvmx.com",
            "status": "DELIVERED"
        }
    ],
    "forward": null,
    "hostname": "piedpiper.com",
    "id": "20250330190000.a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
    "message_id": "<[email protected]>",
    "recipient": {
        "email": "[email protected]",
        "name": null
    },
    "sender": {
        "email": "[email protected]",
        "name": null
    },
    "subject": "Middle-out compression",
    "transport": "api"
}

Search email logs

GET /domains/:domain/logs/search

Typo-tolerant fuzzy search across subject, sender, recipient, and forward. query is required; the optional filters AND with it. Results are offset-paginated.

curl -X GET https://api.improvmx.com/v4/domains/piedpiper.com/logs/search \
  -u "api:$API_KEY" -G \
  --data-urlencode "query=series a" \
  --data-urlencode "status=DELIVERED,SOFT-BOUNCE"
PARAMETER TYPE DESCRIPTION
query query Required. Typo-tolerant keyword. Matches across subject, sender, recipient, and forward.
sender query Case-insensitive substring filter on sender address.
recipient query Case-insensitive substring filter on recipient address.
forward query Case-insensitive substring filter on forwarding destination.
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).
order query relevance (default, best match first), created_desc (most recent first), or created_asc.
limit query Number of results. Default 20, max 200.
offset query Skip this many results. Pass next_offset from the previous response to paginate.
after query ISO 8601 timestamp (e.g. 2024-07-02T12:00:00Z ). Returns entries received after this time.
before query ISO 8601 timestamp. Returns entries received before this time.

Response:

{
    "logs": [
        {
            "created_at": "2025-05-12T09:45:18Z",
            "events": [
                {
                    "code": 250,
                    "created_at": "2025-05-12T09:45:20Z",
                    "id": "<[email protected]>-0",
                    "local": "mx1.improvmx.com",
                    "message": "Queued",
                    "server": "mail-yw1-f44.google.com",
                    "status": "QUEUED"
                },
                {
                    "code": 250,
                    "created_at": "2025-05-12T09:45:23Z",
                    "id": "<[email protected]>-1",
                    "local": "gmail-smtp-in.l.google.com",
                    "message": "Sent.",
                    "server": "mail7.mxa.infra.improvmx.com",
                    "status": "DELIVERED"
                }
            ],
            "forward": {
                "email": "[email protected]",
                "name": "Richard Hendricks"
            },
            "hostname": "mail-yw1-f44.google.com",
            "id": "20250512094518.0412c5c8a4f74a82b4d02ea83404a6f1",
            "message_id": "<[email protected]>",
            "recipient": {
                "email": "[email protected]",
                "name": null
            },
            "sender": {
                "email": "[email protected]",
                "name": "Monica Hall"
            },
            "subject": "Series A term sheet draft",
            "transport": "smtp"
        },
        {
            "created_at": "2025-05-12T06:12:04Z",
            "events": [
                {
                    "code": 250,
                    "created_at": "2025-05-12T06:12:05Z",
                    "id": "<[email protected]>-0",
                    "local": "mx2.improvmx.com",
                    "message": "Queued",
                    "server": "mail-pj1-f32.google.com",
                    "status": "QUEUED"
                },
                {
                    "code": 250,
                    "created_at": "2025-05-12T06:12:07Z",
                    "id": "<[email protected]>-1",
                    "local": "gmail-smtp-in.l.google.com",
                    "message": "Sent.",
                    "server": "mail12.mxa.infra.improvmx.com",
                    "status": "DELIVERED"
                }
            ],
            "forward": {
                "email": "[email protected]",
                "name": "Jared Dunn"
            },
            "hostname": "mail-pj1-f32.google.com",
            "id": "20250512061204.9f65bc20deab4f71bcedad1dfc513e9a",
            "message_id": "<[email protected]>",
            "recipient": {
                "email": "[email protected]",
                "name": null
            },
            "sender": {
                "email": "[email protected]",
                "name": "Laurie Bream"
            },
            "subject": "Re: Series A funding timeline",
            "transport": "smtp"
        }
    ],
    "limit": 20,
    "offset": 0,
    "total": 2,
    "next_offset": null
}

next_offset is the offset of the next page, or null when there are no more results. Pass it back as offset to fetch the next page.

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/v4/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_at": "2020-02-13T14:42:50Z",
            "usage": 0,
            "username": "richard"
        },
        {
            "created_at": "2020-02-13T15:17:08Z",
            "usage": 0,
            "username": "monica"
        }
    ],
    "limit": 20,
    "page": 1,
    "total": 2
}

Add credential

POST /domains/:domain/credentials

curl -X POST https://api.improvmx.com/v4/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 [email protected]).
password body Required. SMTP credential password.

Response:

{
    "credential": {
        "created_at": "2020-04-30T08:55:52Z",
        "usage": 0,
        "username": "bighead"
    },
    "requires_new_mx_check": false
}

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/v4/domains/piedpiper.com/credentials/bighead \
  -u "api:$API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
      "password": "abcd1234"
  }'

Response:

{
    "credential": {
        "created_at": "2020-04-30T08:55:52Z",
        "usage": 0,
        "username": "bighead"
    }
}

Delete credential

DELETE /domains/:domain/credentials/:username

curl -X DELETE https://api.improvmx.com/v4/domains/piedpiper.com/credentials/russ \
  -u "api:$API_KEY"

Returns 204 No Content on success.