Skip to content

Delivery Server API Documentation ​

Delivery server management endpoints for creating, updating, deleting, retrieving and verifying SMTP delivery servers. These endpoints are admin-only and manage the SMTP servers used to send email campaigns.

Create a Delivery Server ​

POST /api/v1/deliveryserver.create

API Usage Notes

  • Authentication required: Admin API Key
  • v1 REST alias: POST /api/v1/deliveryserver.create. Legacy access via /api.php is also supported

Request Body Parameters:

ParameterTypeRequiredDescription
CommandStringYesAPI command: deliveryserver.create
SessionIDStringNoSession ID obtained from login
APIKeyStringNoAPI key for authentication
DeliveryServerNameStringYesName of the delivery server
SendMethodSMTPHostStringYesSMTP server hostname or IP address
SendMethodSMTPPortIntegerYesSMTP server port (e.g., 25, 587, 465)
SendMethodSMTPSecureStringYesSecurity protocol: "false", "ssl", or "tls"
SendMethodSMTPTimeoutIntegerYesConnection timeout in seconds (must be numeric)
SendMethodSMTPAuthBooleanYesWhether SMTP authentication is required: true or false
SendMethodSMTPUsernameStringConditionalSMTP username (required if SendMethodSMTPAuth is true)
SendMethodSMTPPasswordStringNoSMTP password
DomainSettings_LinkTrackingStringYesDomain for link tracking (e.g., "track.example.com")
DomainSettings_OpenTrackingStringYesDomain for open tracking (e.g., "open.example.com")
DomainSettings_MFromStringYesMail From domain (e.g., "bounce.example.com")
DomainSettings_EnforcedFromStringNoEnforced From email address (must be valid email format)
SenderInfoAsMFromStringNoUse sender info as MFrom: "Enabled" or "Disabled" (default: "Disabled")
SenderInfoAsFromStringNoUse sender info as From: "Enabled" or "Disabled" (default: "Disabled")
SenderRotationStringNoEnabled to store Domains.sender_rotation = true (default false). Before v5.9.6 this parameter was accepted by deliveryserver.update only and silently dropped on create
SenderRotation_SettingsStringNoStored as Domains.sender_rotation_settings. Before v5.9.6 this parameter was accepted by deliveryserver.update only and silently dropped on create
bash
curl -X POST https://example.com/api.php \
  -H "Content-Type: application/json" \
  -d '{
    "Command": "deliveryserver.create",
    "SessionID": "admin-session-id",
    "DeliveryServerName": "Primary SMTP Server",
    "SendMethodSMTPHost": "smtp.example.com",
    "SendMethodSMTPPort": 587,
    "SendMethodSMTPSecure": "tls",
    "SendMethodSMTPTimeout": 30,
    "SendMethodSMTPAuth": true,
    "SendMethodSMTPUsername": "smtp_user",
    "SendMethodSMTPPassword": "smtp_password",
    "DomainSettings_LinkTracking": "track.example.com",
    "DomainSettings_OpenTracking": "open.example.com",
    "DomainSettings_MFrom": "bounce.example.com",
    "DomainSettings_EnforcedFrom": "noreply@example.com"
  }'
json
{
  "Success": true,
  "ErrorCode": 0,
  "ErrorText": "",
  "DeliveryServerID": 123
}
json
{
  "Success": false,
  "ErrorCode": [1, 2, 3],
  "ErrorText": ["Missing deliveryservername", "Missing sendmethodsmtphost", "Missing sendmethodsmtpport"]
}
txt
0: Success
1: Missing deliveryservername
2: Missing sendmethodsmtphost
3: Missing sendmethodsmtpport
4: Missing sendmethodsmtpsecure
5: Missing sendmethodsmtptimeout
6: Missing sendmethodsmtpauth
7: Missing sendmethodsmtpusername
8: Missing sendmethodsmtppassword
9: Missing domainsettings_linktracking
10: Missing domainsettings_opentracking
11: Missing domainsettings_mfrom
12: Missing domainsettings_enforcedfrom
13: Invalid sendmethodsmtpsecure value (must be: false, ssl, tls)
14: Invalid sendmethodsmtpauth value (must be: true, false)
15: Invalid sendmethodsmtptimeout value (must be numeric)
16: Invalid email address value for domainsettings_enforcedfrom

