English
Withdrawal Flow
An external withdrawal sends customer wallet funds to an external address. Acceptance reserves the amount and fee; on-chain execution and its final result complete the workflow. An internal transfer sends funds to another OOLIN account through account balance movements.
External withdrawals and internal transfers
| Concern | External withdrawal | Internal transfer |
|---|---|---|
| Destination | External address on the selected network | Another OOLIN account |
| Create API | POST /withdrawals | POST /withdrawals/internal |
| Main inputs | Source account, asset type, network, address, amount | Source/recipient accounts, asset type, amount |
| Processing | Asynchronous on-chain execution after acceptance | Immediate account transfer |
| Fee | Check quote fee_amount | Zero |
| Success | Both completed states and a valid tx_hash | Both completed states and request_type: INTERNAL |
Both use withdrawal_id for detail queries. Internal transfer completion does not require an external network or on-chain tx_hash.
Customer wallet withdrawal stages
text
Customer withdrawal application and authorization
→ validate the destination
→ quote and customer confirmation
→ persist the business request ID
→ create the withdrawal and reserve funds
→ retrieve detail to track the result
→ apply completion or failure1. Validate the destination and quote
Verify the asset/network combination and validate address format with /assets/{asset_id}/validate-address. Then use POST /withdrawals/quote to check account state, amount, limits, fees, balance, and transfer type.
For an external withdrawal, require can_withdraw: true and transfer_type: EXTERNAL. Another OOLIN account's deposit address can be classified as internal, so address format alone does not determine transfer type.
| Quote field | Meaning |
|---|---|
amount | Principal to send |
fee_amount | Fee added to the principal |
receive_amount | Amount received by the recipient |
min_amount, max_amount | Request amount limits |
can_withdraw, reason | Current eligibility and reason when unavailable |
The account needs amount + fee_amount. A quote neither reserves funds nor guarantees success, so also inspect the create response.
2. Persist and create the request
Before submission, connect the withdrawal application to the account, asset, network, amount, destination, and unique client_request_id. Attach the returned withdrawal_id after successful creation.
client_request_id tracks one financial intent and must be unique across internal transfers and external withdrawals. Its purpose differs from the HMAC nonce on each HTTP request. Keep the business request ID during recovery while generating fresh HTTP authentication values.
3. Reserve funds and retrieve the result
If a customer holds 100 USDT and withdraws 20 USDT with a 1 USDT fee, acceptance reserves 21 USDT and leaves 79 USDT available. Total balance remains 100 USDT at this point; the withdrawal is not complete.
External success requires all of the following in detail:
request_type: EXTERNALstatus: COMPLETEDuser_status: COMPLETED- A valid
tx_hash
Without concurrent activity, total balance becomes 79 USDT after completion. After a reservation is released for failure, rejection, or cancellation, verify principal and fee recovery through the final balance. See Balances and Ledger for amount changes.
Lost responses and cancellation
If a create response is lost before receiving the transaction ID, retrieve the existing result with GET /withdrawals/client-request/{client_request_id}. A timeout does not prove financial failure. One WITHDRAWAL_NOT_FOUND also does not prove the original request was never processed; follow the idempotency guide.
You can request cancellation with POST /withdrawals/{withdrawal_id}/cancel, but the withdrawal must still be cancellable. Depending on processing progress, the API can return WITHDRAWAL_NOT_CANCELLABLE. Sending a cancellation request alone does not close the workflow; verify the API result and balance.
Account transfers and Digital Payment
General internal transfers move one asset type between two active accounts. They can serve transfers between a customer's accounts or sending funds to another user's account. Your backend authorizes the source account and action.
Digital Payment sets the customer USER account as sender and the merchant BUSINESS account as recipient, then links the transfer to an order. Merchant settlement follows the external withdrawal process above. Your order or settlement ID identifies the business operation; withdrawal_id identifies the Wallet API fund movement.
Follow Request an External Withdrawal and Track Withdrawal Status for customer wallet requests. See Transaction Status Model for state-dependent behavior.