Skip to main content
A sponsored transfer has two signers. Your user signs to authorize moving their tokens. Bitnob signs as the operator that pays the network fee. Neither signature is enough alone, and neither party can change what the other signed.

Who does what

Bitnob never holds the user’s key or the user’s funds. Tokens go straight from the sender’s address to the recipient, and the fee goes to Bitnob in the same transaction.

The fee model

Bitnob pays the network fee in the native asset and charges a sponsorship fee in the token being sent. The quote fixes the fee, so the user sees the exact cost before they sign, whatever happens to gas prices afterwards. A quote breaks the transfer into parts: total_debit always equals recipient_amount + fee.amount + partner_fee.amount.

Net mode and gross mode

amount on the quote request means one of two things:
  • Net mode, the default: amount is what the recipient receives. The fees are added on top, so total_debit is more than amount. Use it for payments, where the recipient must get an exact amount.
  • Gross mode, with treat_as_gross_amount: true: amount is the sender’s total debit. The fees come out of it, so the recipient gets less than amount. Use it to empty an address without overdrawing it. See Sweep a full balance.
For a 10.50 USDC transfer with a 0.77 USDC fee and no partner fee: A gross-mode quote carries "treat_as_gross_amount": true, so you can check which mode was applied. Net-mode quotes leave the field out. Amounts are decimal strings in the token’s normal units, for example "10.50" USDC. They are not base units. Responses drop trailing zeros, so "1.00" comes back as "1". Compare amounts as decimals, not as strings. The fee covers the network cost of the transfer, so it depends on the chain and on network conditions, and a first-time Tron sender pays more because the quote includes the one-time approval. As a guide, mainnet quotes for 1 unit have come back at about 0.77 USDC on Base and about 2.57 USDT for a first-time sender on Tron. Always show the user the quoted fee.

Quotes expire

A quote is valid until its expires_at, an RFC 3339 timestamp about three minutes after it was created. The user must sign and you must submit before then. After it, Submit returns 409 with quote_expired, and you request a new quote. The quote’s status may still read quoted for a short while after expires_at, so go by the timestamp. Keep the time between quote and submit short: request the quote when the user is ready to confirm, not when they open the screen. If the user takes a long time, re-quote, and show the new amounts before they sign again.

The lifecycle

A signature that doesn’t verify doesn’t fail the transfer. Submit returns 422 and the quote stays quoted, so the user can sign again. onboarding in the diagram stands for the chain-specific step: assembled on EVM, and tron_activating or tron_approving on Tron. Solana goes straight to pending.

Limits

  • Quote rate. Requesting quotes too fast returns 429 with rate_limited.
  • Daily budget. Your organization has a daily sponsored-gas budget. Past it, quotes return 429 with budget_exceeded until the budget resets.
  • Capacity. Rarely, sponsorship capacity is briefly unavailable, and quotes return 503 with capacity_unavailable.
Every 429 carries a Retry-After header. Handle failures and expiry covers how to respond to each.

How this differs from Enterprise wallet transfers

Your policies govern what the Bitnob Secure Enclave signs from your own wallets. In a sponsored transfer the sender’s funds sit at an address your user controls, and your user signs with their own key. Enforce any per-user limits you need in your own application, before you request the quote.