Skip to main content

Webhooks

What it is​

The single entry point for external providers to notify the platform of events — payment confirmations (Paystack), wallet/transfer events (PiggyVest Business), and delivery/fulfillment updates (GetIT, for physical gift orders — see Gift & Giftstore). Every "the webhook confirms it, not the client" pattern referenced throughout Payments and PartyBank terminates here.

Core concepts​

  • One route per provider, all under /v1/webhooks/*: POST /paystack, POST /piggyvest-business, POST /getit. Each has a matching GET (used for provider dashboard "verify this URL is reachable" checks, not for receiving real events).
  • Signature verification is provider-specific and not uniformly enforced today. Paystack's webhook actively verifies an HMAC-SHA512 signature (x-paystack-signature against the secret key) and rejects the request if it doesn't match. The PiggyVest Business webhook's equivalent signature check exists in the code but is commented out — the endpoint currently processes payloads without verifying they actually came from PiggyVest. If you're touching this module, that's worth treating as a real gap rather than assuming parity with the Paystack path.

How it works​

  • Paystack (paystack-webhook.service.ts): verifies the HMAC signature first; only on success does it proceed to match the payload against a payment tracking record and call into PaymentsService (recordPayout, tracking updates — see Payments & Payouts).
  • PiggyVest Business (webhook.service.ts): a single endpoint handles multiple PVB event types (wallet funding, transfer completion, etc.) via processPiggyvestBusinessWebhook, routed internally by eventType. This is what confirms PartyBank/personal-wallet bank transfers and the piggy.payment.success event referenced in the PartyBank guide.
  • GetIT (getit-webhook.service.ts): delivery validation and fulfillment completion callbacks for physical gift-box orders — a different domain (logistics) from the other two (payments).

Key business rules & edge cases​

  • Don't assume the PVB webhook payload is authenticated as currently implemented — if you're relying on data from it for anything security-sensitive, treat this as an open item rather than a settled guarantee. Re-enabling the commented-out verifySignature check (mirroring the Paystack implementation) is the fix if/when this gets picked up.
  • All three webhooks are public, unauthenticated routes by necessity (external providers can't hold a platform JWT) — the only thing standing between "real event" and "forged event" is signature verification, which is why the PVB gap above matters more than it might on a route with other layers of defense.
  • The tests/test-processing endpoints exist for local development against webhook logic without needing a real provider callback — test-processing requires a local key, tests doesn't appear to, so don't expose either publicly in a way that lets someone inject fake webhook processing.

POST /v1/webhooks/paystack, POST /v1/webhooks/piggyvest-business, POST /v1/webhooks/getit. Not applicable to the generated OpenAPI spec in the usual sense (these are provider-facing, not client-facing).

  • src/modules/webhooks/webhook.routes.ts, webhooks.controller.ts
  • src/modules/webhooks/paystack-webhook.service.ts — active signature verification
  • src/modules/webhooks/webhook.service.ts — PiggyVest Business (verifySignature present but not called)
  • src/modules/webhooks/getit-webhook.service.ts