Developers

Universal Deposit Addresses

A Universal Deposit Address (UDA) is one persistent address per owner that accepts deposits on every supported chain. Every deposit lands in the destination chain and token you configured at create time — Stridge detects, routes, and settles automatically.

Set it up once. Deposit forever, from any chain.

Note

Stridge routes across the EVM chains — Ethereum, Arbitrum, Base, BNB Smart Chain, and Polygon — plus Tron. Other non-EVM chains (Solana, Bitcoin) and fiat on-ramps are on the roadmap. Tron assets that have no cross-chain route need a routing rule.

Why UDA

Cross-chain deposits are painful for end users and expensive for integrators:

  • Users have to pick the right network, bridge, and swap before they can deposit.
  • Integrators build per-chain deposit logic, wallet provisioning, and settlement themselves.
  • Ephemeral per-checkout addresses can't be reused, can't be shown in a user profile, and force reconfiguration on every flow.

UDA replaces all of that with a single persistent address per user (or account, or email). Every deposit — on any chain, in any accepted token — lands in the destination you configured.

How a UDA works

Create a UDA

Call POST /v1/uda (see the API reference) once per owner. Stridge provisions deposit addresses on every supported EVM chain and returns them as a single UDA record.

User deposits from any chain

The user sends any accepted token on any supported chain to the address. They don't have to pick a network in your UI — every chain is already wired up and listening.

Stridge detects the deposit

The Observer service emits a deposit.confirmed webhook as soon as the transaction is confirmed. The payload marks to_wallet_category: "uda" so you can distinguish UDA deposits from regular wallet deposits.

UDA opens a settlement

The UDA service opens a settlement and fires uda.settlement.created. The Routing Engine quotes across providers (LI.FI, Relay), picks the best route, and executes — swap, bridge, or both.

Settlement webhook fires

You receive uda.settlement.completed the moment funds land in the destination token on the destination chain. The same UDA keeps working forever — no re-creation required.

An integrator creates a UDA, the end user deposits on any supported chain, and Stridge emits the three lifecycle events.

Creating a UDA

The minimum request is an owner and a destination. owner is a stable identifier for your user — a wallet address, user id, or email all work. destination is the address and token where every deposit will ultimately land.

POST /v1/uda
{
  "accepted_assets": ["USDC", "USDT", "ETH"],
  "destination": {
    "address": "0x8f4a2c9e1b3d7f5a6c8e0d9b2a4c6e8f0a2c4d6e",
    "asset_symbol": "USDC",
    "network_id": "9001"
  },
  "owner": "user_8a7f3c"
}
FieldRequiredNotes
owneryesAny stable identifier — wallet address, internal user id, or email
destination.addressyesWhere settled funds land
destination.network_idyesStridge network_id of the destination chain
destination.asset_symbolnoSettlement asset — defaults to the destination chain's native token if omitted
accepted_assetsnoAsset-symbol whitelist for all deposit chains. Omit to accept every configured asset
routing_rulesnoUp to 3 per-source overrides of the default destination. See Routing rules
Tip

accepted_assets filters which assets Stridge will route on the source side. It does not change which network a user can deposit on — every supported chain is always active.

destination accepts exactly one of two shapes: the inline network_id + address + asset_symbol triple above, or a treasury: "<name>" reference to a treasury you created in the dashboard. Treasury destinations rotate centrally — see Treasuries for when to pick each.

Calls are idempotent by (tenant, owner): posting the same owner twice returns the existing UDA with 200 OK instead of creating a duplicate.

Response

{
  "id": "31d32b68-e455-42b7-9d39-d2904adbe1b8",
  "status": "active",
  "owner": "user_8a7f3c",
  "destination": {
    "address": "0x8f4a2c9e1b3d7f5a6c8e0d9b2a4c6e8f0a2c4d6e",
    "eip155_id": "42161",
    "network_id": "9001",
    "network_name": "arbitrum",
    "token_address": "0xaf88d065e77c8cc2239327c5edb3a432268e5831",
    "token_symbol": "USDC",
    "token_decimals": 6
  },
  "deposit_addresses": [
    {
      "eip155_id": "1",
      "network_name": "ethereum",
      "address": "0x3b7e9d1a5c2f4b8e6d0c9f3a2b1e4d5c7a9b8e0f",
      "accepted_assets": [
        { "symbol": "USDC", "address": "0xa0b8…eb48", "decimals": 6 },
        { "symbol": "USDT", "address": "0xdac1…1ec7", "decimals": 6 }
      ]
    },
    {
      "eip155_id": "8453",
      "network_name": "base",
      "address": "0x3b7e9d1a5c2f4b8e6d0c9f3a2b1e4d5c7a9b8e0f",
      "accepted_assets": [
        { "symbol": "USDC", "address": "0x8335…2913", "decimals": 6 }
      ]
    }
  ]
}

