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-Signatureheader? - How do I handle
completed,paid,pending,new,failedandcanceledtransactions? - Why is my Onramper webhook signature verification failing?
- How do I tell a
buyfrom anofframptransaction 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
- references/overview.md - How the webhooks work, statuses, payload
- references/setup.md - Getting webhooks enabled and the secret issued
- references/verification.md - Signature details, Node and Python verifiers, debugging
- examples/ - Runnable Express, Next.js and FastAPI handlers with tests