Skip to main content


We can send optional Webhooks (HTTPS POST requests) to an endpoint of your choice when certain events happen in the MailPace API.

To set this up, open the Webhooks section of your Domain. Here you can add or remove endpoints and see recently sent webhooks.

Note that endpoint URLs must use TLS/SSL, and start with https://

Webhooks are sent as JSON POST requests, with a Content-Type of application/json, and are signed using an Ed25519 signature available in the X-MailPace-Signature header key.


All webhook event bodies have two properties:

  • event a string with the event name, e.g. email.delivered
  • payload a JSON object containing the event details (see below for details)

Email Events

email.queuedOccurs when an email is added to the queue for sending
email.deliveredOccurs when an email is accepted by the recipient's SMTP server
email.deferredOccurs when an email soft-bounces and is marked for redelivery
email.bouncedOccurs when an email hard bounces, delivery will not be attempted again
email.spamOccurs when our internal filter identifies an email as spam, delivery will not be attempted

Payload Properties

statusStringEmail status, one of either queued, delivered, deferred, bounced or spamNo
idIntegerReference ID of emailNo
domain_idIntegerReference ID of sending DomainNo
created_atDateTimeTimestamp of when the email was first received by our APINo
updated_atDateTimeTimestamp of when the email was last updated, typically a status changeNo
fromStringFrom email addressNo
toStringTo email address, may be a comma separated list if multiple recipients providedYes
htmlbodyStringHTML body in emailYes
textbodyStringText body in emailYes
ccStringCarbon Coop email address, may be a comma separated list if multiple recipients providedYes
bccStringBlind Carbon Copy email address, may be a comma separated list if multiple recipients providedYes
subjectStringEmail subjectYes
replytoStringReply to addressYes
message_idStringMessage ID set by MailPace, in the format <message-id>@<>No
list_unsubscribeStringList-Unsubscribe headerYes

Properties that are marked as nullable are optional and will appear as null in the body if undefined

Example Body

"event": "email.queued",
"payload": {
"status": "queued",
"id": 1,
"domain_id": 1,
"created_at": 2021-11-16T14:50:15.445Z,
"updated_at": 2021-11-16T14:50:15.445Z,
"from": "string",
"to": "string",
"htmlbody": "string",
"textbody": "string",
"cc": "string",
"bcc": "string",
"subject": "string",
"replyto": "string",
"message_id": "string",
"list_unsubscribe": "string"


For added security we sign all webhook requests with an Ed25519 keypair and place the signature of the webhook body into the request headers, under the header name X-MailPace-Signature.

You can validate this signature using the public key available in the Webhooks -> Public Key Verification section of your Domain at Note that each domain has a different keypair.

This is useful to ensure that all received webhooks have come from the MailPace servers and have not been tampered with. Only we have the private key to sign requests, so if the request body verifies successfully you know we have sent it.


Both the key and signature are a byte string that has been Base64 encoded, using strict_encode. You will need to decode both key and signature to the byte string before verifying (as shown in the examples below). We do this to make sending the signature and key over HTTPS easier and less error-prone.



require "ed25519"

# Assuming you have the headers available in a headers array
signature_base64 = headers["X-MailPace-Signature"]
signature = Base64.strict_decode64(signature_base_64)

verify_key_base64 = "Your Public Key from here"
verify_key =

# Assuming the full body of the request is available under a request object
message = request.raw_post

verify_key.verify(signature, message) # True if verification passed!