Developers

UDA webhook events

Every UDA deposit produces three webhook deliveries — one for the source-chain confirmation, one when routing starts, and one when the destination transaction lands.

OrderEventWhat it means
1deposit.confirmedSource-chain deposit confirmed at the UDA address
2uda.settlement.createdRouting Engine accepted the deposit and is executing the route
3uda.settlement.completedDestination transaction landed in the destination token

All three share the standard Stridge webhook envelopeid, type, time, version, signed with HMAC SHA-256. The payloads below are the inner payload object.

Note

If a settlement fails permanently, the third event is uda.settlement.failed instead of .completed and includes an error field. Everything else is identical.

Subscribing

Register an endpoint in the dashboard and opt into the three event types. Stridge supports multiple subscribers — one endpoint per environment is the recommended pattern.

Always verify the webhook-signature before trusting the body. See Verify signature for example code in Node.js, Go, and Python.

deposit.confirmed

Fires once the source-chain deposit transaction has reached the required number of confirmations. to_wallet_category: "uda" flags the deposit as routed through a UDA — regular wallet deposits carry the same event type but a different category.

{
  "id": "bcc2b0c1-f75c-43b2-b1bc-c44437d775f4",
  "time": "2026-04-24T06:55:59Z",
  "asset": "BNB",
  "symbol": "BNB",
  "owner": "31d32b68-e455-42b7-9d39-d2904adbe1b8",
  "tx_id": "0xb7b493e68121ce6c7c39b6e0dce56fd45899277a8a85e5c524a718a00837355c",
  "balance": {
    "raw": "5000000000000000",
    "usd": "3.17565",
    "amount": "0.005"
  },
  "decimal": 18,
  "network_id": "9006",
  "network_symbol": "bsc",
  "block_number": "94359674",
  "from_address": "0x5a9b7c3e2f8d4a1b6c0e9f7a3b8c2d5e1f4a7b9c",
  "to_address": "0x3b7e9d1a5c2f4b8e6d0c9f3a2b1e4d5c7a9b8e0f",
  "contract_address": "",
  "is_token_transfer": false,
  "scanner_url": "/tx/0xb7b493e68121ce6c7c39b6e0dce56fd45899277a8a85e5c524a718a00837355c",
  "to_wallet_category": "uda",
  "from_wallet_category": "external"
}
FieldTypeNotes
idstringDeposit id — same as deposit_id on the settlement events
ownerstringUDA id for UDA deposits (not the tenant-level owner you sent on create)
asset / symbolstringThe deposited asset symbol
tx_idstringSource-chain transaction hash
balance.rawstringAmount in the asset's smallest unit (stringified integer)
balance.amountstringHuman-readable amount (already divided by decimal)
balance.usdstringIndicative USD value at detection
network_idstringStridge internal network id
network_symbolstringNetwork slug (ethereum, bsc, base, arbitrum, …)
is_token_transferbooleantrue for ERC-20 transfers, false for native coin
contract_addressstringERC-20 token contract (empty when is_token_transfer is false)
to_addressstringUDA deposit address that received the funds
to_wallet_categoryenum"uda" for UDA deposits — use this to filter out regular wallet deposits
from_wallet_categoryenum"external" for third-party senders
scanner_urlstringRelative path on the chain's block explorer
Tip

The owner field on deposit.confirmed is the UDA id, not the owner string you passed to POST /v1/uda. Use it to look up the UDA record or to join with uda.settlement.* events via uda_address_id.

uda.settlement.created

Fires immediately after the Routing Engine accepts the deposit and opens a settlement. At this point the route has been picked but not yet executed, so destination_amount and fee_amount are zero.