Full schema and error codes in the API reference.

Routing rules

By default a UDA settles every deposit to the single destination above. Routing rules let one UDA carry up to 3 per-source overrides: a deposit from a specific chain and asset can settle to a destination of its own, while everything else falls back to the default.

This is what makes non-routable assets work — TRX on Tron can't be bridged off Tron, so accepting it requires a rule that keeps it on Tron as a same-chain transfer.

{
  "owner": "user_8a7f3c",
  "destination": {
    "address": "0x8f4a2c9e1b3d7f5a6c8e0d9b2a4c6e8f0a2c4d6e",
    "asset_symbol": "USDC",
    "network_id": "9002"
  },
  "routing_rules": [
    {
      "match": { "source_network_id": "195", "source_asset_symbol": "TRX" },
      "destination": {
        "address": "TJDENsfBJs4RFETt1X1W8wMDc8M5XnJhCe",
        "asset_symbol": "TRX",
        "network_id": "195"
      }
    }
  ]
}

See Routing rules for matching semantics, limits, and the full field reference.

Supported chains & tokens

UDA accepts deposits on every chain returned by GET /v1/uda/supported-chains (see the API reference). The list is refreshed whenever a new network is onboarded and is safe to cache per-request.

Networkeip155_idnetwork_id
Ethereum160
BNB Smart Chain569006
Base84538453
Arbitrum One421619001
Polygon PoS1379002
Tron195

See Supported networks for the full matrix (identifiers, native assets, scanners). Tron is non-EVM, so it has no eip155_id; assets on Tron that have no cross-chain route need a routing rule.

Phase 1 tokens include native coins (ETH, BNB, POL) and the main stablecoins (USDC, USDT) on every chain above. Query supported-chains at runtime to get the authoritative list for your tenant.

Routing scenarios

Every combination of source and destination is handled automatically in Phase 1:

ScenarioExampleRoute
Same chain, same tokenUSDC on Arbitrum → USDC on ArbitrumDirect transfer
Same chain, different tokenUSDT on Arbitrum → USDC on ArbitrumDEX swap (LI.FI)
Cross chain, same tokenUSDC on Base → USDC on ArbitrumBridge (LI.FI/Relay)
Cross chain, different tokenBNB on BSC → USDC on ArbitrumSwap + bridge

The scenario field on settlement webhooks and GET /v1/settlements/{id} tells you which path was taken (see UDA webhook events).

Webhooks

Three events cover the full lifecycle of a UDA deposit:

EventFires when
deposit.confirmedOn-chain deposit is confirmed at the UDA address
uda.settlement.createdRouting Engine has accepted the deposit and begun execution
uda.settlement.completedDestination tx has landed; funds are in the destination token

All UDA webhooks follow the standard signed envelope. The full payload reference lives at UDA webhook events.

Live quote

The quote endpoint returns an indicative fee and ETA without moving any funds. Pick a route below to hit the dev API in your browser and inspect the raw response — no API key, no wallet, no signing required.

Try the quote endpoint
Loading supported chains…

API surface

EndpointPurpose
POST /v1/udaCreate (or return existing) UDA for an owner
GET /v1/udaList UDAs, filter by owner or status
GET /v1/uda/{id}Fetch a UDA with its deposit address set
PATCH /v1/uda/{id}Change destination, accepted assets, routing rules, or pause/resume
DELETE /v1/uda/{id}Retire a UDA (in-flight settlements still complete)
GET /v1/uda/supported-chainsAll chains and assets you can receive on
GET /v1/uda/quoteIndicative fee & time estimate for a given route
GET /v1/uda/{id}/settlementsPaginated settlement history for one UDA
GET /v1/uda/settlements/by-referenceSettlements that an on-chain deposit transaction funded
GET /v1/settlements/{id}Single settlement with deposit, route, fees, tx ids

See the API reference for full request and response schemas.

Next

  • UDA Quickstart — create your first UDA and trace a deposit in under five minutes.
  • Treasuries — back a UDA with a named treasury so the destination can rotate without recreating the UDA.
  • Routing rules — per-source overrides of the default destination, including Tron internal transfers.
  • UDA webhook events — payloads for deposit.confirmed, uda.settlement.created, uda.settlement.completed.
  • Settlements — settlement lifecycle, statuses, and debugging tips.
  • Supported networks — chain identifiers and tokens.
Was this page helpful?