Agent skill
Ramp Webhooks Skill
Receive and verify Ramp webhooks. Use when setting up a Ramp webhook endpoint, verifying the X-Ramp-Signature header (hex HMAC-SHA256 of the raw body), completing the webhooks.verification challenge, debugging signature failures, or handling events like transactions.authorized, transactions.cleared, bills.paid, and reimbursements.ready_for_review.
Install this skill
npx skills add hookdeck/webhook-skills --skill ramp-webhooks
When to Use This Skill
- How do I receive Ramp webhooks?
- How do I verify the Ramp
X-Ramp-Signatureheader? - How do I complete the Ramp
webhooks.verificationchallenge and activate a subscription? - How do I handle
transactions.authorizedortransactions.clearedevents? - Why is my Ramp webhook signature verification failing?
Verification (core)
Ramp sends X-Ramp-Signature: the hex-encoded HMAC-SHA256 of the raw request body, keyed with the secret returned when you create the subscription (use the string as-is; do not base64-decode it). There is no timestamp or prefix. Verify against the raw body, before parsing JSON.
const crypto = require('crypto');
function verifyRampSignature(rawBody, signature, secret) {
if (!signature || !secret) return false;
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
try {
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
} catch {
return false; // length mismatch
}
}
Ramp has no webhook verification SDK; the manual check above is the supported approach in every framework.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Activating a Subscription (verification challenge)
New subscriptions start as pending_verification and receive no business events. Ramp POSTs a signed {"type": "webhooks.verification", "challenge": ...} to your URL. Return a 2xx, then submit the challenge to POST /developer/v1/webhooks/{id}/verify to activate. See references/setup.md.
Common Event Types
| Event | Description |
|---|---|
webhooks.verification | One-time challenge sent when a subscription is created |
transactions.authorized | Card transaction authorized |
transactions.cleared | Transaction settled (also fires for refunds and reversals) |
transactions.declined | Card transaction declined |
reimbursements.ready_ | Reimbursement needs review |
bills.created | Bill created |
bills.approved | Bill approved |
bills.paid | Bill payment completed |
tests.test_event | Mock event from POST /developer/v1/webhooks/mock-webhook-event |
Payloads contain id, type, created_at, business_id, and object (resource ID only); fetch the resource from the Ramp API for details.
For the full event list, see references/overview.md and Ramp's webhook guide.
Important Headers
| Header | Description |
|---|---|
X-Ramp-Signature | Hex HMAC-SHA256 of the raw body |
X-Ramp-Webhook-ID | Event ID (same as payload id, constant across retries); not on verification requests |
Environment Variables
RAMP_WEBHOOK_SECRET=your_subscription_secret # "secret" from POST /developer/v1/webhooks
Local Development
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 ramp --path /webhooks/ramp
Reference Materials
- references/overview.md - Ramp webhook events, payload structure, retries
- references/setup.md - Create a subscription and complete the challenge
- references/verification.md - Signature details and debugging