{
  "id": "bcc2b0c1-f75c-43b2-b1bc-c44437d775f4",
  "state": "created",
  "scenario": "cross_chain_diff_token",
  "deposit_id": "bcc2b0c1-f75c-43b2-b1bc-c44437d775f4",
  "deposit_tx_id": "0xb7b493e68121ce6c7c39b6e0dce56fd45899277a8a85e5c524a718a00837355c",
  "uda_address_id": "31d32b68-e455-42b7-9d39-d2904adbe1b8",
  "source_network_id": "9006",
  "source_token_address": "",
  "source_amount": "5000000000000000",
  "destination_network_id": "9001",
  "destination_token_address": "0xaf88d065e77c8cc2239327c5edb3a432268e5831",
  "destination_address": "0x8f4a2c9e1b3d7f5a6c8e0d9b2a4c6e8f0a2c4d6e",
  "destination_amount": "0",
  "fee_amount": "0",
  "created_at": "2026-04-24T06:56:06Z",
  "updated_at": "2026-04-24T06:56:06Z"
}
FieldTypeNotes
id / deposit_idstringSettlement id and originating deposit id (equal on first event)
stateenumcreated
scenarioenumsame_chain_same_token, same_chain_diff_token, cross_chain_same_token, cross_chain_diff_token
uda_address_idstringUDA record the deposit landed on
source_*Network, token, amount on the source side
destination_*Where the funds will be delivered (amount is 0 until completed)
fee_amountstringRouting fee in destination-token smallest units (populated on completed)
source_token_addressstringEmpty string for native coins

uda.settlement.completed

Fires once the destination transaction is on-chain. state is completed, destination_amount and fee_amount are populated, and source_routing_tx_id gives you the outbound tx on the destination chain.

{
  "id": "bcc2b0c1-f75c-43b2-b1bc-c44437d775f4",
  "state": "completed",
  "provider": "lifi",
  "scenario": "cross_chain_diff_token",
  "deposit_id": "bcc2b0c1-f75c-43b2-b1bc-c44437d775f4",
  "deposit_tx_id": "0xb7b493e68121ce6c7c39b6e0dce56fd45899277a8a85e5c524a718a00837355c",
  "uda_address_id": "31d32b68-e455-42b7-9d39-d2904adbe1b8",
  "source_network_id": "9006",
  "source_token_address": "",
  "source_amount": "5000000000000000",
  "source_routing_tx_id": "0x158ffc8b098ae63d697485a75666a337eaab18a2167ff417861f3209dffce29b",
  "destination_network_id": "9001",
  "destination_token_address": "0xaf88d065e77c8cc2239327c5edb3a432268e5831",
  "destination_address": "0x8f4a2c9e1b3d7f5a6c8e0d9b2a4c6e8f0a2c4d6e",
  "destination_amount": "3140",
  "fee_amount": "18485000000000",
  "created_at": "2026-04-24T06:56:06Z",
  "updated_at": "2026-04-24T06:56:17Z"
}
FieldTypeNotes
stateenumcompleted on success; failed with an error field on terminal failure
providerstringBridge/swap provider used (lifi, relay, …)
destination_amountstringDelivered amount in the destination token's smallest unit
fee_amountstringTotal fee (gas + protocol) in the destination token's smallest unit
source_routing_tx_idstringDestination-chain transaction that delivered the funds

Full example timeline

t = 0.0s   User sends 0.005 BNB on BSC → UDA address
t = 7.0s   Observer detects tx                          → deposit.confirmed
t = 7.2s   UDA opens settlement, picks route via LI.FI  → uda.settlement.created
t = 18.0s  LI.FI swap + bridge completes on Arbitrum    → uda.settlement.completed

Total wall time for a cross-chain, cross-token settlement is typically 10–30 seconds on L2 destinations, and 60–90 seconds on Ethereum mainnet.

Consumer checklist

  • Verify every signature. See Verify signature.
  • Deduplicate by envelope id. Stridge retries failed deliveries up to six times; every retry reuses the same id.
  • Treat state as the source of truth, not event ordering. If created is delayed and completed lands first, trust state + updated_at rather than arrival order.
  • Join deposit.confirmed and settlement events via the deposit id. deposit.confirmed.id == uda.settlement.*.deposit_id.
  • Mirror uda.settlement.failed. Treat it as terminal and surface the error field to support tooling; Stridge does not retry failed settlements automatically.

Next

  • Settlements — state machine, failure modes, and the GET /v1/settlements/{id} contract.
  • Server setup — envelope, retries, handler contract.
  • Verify signature — signing algorithm and verification snippets.
Was this page helpful?