Webhooks
TagadaPay pushes processing events to your HTTPS endpoint as they happen: a charge fails, a payout lands, a dispute opens. One partner-level endpoint receives events for all your TPAs — theaccount field on every event tells you which merchant it belongs to (Stripe Connect semantics). Direct merchants subscribe per-TPA the same way.
Requires @tagadapay/node-sdk ≥ 3.8.0.
1. Create an endpoint
enabledEvents accepts exact types (payout.paid), prefixes (payout.*), or '*' for everything.
Manage endpoints with list(), retrieve(id), update(id, { url, enabledEvents, status }) and del(id). Set status: 'disabled' to pause deliveries instantly.
2. Verify and handle events
Every delivery is signed with your endpoint’swhsec_… secret (header tagadapay-signature, Stripe-style t=<unix>,v1=<hmac>). Use the SDK helper — it verifies and parses in one call, and throws on a bad signature:
event.id.
Event types
This table is the whole catalog — there is nothing else to subscribe to. An
enabledEvents entry that names anything outside it is rejected with
400 invalid_body listing the offenders, so a typo fails at subscription time
rather than by silently never delivering.
Subscribing to a family is easier than listing names: account.* and
document.* cover the onboarding lifecycle and pick up events added later.
Nested prefixes such as account.kyc.* work too.
Onboarding events reach partner-owned endpoints regardless of the merchant’s
own notification preferences. Those preferences govern the merchant’s in-app and
email notifications only; they no longer gate webhook delivery.
charge.* payloads include a card block with PSP-agnostic BIN intelligence (funding credit/debit, segment consumer/business/commercial/government, isCommercial, prepaid, issuer country/name/currency, card product) resolved from Tagada’s own enrichment data — ready for commercial-card surcharging and risk rules without any acquirer-specific configuration. See Card intelligence.Payload by family
data.object depends on the event family. Every object carries an object discriminator, so branch on data.object.object rather than on the event name when one type can arrive in more than one shape.
Onboarding, KYC, contracts, account status (account.application.approved / .declined, account.kyc.*, account.contract.*, account.activated, account.suspended, account.payments_enabled, account.payouts_enabled):
title and body are the merchant-facing wording, not structured fields. Treat these events as a signal and read the merchant’s current state from GET /v1/partner/tpas/{id} for the details (contract, KYC outcome, enabled capabilities).
Application submitted (account.application.submitted):
document.requested, document.uploaded, document.verified, document.rejected):
id is dreq_… for a request raised on the payfac account and edreq_… for one raised on the application; documentType is the label shown to the merchant, not an enum. status is the request’s own state (open for a new request, then uploaded, verified, rejected); reason carries the reviewer’s note on a rejection. document.requested can also arrive with the notification shape above when the request was raised through the merchant notification flow, hence the advice to branch on data.object.object.
Requirements (account.requirements.updated, one event per change to the checklist):
account.gwp.completed):
charge, refund, dispute, chargeback_alert, payout) with the same fields as the reporting API; see the payout example above and Reporting.
Retries
A delivery that doesn’t get a 2xx within 10 seconds is retried with backoff 1 min → 10 min → 1 h → 6 h → 24 h (6 attempts total), then marked failed. Failures never block other events.3. Delivery log & replay
Audit exactly what was sent, when, and what your server answered:event.id, so idempotent consumers stay safe.
Testing your integration
Point a temporary endpoint at a request inspector (e.g.https://webhook.site/…), subscribe to '*', then trigger a test event — the fastest is an on-demand payout or a small refund on a test TPA. Check the delivery log to confirm the 200.