Authentication
There are two credentials you need to configure before going live: an API key for authenticating outbound requests, and a webhook secret for verifying inbound events. Both are available in your dashboard under Settings.
API Key
Every request to the Mono-Parser API must include your API key in the x-api-key header. Your key is prefixed with mp_live_.
Request Header
x-api-key: mp_live_your_secret_key_here
Webhook Secret
Every event we send to your webhook URL includes an x-signature header — an HMAC-SHA256 signature of the raw request body, signed with your webhook secret. Verify this signature on every inbound event before processing it.
Your webhook secret is available in your dashboard under Settings. It is shown once on generation — store it as an environment variable. If you lose it, rotate from the dashboard to get a new one.
Verifying the signature
Compute an HMAC-SHA256 of the raw request body (the unparsed JSON string) using your webhook secret, hex-encode the result, and compare it against the x-signature header. Use a timing-safe comparison to prevent timing attacks.
import crypto from 'crypto';
import express from 'express';
const app = express();
// Use express.raw() on this route to receive the unparsed body as a Buffer
app.post('/webhooks/mono-parser', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-signature'];
const secret = process.env.MONO_PARSER_WEBHOOK_SECRET;
if (!signature || !secret) {
return res.status(401).json({ error: 'Missing signature' });
}
const expected = crypto
.createHmac('sha256', secret)
.update(req.body) // req.body must be the raw Buffer, not parsed JSON
.digest('hex');
const sigBuffer = Buffer.from(signature);
const expectedBuffer = Buffer.from(expected);
if (
sigBuffer.length !== expectedBuffer.length ||
!crypto.timingSafeEqual(sigBuffer, expectedBuffer)
) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = JSON.parse(req.body.toString());
// process event.event, event.data ...
res.status(200).end();
});