Webhook reference
Receive incoming MailContact messages in your own app or automation. Available on Pro and Plus.
Want email, Slack or Discord alerts? Follow the notification guide.
The payload
Each new message triggers one HTTP POST to your URL with a Content-Type: application/json body:
POST https://your-app.example/hooks/mailcontact
{
"id": "d8f2e71a20b4",
"event": "message.created",
"project": {
"id": "prj_8f2k1q",
"name": "acme-site"
},
"source": {
"type": "form",
"name": "Website contact form"
},
"url": "https://mailcontact.app/app/projects/prj_8f2k1q?message=msg_4t9s2e",
"reply": {
"url": "https://mailcontact.app/app/projects/prj_8f2k1q?message=msg_4t9s2e",
"method": "open_conversation"
},
"message": {
"id": "msg_4t9s2e",
"from": {
"name": "Ada Lovelace",
"email": "[email protected]"
},
"subject": "Question about pricing",
"body": "Hi, quick question about the Pro plan...",
"receivedAt": "2026-07-14T09:30:00.000Z"
}
}Fields
event:message.createdfor an incoming message, ornotification.testfor the Test button. Test events have a nullmessageandsource.project: the project whose inbox received the message (itsidandname).source: where the message came from.typeis"form"(the form endpoint) or"email"(the project email address);nameis the source's label in your inbox.message.from: the sender'semail(always present) andname(may be empty when the sender didn't provide one).message.subject: optional on form posts, so it may be empty.message.receivedAt: ISO 8601 timestamp, UTC.reply.url: opens this conversation in Mailcontact, where its owner can reply after signing in. It grants no access on its own. Test events have a nullreply.
Delivery
- Respond fast. Return a 2xx status as soon as you've accepted the payload and do any real work asynchronously. Deliveries will time out after 10 seconds.
- At-least-once. A slow response or a transient failure can cause the same message to be delivered more than once. Deduplicate using the payload's
id, also sent in theIdempotency-KeyandX-Mailcontact-Event-Idheaders. - Temporary failures and HTTP 429 are retried up to five attempts, with exponential delays. Most other 4xx responses stop delivery.
- Use a public HTTPS endpoint on port 443. Private networks, credentials in URLs and redirects are refused.
Security
Payloads are not signed yet, which means anyone who discovers your webhook URL can POST a fake payload to it. Follow these precautions:
- Use a long, unguessable path for your webhook URL and don't publish it anywhere.
- Treat every payload as untrusted input: validate it before acting on it.
- Don't trigger destructive or irreversible actions from an unsigned webhook. Notifying, logging and queuing are fine; deleting things is not.
Webhook signing is not currently available. Do not treat receipt of a payload as proof of its sender.
Webhooks vs. notification channels
Use the notification guide for email, Slack and Discord alerts. This reference covers the generic webhook format for your own code. See pricing for the current offers.