Skip to Content
đź‘‹ Welcome to 100Pay Developers
DocsWebhooksTransaction Events

Transaction Events

Fired whenever a wallet ledger transaction is recorded or changes status. These are the most common events you’ll receive — internal transfers, card charges, staking, rewards, and more all produce them.

EventTrigger
transaction.depositA credit transaction was recorded on one of your wallets
transaction.withdrawalA debit transaction was recorded on one of your wallets
reward.payoutA reward credit was paid out
transaction.status.changedAn existing transaction moved between statuses

transaction.deposit / transaction.withdrawal / reward.payout

interface TransactionWebhook { eventType: "transaction.deposit" | "transaction.withdrawal" | "reward.payout"; eventId: string; // UUID, unique per event timestamp: string; // ISO 8601 transactionId: string; transactionHash: string; amount: string; currency: string; // wallet symbol, e.g. "NGN", "USDT" type: "credit" | "debit"; status: "successful" | "pending" | "failed" | "reversed"; description: string; from: string; // source wallet / address / system name to: string; // destination wallet / address category: string; // see category table below metadata: Record<string, unknown>; // category-specific context }

Example — internal transfer withdrawal

{ "eventType": "transaction.withdrawal", "eventId": "8f2c1a34-6a1b-4a7e-9c2f-3d4e5f6a7b8c", "timestamp": "2026-03-12T13:42:46.165Z", "transactionId": "665f1c2e8b6a4a0012a4d920", "transactionHash": "DR_1700000000000_XXXXXXXX", "amount": "100", "currency": "NGN", "type": "debit", "status": "successful", "description": "Internal transfer to 160005", "from": "625988", "to": "160005", "category": "internal_transfer", "metadata": { "transferType": "internal", "recipientWalletId": "665f0aa18b6a4a0012a4d100", "recipientUserId": "628b228b19ac52002c588525", "note": "Invoice #42" } }

Example — reward payout

{ "eventType": "reward.payout", "eventId": "2b7d9e10-1c2d-4e5f-8a9b-0c1d2e3f4a5b", "timestamp": "2026-03-13T00:05:00.000Z", "transactionId": "665f1c2e8b6a4a0012a4d930", "transactionHash": "RW_1700000000000_XXXXXXXX", "amount": "1.25", "currency": "NGN", "type": "credit", "status": "successful", "description": "Daily rewards payout for 1 day(s) - NGN wallet", "from": "REWARDS_SYSTEM", "to": "665f0aa18b6a4a0012a4d100", "category": "reward", "metadata": { "rewardType": "daily_interest", "numberOfDays": 1 } }

Common categories

The category field tells you which product generated the transaction. Common values include:

CategoryProduct
internal_transferWallet-to-wallet transfers
fiatDeposit / fiatWithdrawalBank deposits and withdrawals (these map to bank_transfer.credit / bank_transfer.debit instead)
card-order, card_payment, card_settlementCard issuing and card spend
staking, unstaking, staking_rewardStaking
borrowing, loan_repayment, liquidationBorrowing
rewardReward payouts (maps to reward.payout)
checkout_withdrawalCheckout settlement withdrawals
correctionLedger corrections / reversal credits
uncategorizedLegacy transactions with no category

Treat category as an open set — new products introduce new categories. Route on eventType and type first, and use category for finer-grained handling.

transaction.status.changed

Fired whenever a transaction’s status transitions (e.g. pending → successful, successful → reversed). One event fires per transition, with a distinct dedupe reference of the form <transactionId>:<previous>-><next>.

interface TransactionStatusChangedWebhook { eventType: "transaction.status.changed"; eventRef: string; // "<transactionId>:<previousStatus>-><status>" timestamp: string; source: string; // internal service that triggered the change transactionId: string; transactionHash: string; linkedTransactionId: string | null; // links debit/credit pairs correctionForId: string | null; // set when this corrects another transaction status: string; // new status previousStatus: string; type: "credit" | "debit"; category: string; amount: string; currency: string; accountId: string; // wallet ID subAccountId?: string; appId: string; userId: string; description: string; failureReason?: string; // set when status becomes "failed" metadata: Record<string, unknown>; createdAt: string; // when the transaction was created updatedAt: string; // when the status changed }

Example

{ "eventType": "transaction.status.changed", "eventRef": "665f1c2e8b6a4a0012a4d920:pending->successful", "timestamp": "2026-03-12T13:45:02.101Z", "source": "banktransfer.service", "transactionId": "665f1c2e8b6a4a0012a4d920", "transactionHash": "DR_1700000000000_XXXXXXXX", "linkedTransactionId": null, "correctionForId": null, "status": "successful", "previousStatus": "pending", "type": "debit", "category": "fiatWithdrawal", "amount": "5000", "currency": "NGN", "accountId": "665f0aa18b6a4a0012a4d100", "appId": "62ee5dbfb029b7002d5b7453", "userId": "628b228b19ac52002c588525", "description": "Bank transfer to JOHN DOE", "metadata": {}, "createdAt": "2026-03-12T13:42:46.165Z", "updatedAt": "2026-03-12T13:45:02.099Z" }

Handling

async function handleStatusChange(event: TransactionStatusChangedWebhook) { switch (event.status) { case "successful": await markSettled(event.transactionId); break; case "failed": await markFailed(event.transactionId, event.failureReason); break; case "reversed": // A correcting credit exists — see correctionForId on the correction await handleReversal(event.transactionId); break; } }

A transaction.deposit / transaction.withdrawal event tells you a transaction was recorded — its status may still be pending. Wait for transaction.status.changed to successful (or verify server-side) before treating funds as final.

Last updated on