Clone a Delivery Server New in v6.0.1 ​

POST /api/v1/deliveryserver.clone

API Usage Notes

  • Authentication required: Admin API Key
  • Required admin privilege: DeliveryServers
  • v1 REST alias: POST /api/v1/deliveryserver.clone. Legacy access via /api.php is also supported
  • Creates a new delivery server from an existing one. The new server gets the source's ConnectionParams, including the stored SMTP password, and its Domains settings, copied on the server. The password is never returned.
  • The verification results are reset to false and the last-checked time is cleared, as for a newly created server. Run deliveryserver.verify on the clone.
  • Not copied: email headers scoped to the source server, user group channel assignments and delivery routes.
  • Fires the DeliveryServers.Create.Post plugin hook with the new server's ID, the same hook deliveryserver.create fires.

Request Body Parameters:

ParameterTypeRequiredDescription
CommandStringYesAPI command: deliveryserver.clone
SessionIDStringNoSession ID obtained from login
APIKeyStringNoAPI key for authentication
DeliveryServerIDIntegerYesID of the delivery server to copy. Must be an integer or a string of digits greater than 0. Any other value, such as true or 1.0, returns error 2
DeliveryServerNameStringNoName of the new server. Leading and trailing whitespace is trimmed and the name is cut to 250 characters. When it is omitted or empty after trimming, the name is the source server's name followed by (Copy)
bash
curl -X POST https://example.com/api.php \
  -H "Content-Type: application/json" \
  -d '{
    "Command": "deliveryserver.clone",
    "SessionID": "admin-session-id",
    "DeliveryServerID": 123,
    "DeliveryServerName": "Secondary SMTP Server"
  }'
json
{
  "Success": true,
  "ErrorCode": 0,
  "ErrorText": "",
  "DeliveryServerID": 124
}
json
{
  "Success": false,
  "ErrorCode": [2],
  "ErrorText": ["Delivery server not found"]
}
txt
0: Success
1: Missing deliveryserverid
2: Delivery server not found
3: Delivery server could not be created

Save Delivery Server Test Results ​

GET /api/v1/deliveryserver.testresults

API Usage Notes

  • Authentication required: Admin API Key
  • v1 REST alias: GET /api/v1/deliveryserver.testresults. Legacy access via /api.php is also supported
  • Since v5.9.6 this command runs the real verification (a test message through the server's own SMTP credentials, then the SPF, DKIM and DMARC TXT checks and the CNAME checks on the MFROM, link-tracking and open-tracking hosts) and stores what the check found. The test_results and last_checked_at values you send are accepted for backward compatibility and ignored. Before v5.9.6 the command stored those values as sent, with no check, so any admin caller could mark a server verified (issue #2769).
  • The test message is sent to the authenticated admin's email address, with the admin's name as sender name. To pick another recipient, and to receive the results in the response instead of reading them back with deliveryserver.get, call deliveryserver.verify.
  • Every call sends real mail and performs six DNS lookups, so since v5.9.6 this command is rate limited the same way as deliveryserver.verify: 10 calls per 300 seconds per caller.
  • In demo mode the command answers Success: true without running or storing anything.
  • The recipient is always the authenticated admin's stored email address. If that address is empty or invalid the test send fails and email_delivery is stored as false; the response does not say why, so check the admin record if deliveryserver.verify reports a send failure that names the recipient.
  • Parameter names are matched after lowercasing, so send them exactly as test_results and last_checked_at (with the underscores). Earlier versions of this page showed TestResults and LastCheckedAt; those lowercase to testresults / lastcheckedat, never matched the handler, and always answered ErrorCode [2, 4].

Request Body Parameters:

ParameterTypeRequiredDescription
CommandStringYesAPI command: deliveryserver.testresults
SessionIDStringNoSession ID obtained from login
APIKeyStringNoAPI key for authentication
DeliveryServerIDIntegerYesID of the delivery server to verify
test_resultsObjectYesAccepted for backward compatibility, ignored. Any non-empty value satisfies the check (for example {"spf": false})
last_checked_atStringYesAccepted for backward compatibility, ignored. The stored VerificationLastCheckedAt is the time the check ran
bash
curl -X POST https://example.com/api.php \
  -H "Content-Type: application/json" \
  -d '{
    "Command": "deliveryserver.testresults",
    "SessionID": "admin-session-id",
    "DeliveryServerID": 123,
    "test_results": {"spf": false},
    "last_checked_at": "2025-12-28 10:30:00"
  }'
