Agent skill

Onramper Webhooks Skill

Receive and verify Onramper webhooks. Use when setting up Onramper transaction status webhooks, debugging X-Onramper-Webhook-Signature verification, or handling the completed, paid, pending, new, failed and canceled statuses.

Install this skill

npx skills add hookdeck/webhook-skills --skill onramper-webhooks


Onramper (the fiat-to-crypto on-ramp aggregator) sends a webhook each time a transaction's status changes. Every delivery is the transaction's current state as one JSON object, signed with HMAC-SHA256 in the X-Onramper-Webhook-Signature header.

Onramper turns on webhooks through your Customer Success Manager. Send them the Hookdeck URL and paste the secret key they issue.

When to Use This Skill

  • How do I receive Onramper webhooks?
  • How do I verify the X-Onramper-Webhook-Signature header?
  • How do I handle completed, paid, pending, new, failed and canceled transactions?
  • Why is my Onramper webhook signature verification failing?
  • How do I tell a buy from an offramp transaction in the payload?

Verification (core)

  • Header: X-Onramper-Webhook-Signature, the bare lowercase hex digest (no prefix). Compare the whole value.
  • Algorithm: HMAC-SHA256 with the secret Onramper issues, keyed with the secret's UTF-8 bytes as-is, over the raw request body bytes. Nothing else is signed (no timestamp or id), so there is no replay window to check.
const crypto = require('crypto');

function verifyOnramperSignature(rawBody, signature, secret) {
  if (!secret || typeof signature !== 'string') return false;
  if (!/^[0-9a-fA-F]{64}$/.test(signature)) return false; // validate before decoding
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest(); // rawBody: Buffer
  const received = Buffer.from(signature.toLowerCase(), 'hex'); // 32 bytes, safe to decode now
  return crypto.timingSafeEqual(received, expected);
}

Read the body as raw bytes (Express: express.raw({ type: '*/*' }); Next.js: await request.arrayBuffer(); FastAPI: await request.body()) and parse JSON only after the check. Return 401 for a missing, malformed or mismatched signature. Onramper's own sample compares with ===; use a constant-time compare instead.

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Event Types

Onramper sends no event name and no header carries a type. Dispatch on the body's status field. Its six documented values (Onramper's "Webhook Status" table) are new, pending, paid, completed, failed and canceled.

transactionType (buy or offramp) gives the direction. Handle the statuses you need and log the rest. Other fields include transactionId, onrampTransactionId, onramp, sourceCurrency, targetCurrency, inAmount, outAmount, paymentMethod, walletAddress, transactionHash, partnerContext and statusDate.

Environment Variables

ONRAMPER_WEBHOOK_SECRET=your_onramper_webhook_secret  # issued by Onramper at registration

Local Development

npx hookdeck-cli listen 3000 onramper --path /webhooks/onramper

No account required. Give the printed URL to your Onramper Customer Success Manager.

Resources


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 12, 2026

View on GitHub →