Static Wallets
Permanent deposit addresses tied to a specific order or user, perfect for recurring and long-term payments.
Static wallets are permanent addresses for receiving cryptocurrency payments. They are linked to a specific order_id and are unique by the combination of project_id + order_id + currency + network.
Use static wallets for:
- Recurring deposits from the same user
- Long-term payment addresses displayed on a user profile
- High-volume deposit flows where you want a stable address per user
Create static wallet
/v1/static-walletRequest parameters
| Field | Type | Required | Description |
|---|---|---|---|
currency | string | yes | Cryptocurrency (USDT, BTC, ETH, etc.) |
network | string | yes | Network code |
order_id | string | yes | Your order/user ID (up to 255 chars) |
label | string | no | Wallet label (up to 255 chars) |
url_callback | string | yes | URL for webhook notifications |
invite_code | string | no | Referrer code |
Request example
{
"currency": "USDT",
"network": "TRX-TRC20",
"order_id": "USER-123",
"label": "User deposit #123",
"url_callback": "https://your-site.com/webhook/static"
}Response example
{
"state": 0,
"result": {
"uuid": "019b2265-34d8-7001-a230-8f97de90d481",
"address": "TXYZabc123...",
"currency": "USDT",
"network": "TRX-TRC20",
"label": "User deposit #123",
"order_id": "USER-123",
"status": "active",
"url": "https://go.2328.io/static/019b2265-34d8-7001-a230-8f97de90d481",
"created_at": "2026-01-20T12:00:00Z",
"qr": "data:image/png;base64,iVBORw0..."
}
}Wallet info
Get static wallet information by uuid or address.
/v1/static-wallet/infoRequest parameters
| Field | Type | Required | Description |
|---|---|---|---|
uuid | string | yes* | Static wallet UUID |
address | string | yes* | Blockchain wallet address |
At least one of uuid or address is required.
Response example
{
"state": 0,
"result": {
"uuid": "019b2265-34d8-7001-a230-8f97de90d481",
"address": "TXYZabc123...",
"currency": "USDT",
"network": "TRX-TRC20",
"status": "active",
"total_received": "1250.50",
"transactions_count": 3,
"created_at": "2026-01-20T12:00:00Z",
"qr": "data:image/png;base64,iVBORw0..."
}
}total_received— sum of all deposits received by this wallet, incurrency.transactions_count— number of deposits received so far.qr— Base64-encoded QR data URI of the deposit address (always present for static wallets, the address is assigned at creation).
Wallet list
/v1/static-wallet/listRequest parameters
| Field | Type | Required | Description |
|---|---|---|---|
status | string | no | Filter by status (active, inactive) |
currency | string | no | Filter by currency |
network | string | no | Filter by network |
order_id | string | no | Filter by order_id |
page | int | no | Page number (default: 1) |
per_page | int | no | Items per page (default: 20, max: 100) |
Response example
{
"state": 0,
"result": {
"items": [
{
"uuid": "019b2265-...",
"address": "TXYZabc123...",
"currency": "USDT",
"network": "TRX-TRC20",
"status": "active",
"total_received": "1250.50",
"transactions_count": 3
}
],
"paginate": {
"count": 1,
"current_page": 1,
"per_page": 20,
"total": 1,
"total_pages": 1,
"has_more": false
}
}
}Enable / disable wallet
Toggle whether a static wallet accepts new payments.
/v1/static-wallet/disable/v1/static-wallet/enableRequest
Both endpoints take a single parameter:
{
"uuid": "019b2265-34d8-7001-a230-8f97de90d481"
}Response example
{
"state": 0,
"result": {
"uuid": "019b2265-34d8-7001-a230-8f97de90d481",
"status": "inactive",
"message": "Static wallet disabled successfully"
}
}For enable, status is "active" and message reads "Static wallet enabled successfully".
Wallet transactions
Get a list of all deposits received by a static wallet.
/v1/static-wallet/transactionsRequest parameters
| Field | Type | Required | Description |
|---|---|---|---|
uuid | string | yes | Static wallet UUID |
date_from | date | no | Start date (YYYY-MM-DD) |
date_to | date | no | End date (YYYY-MM-DD) |
page | int | no | Page number (default: 1) |
per_page | int | no | Items per page (default: 15, max: 5000) |
Response example
{
"state": 0,
"result": {
"items": [
{
"uuid": "abc123-def456-...",
"order_id": "USER-123",
"amount": "100.00",
"currency": "USDT",
"payment_status": "paid",
"txid": "0xabc123def456...",
"fee_amount": "3.00",
"net_amount": "97.00",
"created_at": "2026-01-20T15:30:00Z"
}
],
"paginate": {
"count": 1,
"hasPages": true,
"perPage": 15,
"page": 1
}
}
}fee_amount— platform fee deducted from this deposit, incurrency.net_amount— amount credited to the merchant balance after the fee.
Static wallet webhooks
When a payment is received on a static wallet, the system sends a webhook to url_callback.
The webhook format for static wallets differs from regular payment webhooks. Notably, static wallet webhooks include a merchant_amount field which you should use for crediting.
Webhook payload
{
"uuid": "a28b293f-5c76-4053-8062-ae9ca4ab784b",
"order_id": "USER-7666308594",
"amount": "10.00000000",
"currency": "USDT",
"amount_usd": "10.00000000",
"exchange_rate": "1.00000000",
"payer_currency": "USDT",
"payer_amount": "10.00000000",
"network": "TRX-TRC20",
"address": "TMU9Tgpchvgbywkbj5SdC8KJS73t5m3M7G",
"payment_status": "paid",
"txid": "8369ede26a0da05b1bae154b4bb4072eb2453db30ba86b21831902670929454f",
"tx_explorer_url": "https://tronscan.org/#/transaction/8369ede26a0da05b1bae154b4bb4072eb2453db30ba86b21831902670929454f",
"payment_amount": "10.00000000",
"merchant_amount": "9.920000000000000000",
"created_at": "2026-05-09T16:13:04+03:00",
"sign": "dd958d1405febce670a9a196e9141784b9f2a5f39cd6d1832d6f3f68d0de1e10"
}Static wallet webhooks do not include url or expires_at (since the address is permanent, not a session). They do include exchange_rate and created_at.
Field reference
| Field | Type | Description |
|---|---|---|
uuid | string | Transaction (invoice) UUID for this deposit |
order_id | string | Your static wallet order_id |
amount | decimal (8 dp) | Crypto amount received |
currency | string | Crypto received (matches the wallet's currency) |
amount_usd | decimal (8 dp) | USD value at the time of receipt |
exchange_rate | decimal | Crypto / USD rate used |
payer_currency | string | Same as currency for static wallets |
payer_amount | decimal (8 dp) | Same as amount for static wallets |
network | string | Blockchain network |
address | string | Static wallet address |
payment_status | string | Current deposit status. Normally paid; AML processing can produce aml_lock, which must not be credited automatically. |
txid | string | Blockchain transaction hash |
tx_explorer_url | string | null | Blockchain explorer transaction URL. null when txid is absent or the transfer is internal P2P. |
payment_amount | decimal (8 dp) | Same as amount |
merchant_amount | decimal (18 dp) | Amount after fee deduction — use this for crediting |
created_at | string (ISO 8601) | When the deposit was received |
sign | string (hex) | HMAC-SHA256 signature of the payload |
Best practices
- Unique
order_id— Use a uniqueorder_idfor each user or order - Idempotency — Check
txidbefore processing to avoid duplicate credits - Verify signatures — ALWAYS verify the
signsignature before crediting funds - Use
merchant_amount— Credit users based onmerchant_amount, notpayment_amount
Lifecycle and idempotency
A static wallet is a reusable deposit identity, not an invoice. It has no expected amount and no expiry. One address can produce any number of deposit transactions over its lifetime.
Creation is idempotent for the same merchant project, order_id, currency, and network: the existing wallet is returned. Keep that tuple stable and persist the returned wallet uuid; do not use a new order_id every time the same customer opens the deposit screen.
Deposit idempotency is different from wallet idempotency:
order_ididentifies the reusable wallet/customer mapping;- wallet
uuididentifies the permanent wallet record; - webhook
uuididentifies one detected deposit transaction; txididentifies the on-chain transfer and is the primary deduplication key for crediting.
Use a database uniqueness constraint for the processed chain/network/txid identity and claim it in the same transaction that credits the customer's internal balance.
Enable and disable semantics
Disabling a wallet prevents the application from processing it as an active deposit target; it does not erase the address or its history and cannot stop a blockchain transfer already sent by a user.
Never tell users that funds sent to an inactive address are automatically returned. Blockchain transfers are irreversible. Disable only after removing the address from your UI, and keep an operational recovery procedure for late deposits.
Re-enabling preserves the same wallet identity and address. Do not create a replacement merely to change the label; labels are not settlement identifiers.
Static wallet edge cases
| Situation | Correct handling |
|---|---|
| Duplicate creation request | Accept the returned existing wallet and verify its persisted tuple instead of expecting a new address. |
| Multiple deposits to one address | Create a separate local deposit row for every transaction uuid/txid; never mark the wallet itself as “paid.” |
| Duplicate webhook | Return HTTP 200 after finding the already committed txid; never credit again. |
| Confirmation delay or chain re-observation | Keep processing idempotent and reconcile from /v1/static-wallet/transactions. |
| Deposit below an auto-convert minimum | Expect source-currency credit with no completed convert block. |
| Auto-convert succeeds | Store source payment values and the target convert result separately. |
| Wrong token or wrong network | Do not fabricate a credit. Record evidence and escalate to support/recovery because recoverability is chain-specific. |
| Memo/tag-based chain | Display and validate every destination field returned by the platform; an address alone may be insufficient when a memo is required. |
| AML lock | Do not credit the end user until the authoritative status is released through the compliance process. |
| Wallet disabled after address display | Remove it from the UI immediately, but continue monitoring operational alerts for late transfers. |
Reconciliation model
Run a periodic job that pages through /v1/static-wallet/transactions, upserts deposits by txid, and compares their merchant_amount, status, and optional conversion result with your internal ledger. Webhook delivery should make reconciliation fast, but reconciliation must make it complete.