json
{
  "Success": true,
  "ErrorCode": 0,
  "ErrorText": ""
}
json
{
  "Success": false,
  "ErrorCode": [3],
  "ErrorText": ["Invalid deliveryserverid"]
}
txt
0: Success
1: Missing deliveryserverid
2: Missing test_results
3: Invalid deliveryserverid
4: Missing last_checked_at

Read the stored outcome back with deliveryserver.get: VerificationResults holds the seven booleans (email_delivery, spf, dkim, dmarc, sender_domain, link_domain, open_domain) and VerificationLastCheckedAt the time of the check.

Update a Delivery Server ​

POST /api/v1/deliveryserver.update

API Usage Notes

  • Authentication required: Admin API Key
  • v1 REST alias: POST /api/v1/deliveryserver.update. Legacy access via /api.php is also supported

Request Body Parameters:

ParameterTypeRequiredDescription
CommandStringYesAPI command: deliveryserver.update
SessionIDStringNoSession ID obtained from login
APIKeyStringNoAPI key for authentication
DeliveryServerIDIntegerYesID of the delivery server to update
DeliveryServerNameStringYesName of the delivery server
SendMethodSMTPHostStringYesSMTP server hostname or IP address
SendMethodSMTPPortIntegerYesSMTP server port (e.g., 25, 587, 465)
SendMethodSMTPSecureStringYesSecurity protocol: "false", "ssl", or "tls"
SendMethodSMTPTimeoutIntegerYesConnection timeout in seconds (must be numeric)
SendMethodSMTPAuthBooleanYesWhether SMTP authentication is required: true or false
SendMethodSMTPUsernameStringConditionalSMTP username (required if SendMethodSMTPAuth is true)
SendMethodSMTPPasswordStringNoSMTP password. Changed in v6.0.1: omit it to keep the stored password. A sent value, including an empty string, replaces it
DomainSettings_LinkTrackingStringYesDomain for link tracking (e.g., "track.example.com")
DomainSettings_OpenTrackingStringYesDomain for open tracking (e.g., "open.example.com")
DomainSettings_MFromStringYesMail From domain (e.g., "bounce.example.com")
DomainSettings_EnforcedFromStringNoEnforced From email address (must be valid email format)
SenderRotation_SettingsStringNoSender rotation configuration (JSON, stored as Domains.sender_rotation_settings)
SenderInfoAsMFromStringNoUse sender info as MFrom: "Enabled" or "Disabled"
SenderInfoAsFromStringNoUse sender info as From: "Enabled" or "Disabled"
SenderRotationStringNoEnable sender rotation: "Enabled" or "Disabled"

The stored SMTP password is kept when omitted (v6.0.1)

deliveryserver.update replaces the server's ConnectionParams and Domains as a whole. deliveryserver.get and deliveryservers.get never return smtp_password, so an integration cannot read it back and resend it. When the request omits SendMethodSMTPPassword, the stored password is kept. Before v6.0.1 an omitted password was stored as empty, which broke the server's sending.

bash
curl -X POST https://example.com/api.php \
  -H "Content-Type: application/json" \
  -d '{
    "Command": "deliveryserver.update",
    "SessionID": "admin-session-id",
    "DeliveryServerID": 123,
    "DeliveryServerName": "Updated SMTP Server",
    "SendMethodSMTPHost": "smtp2.example.com",
    "SendMethodSMTPPort": 587,
    "SendMethodSMTPSecure": "tls",
    "SendMethodSMTPTimeout": 30,
    "SendMethodSMTPAuth": true,
    "SendMethodSMTPUsername": "new_user",
    "SendMethodSMTPPassword": "new_password",
    "DomainSettings_LinkTracking": "track.example.com",
    "DomainSettings_OpenTracking": "open.example.com",
    "DomainSettings_MFrom": "bounce.example.com",
    "SenderRotation": "Enabled"
  }'
