Agent skill
Mailjet Webhooks Skill
Receive and authenticate Mailjet webhooks. Use when setting up Mailjet event webhook handlers, securing them with Basic auth credentials in the webhook URL, or handling email events like sent, open, click, bounce, blocked, spam, and unsub.
Install this skill
npx skills add hookdeck/webhook-skills --skill mailjet-webhooks
When to Use This Skill
- How do I receive Mailjet webhooks (Event API / Event tracking)?
- How do I verify or secure a Mailjet webhook? (there is no signature)
- Why is my Mailjet webhook endpoint receiving an
Authorization: Basicheader? - How do I handle
sent,open,click,bounce,blocked,spam, andunsubevents? - Why does my Mailjet webhook receive an array of events instead of one object?
- Why is Mailjet retrying my webhook?
How Mailjet Webhooks Are Secured
Mailjet does not sign webhooks and cannot send a custom header. The only built-in protection is HTTP Basic auth: put credentials in the webhook URL you register, and Mailjet sends them as an Authorization: Basic base64(username:password) header.
https://username:password@your-domain.com/webhooks/mailjet
Always use HTTPS, and use a long random password. Your handler must decode the header and compare the username and password in constant time.
Verification (core)
const crypto = require('crypto');
// Hash both sides so unequal lengths don't throw or leak length
const safeEqual = (a, b) => crypto.timingSafeEqual(
crypto.createHash('sha256').update(a).digest(),
crypto.createHash('sha256').update(b).digest());
function verifyMailjet(authHeader, username, password) {
if (!authHeader || !/^Basic /i.test(authHeader)) return false;
const decoded = Buffer.from(authHeader.slice(6).trim(), 'base64').toString('utf8');
const i = decoded.indexOf(':'); // split on FIRST colon only
if (i < 0) return false;
const userOk = safeEqual(decoded.slice(0, i), username);
const passOk = safeEqual(decoded.slice(i + 1), password);
return userOk && passOk; // no short-circuit between the two
}
// Reject with 401 + WWW-Authenticate: Basic when this returns false
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Payload Shape
The body is JSON. By default it is one event object per request. If you enable Group Events (Event tracking settings, or version: 2 on /eventcallbackurl), Mailjet posts a JSON array of events. Handlers should accept both.
Every event has event, time, email, mj_campaign_id, mj_contact_id, customcampaign, MessageID, CustomID, and Payload.
Common Event Types
| Event | Triggered When | Key Fields |
|---|---|---|
sent | Destination SMTP server accepted the message | smtp_reply, mj_message_id |
open | Recipient opened the email | ip, geo, agent |
click | Recipient clicked a tracked link | url, ip, geo, agent |
bounce | Delivery failed | hard_bounce, blocked, error_related_to, error, comment |
blocked | Mailjet or the recipient side blocked the send | error_related_to, error |
spam | Recipient reported the message as spam | source |
unsub | Recipient unsubscribed | mj_list_id, ip, geo, agent |
For the full event reference, see Mailjet event types.
Environment Variables
# Must match the user:pass embedded in the webhook URL registered with Mailjet
MAILJET_WEBHOOK_USERNAME=mailjet
MAILJET_WEBHOOK_PASSWORD=change-me-to-a-long-random-string
Gotchas
- Respond
200quickly. Any other status makes Mailjet retry every 30 seconds for up to 24 hours, and a persistently failing URL can be suspended (reactivate by updating it with a new URL). Process events asynchronously. - No event ID or timestamp-based replay protection. Mailjet retries and
sentvolume make duplicates likely; dedupe onMessageID+event+time(+email). - Passwords may contain
:. Split the decoded credentials on the first colon only. Percent-encode special characters in the URL when registering it. sentis high-volume. Turn on Group Events so you receive batches.bounceevents withhard_bounce: falseare temporary; only suppress addresses on hard bounces.
Local Development
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 mailjet --path /webhooks/mailjet
Reference Materials
- references/overview.md — Event catalog and payload fields
- references/setup.md — Registering the webhook URL in the Mailjet dashboard or API
- references/verification.md — Basic auth verification details and gotchas