Agent skill

HitPay Webhooks Skill

Receive and verify HitPay event webhooks. Use when setting up HitPay webhook handlers, validating the Hitpay-Signature header (HMAC-SHA256 with the per-webhook salt), dispatching on Hitpay-Event-Object and Hitpay-Event-Type, or handling charge.created, order.created, invoice.created and transfer.paid events.

Install this skill

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


HitPay is a payments platform (Singapore and Southeast Asia). Its event webhooks, registered under Developers > Webhooks, are HTTP POSTs sent after events such as a completed payment, a new order or a transfer. Each request carries Hitpay-Signature: the hex HMAC-SHA256 of the raw JSON body, keyed with that webhook endpoint's salt.

Not covered: the legacy payment-request and charge callbacks (form-encoded, with an hmac field in the payload, keyed with the API-key salt from the main Developers page). They use a different scheme: sorted, concatenated parameters rather than the raw body.

When to Use This Skill

  • How do I receive HitPay webhooks?
  • How do I verify the Hitpay-Signature header?
  • Which salt do I use: the API-key salt or the webhook salt?
  • How do I tell charge.created from order.created? (The body has no event name.)
  • Why is my HitPay webhook signature verification failing?

Verification (core)

const crypto = require('crypto');

function verifyHitpaySignature(rawBody, signature, salt = process.env.HITPAY_WEBHOOK_SALT) {
  if (!salt) return false;                                    // never accept when unconfigured
  // Check shape first: Buffer.from(x, 'hex') silently truncates invalid hex.
  if (typeof signature !== 'string' || !/^[0-9a-f]{64}$/i.test(signature)) return false;
  const expected = crypto.createHmac('sha256', salt).update(rawBody).digest('hex');
  // Equal-length (64 char) buffers, so timingSafeEqual cannot throw.
  return crypto.timingSafeEqual(Buffer.from(signature.toLowerCase()), Buffer.from(expected));
}

Python: hmac.compare_digest(expected.encode(), signature.lower().encode()) on bytes, so a non-ASCII header gives 401 rather than a TypeError and a 500. Use the raw body bytes, never re-serialised JSON. Express: express.raw({ type: '*/*' }) so any content type verifies. Details in references/verification.md.

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

Event Types

The body is the object itself and carries no event name. The event arrives in two headers: Hitpay-Event-Object (charge, payout, invoice, order, transfer) and Hitpay-Event-Type (created, updated, ...). Dispatch on {Hitpay-Event-Object}.{Hitpay-Event-Type}.

EventTriggered When
charge.createdA payment is successfully completed
charge.updatedA payment is refunded or partially refunded
payout.createdA payout is successfully completed
order.createdAn order is created
order.updatedAn order status is updated
invoice.createdAn invoice is created
transfer.created, transfer.updatedA transfer is created or updated
transfer.processing, transfer.scheduledA transfer is processed or scheduled
transfer.paid, transfer.failed, transfer.canceledA transfer is paid, fails or is canceled

HitPay's list also names payment_request.* and recurring_billing.* events; see references/overview.md.

Environment Variables

HITPAY_WEBHOOK_SALT=your_webhook_salt_from_dashboard   # Developers > Webhooks > the webhook's detail view

Setup

Register the endpoint under Developers > Webhooks in the HitPay dashboard and copy the salt from that webhook's detail view (not the API-key salt on the main Developers page). Details in references/setup.md.

With Hookdeck: only HitPay App webhooks (Developers > Webhooks), which send a Hitpay-Signature header, are supported. Paste that webhook's salt as the source's webhook secret. Legacy payment-request callbacks aren't supported.

Local Development

For local webhook testing, run the Hookdeck CLI via npx (no account required):

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

Paste the printed URL into HitPay Dashboard > Developers > Webhooks.

Resources


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 6, 2026

View on GitHub →