Email delivery events
MarkdownForwarding delivery, open, bounce and complaint events from your email service to Sayproof.
When your email service reports to Sayproof whether invitations reached the recipient and whether they were opened:
- The invitation funnel on the Statistics › Invitations tab is calculated in full: invitations sent, delivered, opened, bounced and turned into a review.
- Addresses that bounce permanently, that complain or that unsubscribe are automatically added to the list of people who do not want emails, and no further invitations are sent to them.
If no delivery events are received, send records remain in the “Sent” state and the open rate is shown as “unknown”; this value is not counted as zero.
Connecting
Section titled “Connecting”- On the Email delivery events tab of the Integration screen (shown only if your own system sends the invitations), press Connect on the Email delivery events card. The Email delivery events password is shown only once.
- Once connected, open the collapsed Addresses to enter in your email service section on the card; it lists the endpoint addresses to enter in your email service. Enter the matching address in the webhook setting of the service you use.
| Service | Authentication |
|---|---|
| Generic (signed notice) | The request is signed with the same three headers as signed order sending |
| Amazon SES (through SNS), SendGrid, Postmark, Mailgun | The address contains an access code specific to your brand |
The service you use is shown on the card once the first event arrives.
To disconnect, press Disconnect on the card; after confirmation, events from your email service are no longer taken. To connect again, create a new password with Connect and enter it in your email service.
Events
Section titled “Events”| Event | Effect |
|---|---|
delivered |
The send’s state becomes “Delivered” |
deferred |
The send’s state becomes “Delayed, will be retried” |
opened |
“Opened” is recorded; the send is also counted as delivered |
bounced |
The send’s state becomes “Bounced”. If the bounce is permanent, the address is added to the list of people who do not want emails |
complained |
The send’s state becomes “Customer complained” and the address is added to the list |
unsubscribed |
The address is added to the list |
The state only moves forward: a deferred event that arrives late does not undo the “Delivered” state. Only a hash of the address is written to the list, not the address itself. Service notices (rejection notices) are not affected by this list.
Only an event that matches an email sent by Sayproof adds an address to the list; an event that does not match is stored, is not counted in matched and does not change the list. The address added is the one the email was sent to; a different recipient address in the event is ignored.
Generic format
Section titled “Generic format”For your own email system, or for a service that is not listed:
POST https://api.sayproof.example/v1/mail-events/genericContent-Type: application/jsonX-Sayproof-Secret: PASSWORD-IDX-Sayproof-Timestamp: 2026-09-28T10:00:00+03:00X-Sayproof-Signature: …{ "events": [ { "type": "delivered", "reference": "SEND-ID", "message_id": "service-message-id", "recipient": "jane@example.com", "occurred_at": "2026-09-28T10:00:00+03:00", "permanent": false, "event_id": "evt-1", "detail": "hard_bounce" } ]}- A single event or a list of up to 500 events can be sent; the body can be at most 1 MB.
typeis one of:delivered,deferred,bounced,complained,opened,unsubscribed. Other types are added to theignoredcount in the response and are not processed.permanent: trueis only taken into account for abouncedevent.detailis stored as a code; email addresses in it are replaced with the wordaddressbefore it is stored.- If a text field contains a character that cannot be stored (NUL
\u0000or an unpaired surrogate), the request is refused with400 invalid / field_invalid. - If an
event_idthat has already been processed is sent again, it is not processed and is added to theduplicatescount. - The signature rules are the same as for order transfer. Up to 600 requests can be sent in 5 minutes per password.
- The ID in the
X-Sayproof-Secretheader is the Password ID column of the Email delivery events password row in the table in the Advanced: signing passwords section of the Channels › Keys tab.
Response: {"accepted", "matched", "duplicates", "ignored", "opted_out"}.
Matching an event to an email
Section titled “Matching an event to an email”Sayproof determines which email an event belongs to from the reference field first and, if nothing is found, from the service’s message ID (message_id).
- Every email Sayproof sends carries the
X-Sayproof-Messageheader. Send this value back asreferencein your service’s event. For the services supported out of the box, the field read iscustom_args.sayproof_messagefor SendGrid,Metadata.sayproof_messagefor Postmark anduser-variables.sayproof_messagefor Mailgun. - If you send invitations from your own system, add the
event_idvalue from the Sayproof request to the email as theX-Sayproof-Messageheader; this value comes back asreferencein the event.