When an end user deposits funds to a merchant’s deposit address, NUSDpay sends a deposit event through a Webhook.

Crediting Logic

If either of the following conditions is met, the deposit can be considered credited:
  1. The event type is wallets.transaction.succeeded and status is Completed
  2. The on-chain confirmation count confirmed_num ≥ 10
Why are 10 blocks considered sufficient?Based on the Ethereum 2.0 Beacon Chain finality mechanism, the probability of a transaction being reverted after 10 blocks is extremely low. The official recommendation for full confirmation is 100 blocks (15–20 minutes), but 10 blocks already satisfy the safety requirements for the vast majority of business scenarios.

Payload Example

{
  "event_id": "48bf7cdc-7dd9-4d61-aa61-496003a4787c",
  "url": "https://apidev.nusd.me/webhooks/real",
  "created_timestamp": 1757407060503,
  "type": "wallets.transaction.created",
  "data": {
    "transaction_id": "157d3c84-294b-4ca1-8ca7-f0bbb3b98787",
    "wallet_id": "5c8e4ee0-e701-43b8-9724-7815d7c12643",
    "type": "Deposit",
    "status": "Confirming",
    "source": {
      "source_type": "DepositFromAddress",
      "addresses": ["0xf3f42f3d87ac8687b845146ec38aa9672d9669ab"]
    },
    "destination": {
      "destination_type": "DepositToAddress",
      "amount": "0.001",
      "address": "0x25246af7149a20b2d742b0796431df070eec7048",
      "wallet_id": "5c8e4ee0-e701-43b8-9724-7815d7c12643"
    },
    "chain_id": "TBSC_BNB",
    "token_id": "TBSC_BNB",
    "confirmed_num": 1,
    "confirming_threshold": 15,
    "transaction_hash": "0x77e1a72d410f279d589b185b4b74d4cc7e030cc67d42c7f0f0d3a96d84c08664",
    "block_info": {
      "block_number": 64752220,
      "block_timestamp": 1757407051000
    },
    "timeline": [{
      "status": "Confirming",
      "finished": false,
      "finished_timestamp": 1757407059000
    }]
  }
}

Field Reference

FieldTypeDescription
event_idstringUnique event identifier
typestringEvent type (wallets.transaction.created / updated / succeeded)
created_timestampnumberEvent creation timestamp (milliseconds)
data.transaction_idstringUnique transaction identifier
data.wallet_idstringMerchant wallet ID
data.typestringTransaction type (Deposit)
data.statusstringTransaction status (Confirming / Completed)
data.source.addressesarraySource addresses of the deposit (the end user’s addresses)
data.destination.amountstringDeposit amount
data.destination.addressstringDestination address of the deposit (the merchant’s deposit address)
data.chain_idstringChain identifier
data.token_idstringToken identifier
data.confirmed_numnumberCurrent on-chain confirmation count
data.confirming_thresholdnumberRequired minimum confirmation count
data.transaction_hashstringOn-chain transaction hash
data.block_infoobjectBlock info (block number, timestamp)
data.timelinearrayStatus change timeline

Handling Recommendations

A single deposit may trigger multiple Webhooks (created → updated → succeeded). Use transaction_id for idempotency to avoid double-crediting.
After receiving an event, first verify that data.wallet_id matches your project’s wallet. Events from other projects should be ignored.
In addition to Webhooks, we recommend periodically calling the Transaction Records endpoint as a reconciliation fallback in case Webhooks are lost.

Manual Acquiring

Manual acquiring reuses this callback: when a payer transfers funds to a fixed address created in the dashboard, the system pushes the event through the normal Webhook channel with exactly the same structure as online deposits. There is no new notification mechanism — merchants reuse their existing deposit-handling code as is.
Project routing works the same as online: data.wallet_id in the event is the project acquiring wallet ID (an existing field). NUSDpay provides each project’s wallet ID during onboarding; merchants route on it (e.g. forwarding only offline deposits to an ops notification group).

Field Mapping

When migrating from a third-party acquiring service, common notification fields map to this callback as follows:
Common fieldNUSDpay Webhook fieldNotes
walletName (address label)The webhook does not carry the address description. Look it up merchant-side from data.destination.address against the description entered when creating the address
chaindata.chain_idChain identifier (TBSC_BNB in the Payload example above is a testnet value; production values come from the actual callback)
toAddressdata.destination.addressThe fixed deposit address
notifyTimecreated_timestampMillisecond timestamp (UTC)
orderAmountdata.destination.amountGross on-chain amount (before service fee and conversion)
currencydata.token_idToken identifier with chain prefix (e.g. TRON_USDT); full list in Supported Tokens & Chains
hashdata.transaction_hashOn-chain transaction hash
txIddata.transaction_idNUSDpay transaction ID (idempotency key)
statustype + data.statusSuccess = type is wallets.transaction.succeeded and status is Completed; or confirmed_num ≥ 10 (see Crediting Logic above)
mchNo (merchant/project no.)data.wallet_idUse the project wallet ID (existing field) to distinguish projects; NUSDpay provides each project’s ID
Typical usage: subscribe to this callback → verify wallet_id matches the manual acquiring wallet → assemble a message per the table above → push to an internal IM bot (e.g. Feishu/WeCom), so ops see offline deposits in real time without logging into the dashboard.