Treasury destinations
A UDA's destination accepts exactly one of two shapes:
- Treasury —
destination.treasury: "<name>"references a named treasury you created in the dashboard. Rotating the treasury propagates automatically to every UDA that points at it. - Inline —
destination.network_id + address + asset_symbolpins a single on-chain destination at create time. Changing it later means recreating the UDA.
Treasury is the recommended shape for any flow where the payout address can change — wallet rotation, cold-storage migration, custodian swap, vendor change — because the change is one dashboard edit, not a mass update across every UDA.
The two shapes are mutually exclusive. Sending both treasury
and inline fields in the same destination object returns
400 Bad Request. This rule applies to the top-level destination
and to each routing_rules[*].destination independently — a
single UDA can mix the two shapes across the default destination and
its routing rules, but never inside the same object.
When to pick treasury
| You want… | Pick |
|---|---|
| A payout address that may rotate (custodian change, wallet refresh, cold-storage move) | Treasury |
| A single fixed destination you know up-front and never need to change | Inline |
| One destination shared across many UDAs that should rotate together | Treasury |
| A one-off destination that belongs to a single UDA | Inline |
| To swap an EVM hot wallet for a smart-contract vault without recreating UDAs | Treasury |
If you start inline and later need to rotate the destination, you have to recreate every UDA — the inline shape pins a snapshot. Starting with a treasury keeps the door open without paying anything up-front: a treasury that never rotates behaves exactly like an inline destination.
How the flow works
In the Stridge Dashboard,
open Treasuries → New treasury and pick a name, the
destination network, address, and settlement asset. The name is
what you'll reference from every UDA, so pick something stable —
main, usdc-arbitrum, cold-storage-eu all work.
Pass the treasury name as destination.treasury instead of the
inline triple.
curl -X POST 'https://api.stridge.com/v1/uda' \
-H 'X-API-Key: '"$STRIDGE_API_KEY"'' \
-H 'Content-Type: application/json' \
-d '{
"accepted_assets": ["USDC", "USDT"],
"destination": { "treasury": "main" },
"owner": "user_8a7f3c"
}'Stridge resolves the treasury at create time, snapshots its current
destination into the UDA record, and returns the usual
deposit_addresses list. No part of the response changes — only the
input shape differs.
When the underlying payout address changes, edit the treasury in the dashboard — not every UDA. Every UDA that references the treasury starts settling to the new destination on its next deposit. In-flight settlements complete against the destination they were opened with.
Treasuries inside routing rules
Each routing_rules[*].destination follows the same EXACTLY-ONE-OF rule independently. A single UDA can have an inline default destination and a treasury corridor, or the reverse — they don't need to match.
{
"owner": "user_8a7f3c",
"accepted_assets": ["USDC", "USDT", "TRX"],
"destination": { "treasury": "main" },
"routing_rules": [
{
"match": { "source_network_id": "195", "source_asset_symbol": "TRX" },
"destination": {
"address": "TJDENsfBJs4RFETt1X1W8wMDc8M5XnJhCe",
"asset_symbol": "TRX",
"network_id": "195"
}
}
]
}The UDA above pools every routable deposit into the main treasury, while TRX on Tron — which has no cross-chain route — stays on Tron at a fixed inline address. Rotating main later does not touch the Tron rule. See Routing rules for the full per-source matching reference.
Idempotency and canonical destinations
POST /v1/uda is idempotent on the canonical destination: when a UDA with the same (tenant, owner) and the same canonical destination already exists, Stridge returns the existing record with 200 OK instead of creating a duplicate.
The canonical destination differs between the two shapes:
| Shape | Canonical destination key |
|---|---|
| Treasury | (tenant, owner, treasury_id) |
| Inline | (tenant, owner, network_id, address, token_address) |
This is what the partial unique indexes on the UDA table enforce.
A treasury UDA and an inline UDA whose current snapshots happen to
coincide are not collapsed: they have independent uniqueness
scopes. Two POST /v1/uda calls with the same owner, one passing
{ treasury: "main" } and the other passing the same address inline,
create two distinct UDAs — and rotating main diverges them
immediately.
Accepted assets
accepted_assets works the same way for treasury UDAs as it does for inline ones — it is a hard filter applied to source assets, independent of the destination shape. An empty accepted_assets (or omitting it) accepts every asset configured on every uda_support chain. Listing assets explicitly is what you want when you only care about, for example, ["USDC", "USDT"].
The list of source assets does not have to include the treasury's settlement asset — Stridge swaps and bridges to the treasury's destination automatically.
Next
- UDA Overview — the UDA model and the full API surface.
- UDA Quickstart — create your first UDA and trace a deposit end-to-end.
- Routing rules — per-source overrides that compose with treasury destinations.
- API reference —
POST /v1/udarequest and response schemas.