Convert Guide
This guide explains the Request for Quote (RFQ) workflow used by the BigONE Convert service. Unlike Spot trading (Order Book), Convert offers a guaranteed price for a short window, making it ideal for instant swaps.
Prerequisites
- Base URL:
https://api.big.one/sapi/v1/convert - Authentication: Requires Bearer Token (JWT).
- Required Scope:
convert assets
Lesson 1: The Quote System
The core concept of Convert is the Quote. You ask the system "How much BTC can I get for 1000 USDT?", and the system replies with a price that is locked for a few seconds.
Endpoint: GET /viewer/quote
Key Parameters
from_asset: The asset you want to sell (e.g., "USDT").to_asset: The asset you want to buy (e.g., "BTC").rfq_size: The quantity involved.rfq_size_asset: Crucial field! Tells the system ifrfq_sizerefers to the source or destination asset.- Set to
from_assetif you want to spend a fixed amount (e.g., "Spend exactly 100 USDT"). - Set to
to_assetif you want to receive a fixed amount (e.g., "Get exactly 0.1 BTC").
- Set to
Logic: "I want to spend 1000 USDT"
import requests
import json
BASE_URL = "https://api.big.one/sapi/v1/convert"
headers = {"Authorization": "Bearer YOUR_JWT"}
params = {
"from_asset": "USDT",
"to_asset": "BTC",
"rfq_size": "1000",
"rfq_size_asset": "USDT" # Fixed input
}
response = requests.get(f"{BASE_URL}/viewer/quote", params=params, headers=headers)
quote = response.json()
print(f"Quote ID: {quote['quote_id']}")
print(f"Price: {quote['px']}")
print(f"Valid for: {quote['ttl_ms']} ms")
Lesson 2: Execution (The Trade)
Once you have a valid quote_id, you must "accept" it by creating a trade. This must happen before the quote expires (ttl_ms usually ~10 seconds).
Endpoint: POST /viewer/trade
Account Selection
You can specify where the funds come from using account_type:
FUND: Use the Funding/Wallet account (default).SPOT: Use the Spot Trading account.
Logic: Accept the Quote
quote_id = quote['quote_id']
payload = {
"quote_id": quote_id,
"account_type": "FUND" # Deduct USDT from Funding Account
}
trade_response = requests.post(f"{BASE_URL}/viewer/trade", json=payload, headers=headers)
if trade_response.status_code == 200:
print("Swap Successful!")
print(json.dumps(trade_response.json(), indent=2))
else:
print("Swap Failed:", trade_response.json())
Lesson 3: Handling Expiration
In volatile markets, or due to network latency, your quote might expire before your trade request reaches the server.
Error Code: 54047 (Convert price expired)
Robust Workflow
- Get Quote.
- Send Trade Request immediately.
- Check Response:
- If Success: Done.
- If Error 54047: Loop back to Step 1 (Get New Quote).
def robust_swap():
# 1. Get Quote
quote = requests.get(f"{BASE_URL}/viewer/quote", ...).json()
# 2. Try Trade
res = requests.post(f"{BASE_URL}/viewer/trade", json={"quote_id": quote['quote_id']}, ...)
if res.status_code != 200:
error = res.json()
if error['code'] == 54047:
print("Quote expired, retrying...")
return robust_swap() # Recursive retry
else:
raise Exception(f"Trade failed: {error['message']}")
return res.json()
Complete Example
This script demonstrates a robust "Quote-to-Trade" loop that handles price expiration automatically.
import requests
import time
import jwt
# --- Config ---
BASE_URL = "https://api.big.one/sapi/v1/convert"
API_KEY = "YOUR_KEY"
SECRET_KEY = "YOUR_SECRET"
def get_headers():
token = jwt.encode({
"sub": API_KEY,
"nonce": int(time.time() * 1000000),
"iat": int(time.time()),
"exp": int(time.time()) + 60
}, SECRET_KEY, algorithm="HS256")
return {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
def execute_swap(from_asset, to_asset, amount, max_retries=3):
attempt = 0
while attempt < max_retries:
attempt += 1
print(f"--- Swap Attempt {attempt} ---")
# 1. Get Quote
print("1. Requesting Quote...")
quote_params = {
"from_asset": from_asset,
"to_asset": to_asset,
"rfq_size": str(amount),
"rfq_size_asset": from_asset # Selling fixed amount
}
# Note: Quote endpoint is GET
q_res = requests.get(f"{BASE_URL}/viewer/quote", params=quote_params, headers=get_headers())
if q_res.status_code != 200:
print("Quote Failed:", q_res.json())
return
quote = q_res.json()
quote_id = quote['quote_id']
price = quote['px']
print(f" Quote ID: {quote_id}, Price: {price}")
# 2. Execute Trade
print("2. Executing Trade...")
trade_payload = {
"quote_id": quote_id,
"account_type": "FUND"
}
# Note: Trade endpoint is POST
t_res = requests.post(f"{BASE_URL}/viewer/trade", json=trade_payload, headers=get_headers())
if t_res.status_code == 200:
trade = t_res.json()
print(" SUCCESS!")
print(f" Trade ID: {trade['id']}, Received: {trade['to_sz']} {trade['to_asset']}")
return
else:
error = t_res.json()
code = error.get('code')
print(f" Error: {code} - {error.get('message')}")
# 54047 = Price Expired
if code == 54047:
print(" >> Quote Expired. Retrying immediately...")
continue # Loop back to Step 1
else:
print(" >> Fatal Error. Stopping.")
return
print("Max retries reached.")
if __name__ == "__main__":
# Swap 100 USDT to BTC
execute_swap("USDT", "BTC", 100)
Conclusion
The Convert API provides a streamlined, zero-slippage alternative to the Order Book for executing swaps. By mastering the RFQ (Request for Quote) workflow, you can build reliable payment or exchange services.
Key Takeaways:
- Quote First: Always get a locked price (
quote_id) before trading. - Handle Expiration: Implement a retry loop for
54047errors to handle fast-moving markets robustly. - Direction Control: Use
rfq_size_assetto strictly control exactly how much you spend OR how much you receive.
Next Steps:
- Integrate Convert into your withdrawal flow to allow users to withdraw assets they don't currently hold.
- Check the Convert API Reference for the full list of supported assets.