Crypto for end users is available to verified merchants only. Unverified merchants receive
ONCHAIN_MERCHANT_NOT_VERIFIED.Supported Networks
All amounts are in USD cents. USDT and USDC are credited 1:1.
Deposits
1
Ask for the user's address
Call
GET /client/crypto/deposit-address?chain=ETH with the client token, or GET /secure/crypto/deposit-address with your API key and a steamId. The first call creates the address. It never changes, so you can cache it and reuse it for every deposit on Ethereum, BNB Smart Chain and Tron.2
Show it to the user
Display
address, the network, the accepted tokens, minDepositCents and the deposit fee. While status is paused the address is valid but deposits are credited only once the chain resumes.3
The user sends the tokens
AssetPay sees the transfer within seconds (on Tron after about a minute, once its block is final) and records a deposit with status
pending.4
The deposit clears
After
minConfirmations blocks the deposit becomes completed, your merchant balance is credited, and you receive a crypto_deposit webhook with the steamId. Credit your user when that webhook arrives.Solana addresses are opened on request
A Solana account costs rent while it is open, so it is opened when the user asks for it and closed again once it has been emptied or has sat unused.- Pass
token=USDTortoken=USDC(defaultUSDC) for the token the user is about to send. USDT and USDC use separate accounts behind the sameaddress, and each one is opened on its own. - The first call answers
status: "pending"withaddress: null. Poll the same endpoint with the sametokenevery few seconds until it isactiveandtokenslists that token. This usually takes under a minute. - Call the endpoint again before every later Solana deposit. If the account was closed in the meantime, the call reopens it.
ONCHAIN_ADDRESS_CAPACITY(503) means too many of your users have an open Solana account right now. Retry later.
Minimum deposit
The live value is
minDepositCents in the address response. A deposit under the minimum is recorded with status below_minimum and waits up to 72 hours for more to the same address. Once the total reaches the minimum, every waiting deposit is credited (completed); if it never does, each one ends failed and is not credited. Tell your users the minimum before they send.
Deposit fee
Deposits on Tron pay a flat $2.50, taken from the deposit, unless the deposit is $10,000 or more. The other chains have no deposit fee. Your merchant balance is credited the amount minus the fee, and thecrypto_deposit webhook carries amount (as sent), fee and netAmount (what was credited).
The address response states the terms for its chain: depositFeeCents is the fee and depositFeeFreeFromCents the amount from which none is charged (null when the chain has no fee). Show both to your users and read them from the response rather than hard-coding them.
Below-minimum deposits that reach the minimum together pay one fee between them. Those credited along with a deposit that cleared on its own pay none.
Deposit statuses
Cashouts
A cashout debits your merchant balance. Debit your own user before you let it go through. There are two ways to start one:
Both work the same way from there: AssetPay asks your server to approve every cashout before anything is sent, the same way it asks for a skin withdrawal. A cashout cannot be taken back once it is on chain, so even a request from your own server is confirmed through your callback URL.
The approval call
Every cashout starts asawaiting_approval. The amount is already held from your merchant balance, and nothing is sent until your server answers.
AssetPay sends a signed POST to your callback URL, the same URL and the same signature as the skin withdrawal approval:
withdrawal, a skin trade carries trade.
Inside your handler: verify the signature, check that
steamId has at least amountCents on your platform, debit them, then answer 200 with { "action": "approve" }. If you approve and the payout later ends as failed, rejected or cancelled, give the user their balance back when that webhook arrives.
Fees and amounts
amountCents is what leaves your merchant balance. A flat network fee per chain, feeCents, comes out of that amount, and the user receives receiveCents:
The fee is the same for every amount. It can change, so read
feeCents from the response rather than hard-coding it. The amount the user receives must be at least $1.00, otherwise the request fails with ONCHAIN_WITHDRAW_BELOW_MIN.
Safe retries
requestId is required. Sending the same requestId for the same user returns the first withdrawal and never creates a second one, so a timed out request can be repeated safely. Use a fresh requestId for every new cashout.
Daily limits
Two rolling 24 hour limits apply: one per end user and one for all of your users together. When one is reached the request fails withONCHAIN_CLIENT_WITHDRAW_LIMIT (403):
scope is user or merchant, and remainingCents is what can still be withdrawn now. Cashouts that were refused, failed or cancelled do not count.
Cashout statuses
Webhooks
Both flows report to your regular callback URL with the regular signature. The body has one top-level key that tells you what it is:
The objects are the same ones the list endpoints return, and the event is the object’s
status. awaiting_approval has no webhook of its own: the approval call is that announcement.
Webhooks can arrive more than once. Key your handling on id plus status.