json
{
  "Success": true,
  "ErrorCode": 0,
  "ErrorText": "",
  "DeliveryServerID": 123
}
json
{
  "Success": false,
  "ErrorCode": [17],
  "ErrorText": ["Delivery server not found"]
}
txt
0: Success
1: Missing deliveryservername
2: Missing sendmethodsmtphost
3: Missing sendmethodsmtpport
4: Missing sendmethodsmtpsecure
5: Missing sendmethodsmtptimeout
6: Missing sendmethodsmtpauth
7: Missing sendmethodsmtpusername
8: Missing sendmethodsmtppassword
9: Missing domainsettings_linktracking
10: Missing domainsettings_opentracking
11: Missing domainsettings_mfrom
12: Missing domainsettings_enforcedfrom
13: Invalid sendmethodsmtpsecure value (must be: false, ssl, tls)
14: Invalid sendmethodsmtpauth value (must be: true, false)
15: Invalid sendmethodsmtptimeout value (must be numeric)
16: Invalid email address value for domainsettings_enforcedfrom
17: Delivery server not found

Delete Delivery Servers ​

POST /api/v1/deliveryservers.delete

API Usage Notes

  • Authentication required: Admin API Key
  • v1 REST alias: POST /api/v1/deliveryservers.delete. Legacy access via /api.php is also supported
  • Deleting a server resets every user group whose TargetDeliveryServerID_Marketing, TargetDeliveryServerID_Transactional or TargetDeliveryServerID_AutoResponder option pointed at it back to 0 (system default), after invalidating the Email Gateway per-user cache for those groups. UserGroupsReset in the response lists the user group ids that were updated.

Request Body Parameters:

ParameterTypeRequiredDescription
CommandStringYesAPI command: deliveryservers.delete
SessionIDStringNoSession ID obtained from login
APIKeyStringNoAPI key for authentication
DeliveryServerIDStringYesComma-separated list of delivery server IDs to delete (e.g., "123,456,789")
bash
curl -X POST https://example.com/api.php \
  -H "Content-Type: application/json" \
  -d '{
    "Command": "deliveryservers.delete",
    "SessionID": "admin-session-id",
    "DeliveryServerID": "123,456"
  }'
json
{
  "Success": true,
  "ErrorCode": 0,
  "UserGroupsReset": [2, 5]
}
json
{
  "Success": false,
  "ErrorCode": [1]
}
txt
0: Success
1: Missing deliveryserverid

Get Delivery Servers ​

GET /api/v1/deliveryservers.get

API Usage Notes

  • Authentication required: Admin API Key
  • v1 REST alias: GET /api/v1/deliveryservers.get. Legacy access via /api.php is also supported
  • The filter, ordering and paging parameters are all optional. The defaults reproduce the previous response: every server, Name ASC, unpaged.

The SMTP password is not returned (changed in v6.0.1)

ConnectionParams.smtp_password is no longer returned. Each server carries HasSMTPPassword instead, which is true when a password is stored, and DeliveryServerID is an integer. ConnectionParams carries only smtp_host, smtp_port, smtp_secure, smtp_timeout, smtp_auth and smtp_username, and any other stored key is withheld. Each server in the list is the same object deliveryserver.get returns for it. To change the password, use deliveryserver.update, which keeps the stored password when it is omitted.

Request Body Parameters:

ParameterTypeRequiredDescription
CommandStringYesAPI command: deliveryservers.get
SessionIDStringNoSession ID obtained from login
APIKeyStringNoAPI key for authentication
DeliveryServerIDIntegerNoReturn only this server (still keyed by id)
OrderFieldStringNoName (default), DeliveryServerID, VerificationLastCheckedAt
OrderTypeStringNoASC (default) or DESC
RecordsFromIntegerNoOffset (default 0)
RecordsPerRequestIntegerNoPage size (default 0 = all, max 1000)
bash
curl -X POST https://example.com/api.php \
  -H "Content-Type: application/json" \
  -d '{
    "Command": "deliveryservers.get",
    "SessionID": "admin-session-id"
  }'
