Guide to MongoDB Atlas Webhooks: Features and Best Practices
MongoDB Atlas raises alerts when something about your clusters or project needs attention: a disk filling up, a metric crossing a threshold, a primary being elected. Email and chat notifications are fine for people, but if you want alerts to open incidents, page the right team or start an automated fix, you need them as HTTP requests. Atlas sends those through its webhook integration.
This guide covers how the Atlas webhook integration is configured, what each request contains, how to verify the optional signature, and what to plan for, given how little Atlas documents about delivery.
What are MongoDB Atlas webhooks?
The webhook is one of Atlas's third-party integrations. You configure it once per project with a URL, and optionally a secret and custom templates. It does nothing on its own: an alert is sent to the webhook only when that alert's configuration lists Webhook as a notification method.
Each notification is an HTTP POST with a JSON body in the same format as the Atlas Administration API's Alerts resource. Two values describe the alert. The X-MMS-Event header says what happened to the alert, such as opened or closed. The body's eventTypeName says what the alert is about, such as OUTSIDE_METRIC_THRESHOLD.
If you set a webhook secret, Atlas adds an X-MMS-Signature header: a base64-encoded HMAC-SHA1 of the request body. Without a secret, requests are unsigned.
MongoDB Atlas webhook features
| Feature | Details |
|---|---|
| Configuration | Project Settings > Integrations > Webhook Settings, one per project |
| Required role | Organization Owner or Project Owner |
| What is sent | Alerts whose configuration includes Webhook as a notification method |
| Method and body | POST, JSON in the Admin API Alerts resource format |
| Alert state | X-MMS-Event header |
| Alert type | eventTypeName in the body |
| Signature header | X-MMS-Signature, only when a webhook secret is set |
| Scheme | HMAC-SHA1, base64 digest, over the request body |
| Secret | Chosen by you. Used only for signing, never sent |
| Replay window | None. The signature covers only the body |
| Customisation | FreeMarker templates for headers and body |
| Success | Any 2xx. Other status codes are failures |
| Retries and timeout | Not documented |
| Failure visibility | Delivery errors appear in the project's Activity Feed |
| Test delivery | None. You trigger a real alert |
| Source IPs | Atlas publishes its IP addresses for allowlisting |
Alert states and types
X-MMS-Event takes one of six values:
X-MMS-Event | Meaning |
|---|---|
alert.open | Atlas just opened the alert |
alert.close | Atlas resolved the alert |
alert.update | A previously opened alert is still open |
alert.acknowledge | A user acknowledged the alert |
alert.cancel | The alert became invalid and Atlas cancelled it |
alert.inform | An informational, point-in-time alert, such as "Primary Elected" |
The body's eventTypeName comes from the full list of Atlas alert types, which the Administration API documentation lists. The webhook page doesn't repeat them.
Atlas documents these body fields:
id: the alert's unique identifiereventTypeName: the type of event that triggered the alertcreated: when the alert was createdstatus: the alert's current status, for exampleOPENorCLOSEDseverity: set when the alert opens, and the same value the Alerts API returnshumanReadable: a description that includes the project and organisation names
Here is the example from Atlas's documentation for a disk space alert. In the original, the humanReadable string contains a raw line break, which isn't valid JSON, so it's shown on one line here:
{
"id": "5d1b6f8e8c2e4e2d3c4a5b6c",
"groupId": "5d1b6f8e8c2e4e2d3c4a5b6d",
"eventTypeName": "OUTSIDE_METRIC_THRESHOLD",
"status": "OPEN",
"created": "2024-01-15T10:30:00Z",
"updated": "2024-01-15T10:30:00Z",
"lastNotified": "2024-01-15T10:30:00Z",
"humanReadable": "Disk space used on data partition is 95.2%. Project: MyProject Organization: MyOrganization",
"metricName": "DISK_PARTITION_SPACE_USED_DATA",
"currentValue": {
"number": 95.2,
"units": "RAW"
}
}
Setting up MongoDB Atlas webhooks
- In Atlas, select the organisation and project, then open Project Settings.
- Open the Integrations tab and click Configure for Webhook Settings.
- Enter the Webhook URL.
- Enter a Webhook Secret. It's optional, but without it there is no
X-MMS-Signatureheader. Store the same value server-side, for example asMONGODB_.ATLAS_ WEBHOOK_ SECRET - Leave the Webhook Headers Template and Webhook Body Template empty unless you need a different format. Atlas validates FreeMarker syntax on save, and shows saved templates as
******afterwards. - Click Save.
- In the project's alert settings, add Webhook as a notification method on each alert you want delivered.
Because Atlas has no test button, check the integration by creating a temporary alert with a condition you can trigger, such as a low disk space threshold on a test cluster or a connection count you can exceed. Delete it once you have seen a delivery arrive.
Securing MongoDB Atlas webhooks
Compute an HMAC-SHA1 of the raw request body, using the secret as a plain string key, base64-encode it, and compare it with X-MMS-Signature in constant time. There is no timestamp and no prefix. If you set a secret, reject requests that arrive without the header.
const crypto = require('crypto');
const express = require('express');
function verifyAtlasSignature(rawBody, signatureHeader, secret) {
if (!signatureHeader || !secret) return false;
const expected = crypto.createHmac('sha1', secret).update(rawBody).digest('base64');
const received = Buffer.from(signatureHeader.trim(), 'utf8');
const computed = Buffer.from(expected, 'utf8');
return received.length === computed.length && crypto.timingSafeEqual(received, computed);
}
const app = express();
app.post('/webhooks/mongodb-atlas', express.raw({ type: '*/*' }), (req, res) => {
const secret = process.env.MONGODB_ATLAS_WEBHOOK_SECRET;
if (!secret) return res.sendStatus(500); // fail closed
if (!verifyAtlasSignature(req.body, req.get('x-mms-signature'), secret)) {
return res.sendStatus(401);
}
const alert_state = req.get('x-mms-event'); // e.g. alert.open
const alert = JSON.parse(req.body.toString('utf8'));
// alert.id, alert.eventTypeName, alert.status, alert.severity ...
// Store it, then act on it asynchronously.
res.sendStatus(200);
});
The same check in Python:
import base64
import hashlib
import hmac
def verify_atlas_signature(raw_body: bytes, signature_header, secret: str) -> bool:
if not signature_header or not secret:
return False
digest = hmac.new(secret.encode("utf-8"), raw_body, hashlib.sha1).digest()
expected = base64.b64encode(digest)
return hmac.compare_digest(signature_header.strip().encode("utf-8"), expected)
# In FastAPI: raw_body = await request.body()
# verify_atlas_signature(raw_body, request.headers.get("x-mms-signature"),
# os.environ["MONGODB_ATLAS_WEBHOOK_SECRET"])
To check your verifier, use the secret atlas-test-secret and this exact body:
{"id":"5d1b6f8e8c2e4e2d3c4a5b6c","eventTypeName":"OUTSIDE_METRIC_THRESHOLD","status":"OPEN"}
The signature should be:
W+CWkZrKWUfCptJMOqvW36ZHXrM=
Atlas never sends the secret itself as a credential. If you can't use a secret, Atlas suggests other ways to authenticate requests: a token in the webhook URL's query string, an allowlist of Atlas's published IP addresses, or a reverse proxy or API gateway that checks requests first.
In Hookdeck, the MongoDB Atlas source type verifies X-MMS-Signature with your webhook secret. Verification is optional, so leave it off if you didn't set a secret.
Make MongoDB Atlas alerts production-ready. Hookdeck Event Gateway verifies the
X-MMS-Signatureheader, stores every alert as it arrives, and retries delivery to your service on a schedule you control.
MongoDB Atlas webhook limitations and pain points
Delivery behaviour is undocumented
The Problem: You can't tell from the documentation whether an alert that your endpoint failed to accept will be sent again, how long Atlas waits for a response, or whether alerts arrive in order.
Why It Happens: Atlas documents only that a non-2xx response is a failure and that delivery errors appear in the Activity Feed. It doesn't publish a retry schedule, a timeout or ordering guarantees.
Workarounds:
- Respond with
2xxquickly and do the work afterwards, so a slow handler can't cause a failure. - Check the Activity Feed after any outage on your side.
- Reconcile with the Alerts API, which returns the same alert objects, if you can't afford to miss one.
How Hookdeck Can Help: Hookdeck accepts each alert at its edge and stores it before delivering it to your service. If your service is down, Hookdeck retries on your schedule, and you can replay any alert from the dashboard.
Signing is optional and off by default
The Problem: An endpoint without a secret will accept a forged alert from anyone who knows the URL.
Why It Happens: The webhook secret is an optional field. If it's empty, Atlas sends no X-MMS-Signature header at all.
Workarounds:
- Always set a webhook secret, and reject requests without a valid signature.
- If you can't, add a query-string token, an IP allowlist or a gateway, as Atlas suggests.
How Hookdeck Can Help: Once you set a secret, Hookdeck verifies every request at the source and records those that fail.
Custom templates change what you receive
The Problem: After someone edits the integration's templates, your parser or router stops working.
Why It Happens: A FreeMarker body template replaces the default body, so fields such as eventTypeName may disappear, and a headers template changes the headers. Saved templates are shown as ******, so you can't read back what is configured. Atlas also doesn't say whether the signature is calculated over the templated body.
Workarounds:
- Keep the default templates unless you have a reason to change them, and keep your template source in version control.
- If you use a custom body template, confirm that signature verification still passes on a real alert before relying on it.
How Hookdeck Can Help: Hookdeck stores every request with its headers and body, so you can see exactly what a templated integration sends. Transformations can reshape payloads in Hookdeck instead of in Atlas.
No test delivery
The Problem: You can't send a sample alert to check a new endpoint.
Why It Happens: Atlas has no way to trigger a test alert manually.
Workarounds:
- Create a temporary alert with a condition that is easy to meet on a test cluster, then delete it.
- Unit-test your handler with the documented payload and the test vector above.
How Hookdeck Can Help: Once one real alert has arrived, you can replay it from Hookdeck to your service as often as you need while you build.
Best practices
Verify against the raw body
Mount express.raw() on the webhook route and parse only after verification. In FastAPI, read await request.body(). Re-serialised JSON won't match the signature.
Use both the header and the body
Route on X-MMS-Event for what happened to the alert, and on eventTypeName for what it's about. An alert.open for OUTSIDE_METRIC_THRESHOLD might page someone, while the matching alert.close resolves the incident.
Expect repeated notifications
alert.update means an alert that is already open is still open, so the same id can arrive several times. Atlas sends no event ID header, so deduplicate on the alert's id together with X-MMS-Event, and make your handling of repeats harmless. See our guide to webhook idempotency.
Acknowledge fast and process asynchronously
Verify, store, return 2xx, and act on the alert afterwards. See why to process webhooks asynchronously.
Don't forget the alert configurations
The integration only sets where alerts go. Each alert you care about must also list Webhook as a notification method, and new alerts added later need it too.
Conclusion
Atlas alert webhooks are simple to receive: a JSON alert in the Administration API format, the alert state in X-MMS-Event, and, if you set a secret, a base64 HMAC-SHA1 signature in X-MMS-Signature. The gaps are on the delivery side. With no documented retries or timeout and no test button, it's worth putting something durable in front of your handler and checking the Activity Feed when things go wrong.
Hookdeck Event Gateway sits in front of your receiver, verifies every signature, stores every alert, and delivers it to your service with retries you control.
Get started with Hookdeck for free and handle MongoDB Atlas webhooks reliably in minutes.