Mono-Parser
Parser
Get Started

Built for Nigerian Fintechs

Contents
Table of Contents

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

http
x-api-key: mp_live_your_secret_key_here
Keep your API key secret. Never expose it in client-side code, mobile apps, or version control. If compromised, rotate it immediately from your dashboard. Your key grants full access to all your applicants and applications.

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.

javascript
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();
});
Always use the raw request body — not the parsed JSON object — when computing the signature. Parsing and re-stringifying the body can change whitespace or key ordering and will cause the comparison to fail even with a valid secret.