Everything you need to receive an email as a signed HTTP request.
Your address
Every account gets one permanent address shaped like inbox_ab12cd34ef@tempy.uk. It cannot be changed, and it is the only address that reaches your webhook. Forward mail to it from any provider, or hand it out directly.
inbox_7wgaav5mdb@tempy.uk
The payload
One HTTPS POST per email, sent as application/json. The body carries the email id, from, to, subject, the text and HTML bodies, every original header and an array of attachments. A header that appeared once is a string; a header that was repeated is an array of strings, in the order the message carried them.
Each request carries an X-Mailhook-Signature header: sha256= followed by the HMAC-SHA256 of the raw request body, keyed with your signing secret. Compute it over the bytes you received, before any JSON parsing, and compare in constant time. Reject anything that does not match.
While a rotation is in progress the primary signature is still computed with your current secret, and the new one arrives in X-Mailhook-Signature-Next. X-Mailhook-Secret-Version names the version behind the primary header. Deploy the new secret, then activate it — nothing breaks in between.
Any 2xx counts as delivered. A 5xx, a 429 or a network failure is retried up to five times, roughly 30 seconds, 1 minute, 2 minutes and 4 minutes apart with jitter. A 4xx other than 429 is permanent and never retried. Your endpoint has 30 seconds to answer.
5×+30s+1m+2m+4m30s
Attachments
Files are not inlined in the JSON. Each attachment carries its filename, content type, size and a signed URL that stays valid for 24 hours from the moment the email arrived. Fetch what you need inside that window — afterwards the file is gone with the rest of the content.
filename · content_type · size · url · expires_at
Limits
A message may be up to 20 MB including attachments; anything larger is rejected at the door so the sender gets a bounce they can act on. Test requests and manual retries are rate limited per account, and a test request carries X-Mailhook-Test: true so you can tell it apart.
20 MB · X-Mailhook-Test: true
Idempotency
A retry sends the same body again with the same email id, so treat that id as your deduplication key. Two POSTs carrying one id are the same email, not two.