Concepts

Webhooks

Every change is POSTed to the webhook URL on the key that caused it, signed with that key’s secret.

Events

deposit:confirmedA customer’s crypto deposit was credited to your balance.
collection:completedA naira collection was paid and credited as USDT.
collection:expired / failedIt was not paid in time, or it failed.
swap:completedA swap went through.
payout:processing / completed / failedA crypto payout moved. Failed ones are refunded.
bank_payout:processing / completed / failedA bank payout moved. Failed ones are refunded.

Verify the signature

X-Rimoswap-Signature is an HMAC-SHA256 of the raw request body with the key's webhook signing secret. Compute it over the exact bytes you received; parsing and re-serialising the JSON first will not match.

Delivery

Answer with any 2xx. Anything else is retried after 1m, 5m, 25m, 2h and 10h. Events can arrive twice or out of order: de-duplicate on data.id with data.status, and read the object back if in doubt. Every event is listed, with your server's answer and a Resend button, on Business → Infrastructure API.

Verifying a webhookNode.js
import crypto from 'node:crypto';

app.post('/rimoswap', express.raw({ type: 'application/json' }), (req, res) => {
  const expected = crypto
    .createHmac('sha256', process.env.RIMOSWAP_WEBHOOK_SECRET)
    .update(req.body)                       // the raw bytes
    .digest('hex');
  const given = req.get('X-Rimoswap-Signature') ?? '';
  if (expected.length !== given.length ||
      !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(given))) {
    return res.status(400).send('bad signature');
  }
  const event = JSON.parse(req.body.toString());
  // de-duplicate on event.data.id + event.data.status
  res.sendStatus(200);
});