json
{
  "Success": true,
  "ErrorCode": 0,
  "TotalDeliveryServerCount": 1,
  "RecordsFrom": 0,
  "RecordsPerRequest": 0,
  "OrderField": "Name",
  "OrderType": "ASC",
  "DeliveryServers": {
    "123": {
      "DeliveryServerID": 123,
      "Name": "Primary SMTP Server",
      "ConnectionParams": {
        "smtp_host": "smtp.example.com",
        "smtp_port": 587,
        "smtp_secure": "tls",
        "smtp_timeout": 30,
        "smtp_auth": true,
        "smtp_username": "smtp_user"
      },
      "HasSMTPPassword": true,
      "Domains": {
        "link_tracking": "track.example.com",
        "open_tracking": "open.example.com",
        "mfrom_domain": "bounce.example.com",
        "enforced_from": "noreply@example.com",
        "senderinfo_as_mfrom": false,
        "senderinfo_as_from": false
      },
      "VerificationResults": {
        "email_delivery": true,
        "spf": true,
        "dkim": true,
        "dmarc": true,
        "sender_domain": true,
        "link_domain": true,
        "open_domain": true
      },
      "VerificationLastCheckedAt": "2025-12-28 10:30:00",
      "UserGroupAssignments": [
        {
          "UserGroupID": "1",
          "GroupName": "Default User Group",
          "Channels": ["Marketing", "Transactional"]
        },
        {
          "UserGroupID": "5",
          "GroupName": "Enterprise Users",
          "Channels": ["AutoResponder"]
        }
      ],
      "IsAllocated": true
    }
  }
}
json
{
  "Success": false,
  "ErrorCode": 2
}
txt
0: Success
2: No delivery servers found

Response Field Reference:

FieldTypeDescription
TotalDeliveryServerCountIntegerReal total number of servers matching the filter, independent of paging
RecordsFromIntegerOffset in effect
RecordsPerRequestIntegerPage size in effect (0 = all)
OrderFieldStringOrdering field in effect
OrderTypeStringOrdering direction in effect
DeliveryServersObjectMap of delivery servers keyed by DeliveryServerID
DeliveryServerIDIntegerUnique identifier for the delivery server (a string before v6.0.1)
NameStringDisplay name of the delivery server
ConnectionParamsObjectSMTP connection configuration: smtp_host, smtp_port, smtp_secure, smtp_timeout, smtp_auth and smtp_username. smtp_password is not returned (v6.0.1)
HasSMTPPasswordBooleantrue when the server stores an SMTP password (v6.0.1)
DomainsObjectDomain settings for tracking and sender identity
VerificationResultsObjectDNS and delivery verification test results
VerificationLastCheckedAtStringTimestamp of last verification check
UserGroupAssignmentsArrayList of user groups assigned to this delivery server. Each entry contains UserGroupID, GroupName, and Channels (array of channel names: Marketing, Transactional, AutoResponder)
IsAllocatedBooleanWhether the delivery server is assigned to at least one user group channel

Get a Delivery Server ​

GET /api/v1/deliveryserver.get

API Usage Notes

  • Authentication required: Admin API Key
  • Required admin privilege: DeliveryServers
  • v1 REST alias: GET /api/v1/deliveryserver.get. Legacy access via /api.php is also supported
  • ConnectionParams.smtp_password is never returned; HasSMTPPassword says whether one is stored. Changed in v6.0.1 ConnectionParams carries only smtp_host, smtp_port, smtp_secure, smtp_timeout, smtp_auth and smtp_username, and only those the server has stored. Any other stored key is left out. Credential keys nested inside a returned value (such as smtp_password, ConnectionParams, Password or APIKey) are also removed, and the same removal applies to Domains and VerificationResults. Since v6.0.1, deliveryserver.update keeps the stored password when SendMethodSMTPPassword is omitted, so a client editing a server does not need to hold it.
  • Since v6.0.1, deliveryservers.get returns the same object for each server.
  • UserGroupAssignments / IsAllocated are the same reverse map deliveryservers.get computes from every user group's TargetDeliveryServerID_* options.

Request Body Parameters:

ParameterTypeRequiredDescription
CommandStringYesAPI command: deliveryserver.get
SessionIDStringNoSession ID obtained from login
APIKeyStringNoAPI key for authentication
DeliveryServerIDIntegerYesID of the delivery server
bash
curl -X POST https://example.com/api.php \
  -H "Content-Type: application/json" \
  -d '{
    "Command": "deliveryserver.get",
    "AdminAPIKey": "your-admin-api-key",
    "DeliveryServerID": 123
  }'
