Skip to main content

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 if rfq_size refers to the source or destination asset.
    • Set to from_asset if you want to spend a fixed amount (e.g., "Spend exactly 100 USDT").
    • Set to to_asset if you want to receive a fixed amount (e.g., "Get exactly 0.1 BTC").

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

  1. Get Quote.
  2. Send Trade Request immediately.
  3. 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 54047 errors to handle fast-moving markets robustly.
  • Direction Control: Use rfq_size_asset to 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.