json
{
  "Success": true,
  "ErrorCode": 0,
  "ErrorText": "",
  "DeliveryServer": {
    "DeliveryServerID": 123,
    "Name": "Primary SMTP Server",
    "ConnectionParams": {
      "smtp_host": "smtp.example.com",
      "smtp_port": "587",
      "smtp_secure": "tls",
      "smtp_timeout": "30",
      "smtp_auth": true,
      "smtp_username": "smtp_user"
    },
    "HasSMTPPassword": true,
    "Domains": {
      "link_tracking": "track.example.com",
      "open_tracking": "open.example.com",
      "mfrom_domain": "bounce.example.com",
      "enforced_from": "",
      "sender_rotation_settings": "",
      "senderinfo_as_mfrom": false,
      "senderinfo_as_from": false,
      "sender_rotation": false
    },
    "VerificationResults": {
      "email_delivery": true,
      "spf": true,
      "dkim": true,
      "dmarc": false,
      "sender_domain": true,
      "link_domain": true,
      "open_domain": true
    },
    "VerificationLastCheckedAt": "2026-09-04 10:12:33",
    "UserGroupAssignments": [
      {"UserGroupID": "2", "GroupName": "Agencies", "Channels": ["Marketing", "Transactional"]}
    ],
    "IsAllocated": true
  }
}
json
{
  "Success": false,
  "ErrorCode": [2],
  "ErrorText": ["Delivery server not found"]
}
txt
0: Success
1: Missing DeliveryServerID
2: Delivery server not found

Verify a Delivery Server ​

POST /api/v1/deliveryserver.verify

API Usage Notes

  • Authentication required: Admin API Key
  • Required admin privilege: DeliveryServers
  • Rate limited: 10 calls per 300 seconds. Every call sends a real test message through the server's SMTP credentials and performs six DNS lookups.
  • v1 REST alias: POST /api/v1/deliveryserver.verify. Legacy access via /api.php is also supported
  • Not available when DEMO_MODE_ENABLED is on (error 4).
  • Runs the same verification as the admin screen's "Test" button (DeliveryServers::Verify): a test send, then SPF, DKIM (DNS_DKIM_KEY._domainkey.<mfrom>) and DMARC TXT checks on the MFROM domain, and CNAME checks on the MFROM, link-tracking and open-tracking hosts against DNS_SENDER_DOMAIN, DNS_LINK_TRACKER and DNS_OPEN_TRACKER. The seven booleans are persisted to VerificationResults together with VerificationLastCheckedAt, exactly as the screen does.
  • The test message goes to the authenticated admin's email address unless To is given.
  • deliveryserver.testresults runs the same verification since v5.9.6 but answers only the Success envelope; prefer this command for a UI, it returns the results and the per-check messages.

Request Body Parameters:

ParameterTypeRequiredDescription
CommandStringYesAPI command: deliveryserver.verify
SessionIDStringNoSession ID obtained from login
APIKeyStringNoAPI key for authentication
DeliveryServerIDIntegerYesID of the delivery server
ToStringNoRecipient of the test message (defaults to the admin's email address)
bash
curl -X POST https://example.com/api.php \
  -H "Content-Type: application/json" \
  -d '{
    "Command": "deliveryserver.verify",
    "AdminAPIKey": "your-admin-api-key",
    "DeliveryServerID": 123,
    "To": "postmaster@example.com"
  }'
json
{
  "Success": true,
  "ErrorCode": 0,
  "ErrorText": "",
  "DeliveryServerID": 123,
  "AllPassed": false,
  "VerificationResults": {
    "email_delivery": true,
    "spf": true,
    "dkim": true,
    "dmarc": false,
    "sender_domain": true,
    "link_domain": true,
    "open_domain": true
  },
  "Messages": {
    "email_delivery": "",
    "spf": "",
    "dkim": "",
    "dmarc": "DMARC record not found",
    "sender_domain": "",
    "link_domain": "",
    "open_domain": ""
  },
  "VerificationLastCheckedAt": "2026-09-04 10:12:33",
  "TestEmailSentTo": "postmaster@example.com"
}
json
{
  "Success": false,
  "ErrorCode": [2],
  "ErrorText": ["Delivery server not found"]
}
txt
0: Success
1: Missing DeliveryServerID
2: Delivery server not found
3: Invalid To email address
4: Not available in demo mode

Any questions? Contact us.