OX.FUN
TradeSupport
  • 🏠OX.FUN
  • OX.FUN DOCS
    • 📈Perps
    • 📊Strategies
    • 🐂OX Coin
    • 🍂Seasons
    • 📩Referral
  • Page
  • API
    • ⚙️OX FUN API
    • 🔑API Key Management
    • ☁️Websocket API
      • Authentication
      • Session Keep Alive
      • Order Commands
        • Place Limit Order
        • Place Market Order
        • Place Stop Limit Order
        • Place Stop Market Order
        • Place Batch Market Order
        • Cancel Order
        • Cancel Batch Order
        • Modify Order
        • Modify Batch Orders
      • Subscriptions - Private
        • Balance Channel
        • Position Channel
        • Order Channel
          • Order Opened
          • Order Closed
          • Order Closed Failure
          • Order Modified
          • Order Modified Failure
          • Order Matched
      • Subscriptions - Public
        • Fixed Size Order Book
        • Full Order Book
        • Incremental Order Book
        • Best Bid/Ask
        • Trade
        • Ticker
        • Candles
        • Liquidation RFQ
        • Market
      • Other Responses
      • Error Codes
        • Curl Error Codes
    • 🔌REST API V3
      • Account & Wallet - Private
      • Deposits & Withdrawals - Private
      • Market Data - Public
      • Orders - Private
      • Trades - Private
  • 🔗External
    • 💧Aerodrome Pool
    • 🔵Trade on Uniswap (Base)
    • Trade on Solana
    • 🦎CoinGecko
    • API Code Examples
  • 🔗SOCIALS
    • 🐂OX.FUN
    • Discord
    • Twitter
Powered by GitBook
On this page
  • GET /v3/account
  • GET /v3/account/names
  • GET /v3/wallet
  • POST /v3/transfer
  • GET /v3/transfer
  • GET /v3/balances
  • GET /v3/positions
  • GET /v3/funding
  1. API
  2. REST API V3

Account & Wallet - Private

GET /v3/account

Get account information

Calling this endpoint using an API key pair linked to the parent account with the parameter "subAcc" allows the caller to include additional sub-accounts in the response. This feature does not work when using API key pairs linked to a sub-account.

Cure

Request

GET v3/account?subAcc={subAcc},{subAcc}

Successful response format

{
    "success": true,
    "data": [
        {
            "accountId": "21213",
            "name": "main",
            "accountType": "PORTFOLIO",
            "balances": [
                {
                    "asset": "OX",
                    "total": "100000",
                    "available": "100000",
                    "reserved": "0",
                    "lastUpdatedAt": "1593627415234"
                },
                {
                    "asset": "USDT",
                    "total": "1585.890",
                    "available": "325.890",
                    "reserved": "1260.0",
                    "lastUpdatedAt": "1593627415123"
                }
            ],
            "positions": [
                {
                    "marketCode": "BTC-USD-SWAP-LIN", 
                    "baseAsset": "BTC", 
                    "counterAsset": "USD", 
                    "position": "0.00030", 
                    "entryPrice": "43976.700", 
                    "markPrice": "43788.1", 
                    "positionPnl": "-5.6580", 
                    "estLiquidationPrice": "2.59", 
                    "lastUpdatedAt": "1637876701404",
                }
            ],
            "collateral": "100000.0",
            "notionalPositionSize": "1313.643",
            "portfolioVarMargin": "131.3643",
            "maintenanceMargin": "65.68215",
            "marginRatio": "0.065682",
            "riskRatio": "761.241829",
            "liquidating": false,
            "feeTier": "2",
            "createdAt": "1611665624601"
        }
    ]
}}
Python
import os
import requests
import hmac
import hashlib
import base64
from dotenv import load_dotenv
from datetime import datetime
import time

load_dotenv()

def get_account_info(sub_accounts=None):
    api_key = os.getenv('API_KEY')
    secret_key = os.getenv('API_SECRET').encode('utf-8')
    ts = datetime.utcnow().isoformat()
    nonce = str(int(time.time() * 1000))
    method = "/v3/account"
    api_url = "api.ox.fun"
    
    # Prepare the subAcc parameter if sub_accounts are provided
    sub_acc_param = f'subAcc={",".join(sub_accounts)}' if sub_accounts else ''
    body = sub_acc_param

    msg_string = f'{ts}\n{nonce}\nGET\n{api_url}\n{method}\n{body}'
    sign = base64.b64encode(hmac.new(secret_key, msg_string.encode('utf-8'), hashlib.sha256).digest()).decode('utf-8')

    headers = {
        'Content-Type': 'application/json',
        'AccessKey': api_key,
        'Timestamp': ts,
        'Signature': sign,
        'Nonce': nonce
    }

    try:
        # Construct the URL with the subAcc parameter if it exists
        url = f'https://{api_url}{method}'
        if sub_acc_param:
            url += f'?{sub_acc_param}'
        
        response = requests.get(url, headers=headers)

        # Print the raw response content for debugging
        print("Raw Response Content:", response.content)

        # Check if the response is JSON
        if response.headers.get('Content-Type') == 'application/json':
            response_data = response.json()
            if response_data.get('success'):
                return response_data.get('data')
            else:
                print('Failed to fetch account data')
        else:
            print('Response is not in JSON format')

    except requests.exceptions.RequestException as error:
        print('Error making API request:', error)

# Example usage
response = get_account_info()

print(response)
Javascript
require('dotenv').config();
const axios = require('axios');
const CryptoJS = require("crypto-js");

async function getAccountInfo(subAccounts = []) {
  const apiKey = process.env.API_KEY;
  const secretKey = process.env.API_SECRET;
  const timestamp = new Date().toISOString();
  const nonce = Math.random().toString(36).substring(2);
  const verb = 'GET';
  const path = 'api.ox.fun';
  const method = '/v3/account';
  const subAccParam = subAccounts.length ? `subAcc=${subAccounts.join(',')}` : '';
  const body = subAccParam;

  const msgString = `${timestamp}\n${nonce}\n${verb}\n${path}\n${method}\n${body}`;
  const sign = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(msgString, secretKey));

  try {
    let url = `https://${path}${method}`;
    if (subAccParam) {
      url += `?${subAccParam}`;
    }

    const response = await axios.get(url, {
      headers: {
        'Content-Type': 'application/json',
        'AccessKey': apiKey,
        'Timestamp': timestamp,
        'Signature': sign,
        'Nonce': nonce
      }
    });

    console.log("Raw Response Content:", response.data);

    if (response.data.success) {      
      return response.data.data;
    } else {
      console.error('Failed to fetch account data');
    }
  } catch (error) {
    console.error('Error making API request:', error.response ? error.response.data : error.message);
  }
}

// Example usage
response = getAccountInfo();
console.log(response);
Request Parameter
Type
Required
Description

subAcc

STRING

NO

Name of sub account. If no subAcc is given, then the response contains only the account linked to the API-Key. Multiple subAccs can be separated with a comma, maximum of 10 subAccs, e.g. subone,subtwo

Response Field
Type
Description

accountId

STRING

Account ID

name

STRING

Account name

accountType

STRING

Account type LINEAR, STANDARD, PORTFOLIO

balances

LIST of dictionaries

asset

STRING

Asset name

total

STRING

Total balance

available

STRING

Available balance

reserved

STRING

Reserved balance

lastUpdatedAt

STRING

Last balance update timestamp

positions

LIST of dictionaries

Positions - only returned if the account has open positions

marketCode

STRING

Market code

baseAsset

STRING

Base asset

counterAsset

STRING

Counter asset

position

STRING

Position size

entryPrice

STRING

Entry price

markPrice

STRING

Mark price

positionPnl

STRING

Position PNL

estLiquidationPrice

STRING

Estimated liquidation price

lastUpdatedAt

STRING

Last position update timestamp

marginBalance

STRING

[Currently Unavailable] Appears in the position section only for positions using isolated margin. Isolated margin + Unrealized position PnL

maintenanceMargin

STRING

[Currently Unavailable] Appears in the position section only for positions using isolated margin

marginRatio

STRING

[Currently Unavailable] Appears in the position section only for positions using isolated margin

leverage

STRING

[Currently Unavailable] Appears in the position section only for positions using isolated margin

collateral

STRING

Total collateral balance

notionalPositionSize

STRING

Notional position size in OX

portfolioVarMargin

STRING

Initial margin

maintenanceMargin

STRING

Maintenance margin. The minimum amount of collateral required to avoid liquidation

marginRatio

STRING

Margin ratio. Orders are rejected/cancelled if the margin ratio reaches 50, and liquidation occurs if the margin ratio reaches 100

riskRatio

STRING

Ignore.

liquidating

BOOL

Available values: true and false

feeTier

STRING

Fee tier

createdAt

STRING

Timestamp indicating when the account was created

GET /v3/account/names

Get sub account information

This endpoint can only be called using API keys paired with the parent account! Returns all active subaccounts.

Curl

Request

GET v3/account/names

Successful response format

{
    "success": true,
    "data": [  
        {
          "accountId": "21213",
          "name": "Test 1"
        }, 
        {
          "accountId": "21214",
          "name": "Test 2"
        }
    ] 
}
Python
import os
import requests
import hmac
import hashlib
import base64
from dotenv import load_dotenv
from datetime import datetime
import time

load_dotenv()

def get_account_names():
    api_key = os.getenv('API_KEY')
    secret_key = os.getenv('API_SECRET').encode('utf-8')
    ts = datetime.utcnow().isoformat()
    nonce = str(int(time.time() * 1000))
    method = "/v3/account/names"
    api_url = "api.ox.fun"
    body = ""

    msg_string = f'{ts}\n{nonce}\nGET\n{api_url}\n{method}\n{body}'
    sign = base64.b64encode(hmac.new(secret_key, msg_string.encode('utf-8'), hashlib.sha256).digest()).decode('utf-8')

    headers = {
        'Content-Type': 'application/json',
        'AccessKey': api_key,
        'Timestamp': ts,
        'Signature': sign,
        'Nonce': nonce
    }

    try:
        url = f'https://{api_url}{method}'
        response = requests.get(url, headers=headers)

        print("Raw Response Content:", response.content)

        if response.headers.get('Content-Type') == 'application/json':
            response_data = response.json()
            if response_data.get('success'):                
                return response_data.get('data')
            else:
                print('Failed to fetch account names')
        else:
            print('Response is not in JSON format')

    except requests.exceptions.RequestException as error:
        print('Error making API request:', error)

# Example usage
response = get_account_names()
print(response)
Javascript
require('dotenv').config();
const axios = require('axios');
const CryptoJS = require("crypto-js");

async function getAccountNames() {
  const apiKey = process.env.API_KEY;
  const secretKey = process.env.API_SECRET;
  const timestamp = new Date().toISOString();
  const nonce = Math.random().toString(36).substring(2);
  const verb = 'GET';
  const path = 'api.ox.fun';
  const method = '/v3/account/names';
  const body = '';

  const msgString = `${timestamp}\n${nonce}\n${verb}\n${path}\n${method}\n${body}`;
  const sign = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(msgString, secretKey));

  try {
    const url = `https://${path}${method}`;

    const response = await axios.get(url, {
      headers: {
        'Content-Type': 'application/json',
        'AccessKey': apiKey,
        'Timestamp': timestamp,
        'Signature': sign,
        'Nonce': nonce
      }
    });

    console.log("Raw Response Content:", response.data);

    if (response.data.success) {
      console.log("Account Names:", response.data.data);
      return response.data.data;
    } else {
      console.error('Failed to fetch account names');
    }
  } catch (error) {
    console.error('Error making API request:', error.response ? error.response.data : error.message);
  }
}

// Example usage
getAccountNames();
Response Field
Type
Description

accountId

STRING

Account ID

name

STRING

Account name

GET /v3/wallet

Get account or sub-account wallet

Calling this endpoint using an API key pair linked to the parent account with the parameter "subAcc" allows the caller to include additional sub-accounts in the response. This feature does not work when using API key pairs linked to a sub-account.

Curl

Request

GET v3/wallet?subAcc={name1},{name2}&type={type}&limit={limit}&startTime={startTime}&endTime={endTime}

Successful response format

{
    "success": true,
    "data": [
        {
             "accountId": "21213",
             "name": "main",
             "walletHistory": [
                  {
                    "id": "810583329159217160",
                    "asset": "USDT",
                    "type": "DEPOSIT", 
                    "amount": "10",
                    "createdAt": "162131535213"  
                  }     
             ]
        }
    ]
}

Python
//code
Javascript
// Some code
Request Parameter
Type
Required
Description

subAcc

STRING

NO

Max 5

type

STRING

NO

DEPOSIT, WITHDRAWAL, etc, default return all, most recent first

limit

LONG

NO

Default 200, max 500

startTime

LONG

NO

Millisecond timestamp. Default 24 hours ago. startTime and endTime must be within 7 days of each other. startTime is INCLUSIVE

endTime

LONG

NO

Millisecond timestamp. Default time now. startTime and endTime must be within 7 days of each other. endTime is INCLUSIVE

Response Field
Type
Description

accountId

STRING

Account ID

name

STRING

Account name

walletHistory

LIST of dictionaries

id

STRING

A unique ID

amount

STRING

Amount

asset

STRING

Asset name

type

STRING

createdAt/lastUpdatedAt

STRING

Millisecond timestamp created time or updated time

POST /v3/transfer

Sub-account balance transfer — TODO

Transferring funds between sub-accounts is restricted to API keys linked to the parent account.

Curl

Request

POST /v3/transfer
{
    "asset": "USDT",
    "quantity": "1000",
    "fromAccount": "14320",
    "toAccount": "15343"
}

Successful response format

{
    "success": true,
    "data": {
        "asset": "USDT", 
        "quantity": "1000",
        "fromAccount": "14320",
        "toAccount": "15343",
        "transferredAt": "1635038730480"
    }
}
Python
import os
import requests
import hmac
import hashlib
import base64
import time
import json
from dotenv import load_dotenv

load_dotenv()

def create_transfer(asset, quantity, from_account, to_account):
    api_key = os.getenv('API_KEY')
    secret_key = os.getenv('API_SECRET').encode('utf-8')
    ts = time.strftime('%Y-%m-%dT%H:%M:%S', time.gmtime())
    nonce = str(int(time.time() * 1000))
    method = "/v3/transfer"
    api_url = "api.ox.fun"

    body = {
        "asset": asset,
        "quantity": quantity,
        "fromAccount": from_account,
        "toAccount": to_account
    }

    # For POST requests, we use the JSON stringified body instead of query params
    body_string = json.dumps(body)
    msg_string = f"{ts}\n{nonce}\nPOST\n{api_url}\n{method}\n{body_string}"

    sign = base64.b64encode(hmac.new(secret_key, msg_string.encode('utf-8'), hashlib.sha256).digest()).decode('utf-8')

    headers = {
        'Content-Type': 'application/json',
        'AccessKey': api_key,
        'Timestamp': ts,
        'Signature': sign,
        'Nonce': nonce
    }

    try:
        response = requests.post(f"https://{api_url}{method}", json=body, headers=headers)
        response.raise_for_status()
        data = response.json()
        if data.get('success'):
            return data['data']
        else:
            print('Failed to create transfer')
    except requests.exceptions.RequestException as error:
        print('Error creating transfer:', error)

# Example usage
asset = 'USDT'
quantity = '1000'
from_account = '14320'
to_account = '15343'

response = create_transfer(asset, quantity, from_account, to_account)
print(response)
Javascript
require('dotenv').config();
const CryptoJS = require("crypto-js");
const axios = require('axios');

async function createTransfer(asset, quantity, fromAccount, toAccount) {
  const apiKey = process.env.API_KEY;
  const secretKey = process.env.API_SECRET;
  const ts = new Date().toISOString();
  const nonce = Math.random().toString(36).substring(2);
  const method = "/v3/transfer";
  const apiUrl = "api.ox.fun";

  const body = {
    asset,
    quantity,
    fromAccount,
    toAccount
  };

  // For POST requests, we use the JSON stringified body instead of query params
  const bodyString = JSON.stringify(body);
  const msgString = `${ts}\n${nonce}\nPOST\n${apiUrl}\n${method}\n${bodyString}`;

  const sign = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(msgString, secretKey));

  const headers = {
    'Content-Type': 'application/json',
    'AccessKey': apiKey,
    'Timestamp': ts,
    'Signature': sign,
    'Nonce': nonce
  };

  try {
    const response = await axios.post(`https://${apiUrl}${method}`, body, { headers });
    if (response.data.success) {
      return response.data.data;
    } else {
      console.error('Failed to create transfer');
    }
  } catch (error) {
    console.error('Error creating transfer:', error.response ? error.response.data : error.message);
  }
}

// Example usage
const asset = 'USDT';
const quantity = '1000';
const fromAccount = '14320';
const toAccount = '15343';

createTransfer(asset, quantity, fromAccount, toAccount).then(data => {
  console.log(data);
});
Request Parameter
Type
Required
Description

asset

STRING

YES

quantity

STRING

YES

fromAccount

STRING

YES

toAccount

STRING

YES

Response Field
Type
Description

asset

STRING

quantity

STRING

fromAccount

STRING

toAccount

STRING

transferredAt

STRING

Millisecond timestamp

GET /v3/transfer

Sub-account balance transfer history

API keys linked to the parent account can get all account transfers, while API keys linked to a sub-account can only see transfers where the sub-account is either the "fromAccount" or "toAccount".

Curl

Request

GET /v3/transfer?asset={asset}&limit={limit}&startTime={startTime}&endTime={endTime}

Successful response format

{
    "success": true,
    "data": [
        {
            "asset": "USDT", 
            "quantity": "1000",
            "fromAccount": "14320",
            "toAccount": "15343",
            "id": "703557273590071299",
            "status": "COMPLETED",
            "transferredAt": "1634779040611"
        }
    ]
}
Python
import os
import requests
import hmac
import hashlib
import base64
import time
from dotenv import load_dotenv

load_dotenv()

def fetch_transfers(asset, limit, start_time, end_time):
    api_key = os.getenv('API_KEY')
    secret_key = os.getenv('API_SECRET').encode('utf-8')
    ts = time.strftime('%Y-%m-%dT%H:%M:%S', time.gmtime())
    nonce = str(int(time.time() * 1000))
    method = "/v3/transfer"
    api_url = "api.ox.fun"

    query_string = f"asset={asset}&limit={limit}&startTime={start_time}&endTime={end_time}"
    msg_string = f"{ts}\n{nonce}\nGET\n{api_url}\n{method}\n{query_string}"

    sign = base64.b64encode(hmac.new(secret_key, msg_string.encode('utf-8'), hashlib.sha256).digest()).decode('utf-8')

    headers = {
        'Content-Type': 'application/json',
        'AccessKey': api_key,
        'Timestamp': ts,
        'Signature': sign,
        'Nonce': nonce
    }

    try:
        response = requests.get(f"https://{api_url}{method}?{query_string}", headers=headers)
        response.raise_for_status()
        data = response.json()
        if data.get('success'):
            return data['data']
        else:
            print('Failed to fetch transfer data')
    except requests.exceptions.RequestException as error:
        print('Error fetching transfer data:', error)

# Example usage
asset = 'OX'
limit = 100
start_time = int(time.time() * 1000) - 24 * 60 * 60 * 1000
end_time = int(time.time() * 1000)
response = fetch_transfers(asset, limit, start_time, end_time)
print(response)
Javascript
require('dotenv').config();
const CryptoJS = require("crypto-js");
const axios = require('axios');

async function fetchTransfers(asset, limit, startTime, endTime) {
  const apiKey = process.env.API_KEY;
  const secretKey = process.env.API_SECRET;
  const ts = new Date().toISOString();
  const nonce = Math.random().toString(36).substring(2);
  const method = "/v3/transfer";
  const apiUrl = "api.ox.fun";

  const queryString = `asset=${asset}&limit=${limit}&startTime=${startTime}&endTime=${endTime}`;
  const msgString = `${ts}\n${nonce}\nGET\n${apiUrl}\n${method}\n${queryString}`;

  const sign = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(msgString, secretKey));

  const headers = {
    'Content-Type': 'application/json',
    'AccessKey': apiKey,
    'Timestamp': ts,
    'Signature': sign,
    'Nonce': nonce
  };

  try {
    const response = await axios.get(`https://${apiUrl}${method}?${queryString}`, { headers });
    if (response.data.success) {
      return response.data.data;
    } else {
      console.error('Failed to fetch transfer data');
    }
  } catch (error) {
    console.error('Error fetching transfer data:', error.response ? error.response.data : error.message);
  }
}

// Example usage
const asset = 'OX';
const limit = 100;
const startTime = Date.now() - 24 * 60 * 60 * 1000;
const endTime = Date.now();
fetchTransfers(asset, limit, startTime, endTime).then(data => {
  console.log(data);
});

Request Parameter
Type
Required
Description

asset

STRING

NO

Default all assets

limit

LONG

NO

Default 50, max 200

startTime

LONG

NO

Millisecond timestamp. Default 24 hours ago. startTime and endTime must be within 7 days of each other. startTime is INCLUSIVE

endTime

LONG

NO

Millisecond timestamp. Default time now. startTime and endTime must be within 7 days of each other. endTime is INCLUSIVE

Response Field
Type
Description

asset

STRING

quantity

STRING

fromAccount

STRING

toAccount

STRING

id

STRING

status

STRING

transferredAt

STRING

Millisecond timestamp

GET /v3/balances

Calling this endpoint using an API key pair linked to the parent account with the parameter "subAcc" allows the caller to include additional sub-accounts in the response. This feature does not work when using API key pairs linked to a sub-account.

Curl

Request

GET /v3/balances?subAcc={name1},{name2}&asset={asset}

Successful response format

{
    "success": true,
    "data": [
        {
            "accountId": "21213",
            "name": "main",
            "balances": [
               {
                   "asset": "USDT",
                   "total": "4468.823",              
                   "available": "4468.823",        
                   "reserved": "0",
                   "lastUpdatedAt": "1593627415234"
               },
               {
                   "asset": "OX",
                   "total": "100000.20",              
                   "available": "100000.20",         
                   "reserved": "0",
                   "lastUpdatedAt": "1593627415123"
               }
            ]
        }
    ]
}
Python
import os
import requests
import hmac
import hashlib
import base64
import time
from dotenv import load_dotenv

load_dotenv()

def get_balances(sub_accounts=None, asset=''):
    api_key = os.getenv('API_KEY')
    secret_key = os.getenv('API_SECRET').encode('utf-8')
    ts = time.strftime('%Y-%m-%dT%H:%M:%S', time.gmtime())
    nonce = str(int(time.time() * 1000))
    method = "/v3/balances"
    api_url = "api.ox.fun"

    # Construct query parameters
    sub_acc_param = f"subAcc={','.join(sub_accounts)}" if sub_accounts else ""
    asset_param = f"asset={asset}" if asset else ""
    query_string = '&'.join(filter(None, [sub_acc_param, asset_param]))

    msg_string = f"{ts}\n{nonce}\nGET\n{api_url}\n{method}\n{query_string}"
    
    sign = base64.b64encode(hmac.new(secret_key, msg_string.encode('utf-8'), hashlib.sha256).digest()).decode('utf-8')

    headers = {
        'Content-Type': 'application/json',
        'AccessKey': api_key,
        'Timestamp': ts,
        'Signature': sign,
        'Nonce': nonce
    }

    try:
        response = requests.get(f"https://{api_url}{method}?{query_string}", headers=headers)
        response.raise_for_status()
        data = response.json()
        print('Response:', data)

        # Display each account's balances
        for account in data.get('data', []):
            print(f"Account Name: {account['name']}")
            for balance in account['balances']:
                print(f"Asset: {balance['asset']}, Total: {balance['total']}, Available: {balance['available']}, Reserved: {balance['reserved']}")
    except requests.exceptions.RequestException as error:
        print('Error fetching balances:', error)

# Example usage
sub_accounts = ['subaccount1']
asset = 'OX'
get_balances(sub_accounts, asset) 
Javascript
const axios = require('axios');
const crypto = require('crypto');
require('dotenv').config();

async function getBalances(subAccounts = [], asset = '') {
    const apiKey = process.env.API_KEY;
    const secretKey = process.env.API_SECRET;
    const ts = new Date().toISOString();
    const nonce = Math.random().toString(36).substring(2);
    const apiUrl = "api.ox.fun";
    const method = "/v3/balances";
    
    // Construct query parameters
    const subAccParam = subAccounts.length > 0 ? `subAcc=${subAccounts.join(',')}` : '';
    const assetParam = asset ? `asset=${asset}` : '';
    const queryString = [subAccParam, assetParam].filter(Boolean).join('&');
    
    const msgString = `${ts}\n${nonce}\nGET\n${apiUrl}\n${method}\n${queryString}`;
    
    const sign = crypto.createHmac('sha256', secretKey)
        .update(msgString)
        .digest('base64');

    const headers = {
        'Content-Type': 'application/json',
        'AccessKey': apiKey,
        'Timestamp': ts,
        'Signature': sign,
        'Nonce': nonce
    };

    try {
        const response = await axios.get(`https://${apiUrl}${method}?${queryString}`, { headers });
        console.log('Response:', response.data);

        // Display each account's balances
        response.data.data.forEach(account => {
            console.log(`Account Name: ${account.name}`);
            account.balances.forEach(balance => {
                console.log(`Asset: ${balance.asset}, Total: ${balance.total}, Available: ${balance.available}, Reserved: ${balance.reserved}`);
            });
        });
    } catch (error) {
        console.error('Error fetching balances:', error.response ? error.response.data : error.message);
    }
}

// Example usage
const subAccounts = ['subaccount1'];
const asset = 'OX';
getBalances(subAccounts, asset);
Request Parameter
Type
Required
Description

asset

STRING

NO

Default all assets

subAcc

STRING

NO

Name of sub account. If no subAcc is given, then the response contains only the account linked to the API-Key. Multiple subAccs can be separated with a comma, maximum of 10 subAccs, e.g. subone,subtwo

Response Field
Type
Description

accountId

STRING

Account ID

name

STRING

The parent account is named "main" and comes first

balances

LIST of dictionaries

asset

STRING

Asset name

total

STRING

Total balance (available + reserved)

available

STRING

Available balance

reserved

STRING

Reserved balance

lastUpdatedAt

STRING

Timestamp of updated at

GET /v3/positions

Returns position data

Curl

Request

GET /v3/positions?subAcc={name1},{name2}&marketCode={marketCode}

Successful response format

{
  "success": True,
  "data": [
      {
        "accountId": "1234",
        "name": "main",
        "positions": [
            {
              "marketCode": "BTC-USD-SWAP-LIN",
              "baseAsset": "BTC",
              "counterAsset": "USD",
              "position": "-0.00030",
              "entryPrice": "43976.7",
              "markPrice": "43706.3",
              "positionPnl": "8.112",
              "estLiquidationPrice": "23611539.7",
              "lastUpdatedAt": "1673231134601",
            }
        ]
      }
  ]
}
Python
import os
import requests
import hmac
import hashlib
import base64
import time
from dotenv import load_dotenv

load_dotenv()
def fetch_positions(sub_accounts, market_code):
    api_key = os.getenv('API_KEY')
    secret_key = os.getenv('API_SECRET').encode('utf-8')
    ts = time.strftime('%Y-%m-%dT%H:%M:%S', time.gmtime())
    nonce = str(int(time.time() * 1000))
    method = "/v3/positions"
    api_url = "api.ox.fun"
    
    sub_acc_param = f"subAcc={','.join(sub_accounts)}" if sub_accounts else ""
    query_string = f"{sub_acc_param}&marketCode={market_code}".strip('&')
    msg_string = f"{ts}\n{nonce}\nGET\n{api_url}\n{method}\n{query_string}"
    
    sign = base64.b64encode(hmac.new(secret_key, msg_string.encode('utf-8'), hashlib.sha256).digest()).decode('utf-8')
    
    headers = {
        'Content-Type': 'application/json',
        'AccessKey': api_key,
        'Timestamp': ts,
        'Signature': sign,
        'Nonce': nonce
    }
    
    try:
        response = requests.get(f"https://{api_url}{method}?{query_string}", headers=headers)
        response.raise_for_status()
        return response.json()
    except requests.exceptions.RequestException as error:
        print('Error fetching positions:', error)
# Example usage
# Example usage
sub_accounts = None
market_code = 'BTC-USD-SWAP-LIN'
response = fetch_positions(sub_accounts, market_code)
print(response)
Javascript
require('dotenv').config();
const axios = require('axios');
const CryptoJS = require("crypto-js");

async function fetchPositions(subAccounts, marketCode) {
  const apiKey = process.env.API_KEY;
  const secretKey = process.env.API_SECRET;
  const ts = new Date().toISOString();
  const nonce = Math.random().toString(36).substring(2);
  const method = "/v3/positions";
  const apiUrl = "api.ox.fun";

  const subAccParam = subAccounts ? `subAcc=${subAccounts.join(',')}` : "";
  const queryString = `${subAccParam}&marketCode=${marketCode}`.replace(/^&/, '');
  const msgString = `${ts}\n${nonce}\nGET\n${apiUrl}\n${method}\n${queryString}`;

  const sign = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(msgString, secretKey));

  const headers = {
    'Content-Type': 'application/json',
    'AccessKey': apiKey,
    'Timestamp': ts,
    'Signature': sign,
    'Nonce': nonce
  };

  try {
    const response = await axios.get(`https://${apiUrl}${method}?${queryString}`, { headers });
    return response.data;
  } catch (error) {
    console.error('Error fetching positions:', error);
  }
}

// Example usage
const subAccounts = null;
const marketCode = 'BTC-USD-SWAP-LIN';
fetchPositions(subAccounts, marketCode).then(response => console.log(response));

Calling this endpoint using an API key pair linked to the parent account with the parameter "subAcc" allows the caller to include additional sub-accounts in the response. This feature does not work when using API key pairs linked to a sub-account. Returns an empty array [] when no positions were found

Request Parameter
Type
Required
Description

marketCode

STRING

NO

Default all markets

subAcc

STRING

NO

Name of sub account. If no subAcc is given, then the response contains only the account linked to the API-Key. Multiple subAccs can be separated with a comma, maximum of 10 subAccs, e.g. subone,subtwo

Response Fields
Type
Description

accountId

STRING

Account ID

name

STRING

The parent account is named "main" and comes first

positions

LIST of dictionaries

marketCode

STRING

Contract symbol, e.g. 'BTC-oUSD-SWAP-LIN'

baseAsset

STRING

counterAsset

STRING

position

STRING

Position size, e.g. '0.94'

entryPrice

STRING

Average entry price

markPrice

STRING

positionPnl

STRING

Postion profit and lost

estLiquidationPrice

STRING

Estimated liquidation price, return 0 if it is negative(<0)

lastUpdated

STRING

Timestamp when position was last updated

marginBalance

STRING

[Currently Unavailable] Appears in the position section only for positions using isolated margin. Isolated margin + Unrealized position PnL

maintenanceMargin

STRING

[Currently Unavailable] Appears in the position section only for positions using isolated margin

marginRatio

STRING

[Currently Unavailable] Appears in the position section only for positions using isolated margin

leverage

STRING

[Currently Unavailable] Appears in the position section only for positions using isolated margin

GET /v3/funding

Get funding payments by marketCode and sorted by time in descending order.

Curl

Request

GET v3/funding?marketCode={marketCode}&limit={limit}&startTime={startTime}&endTime={endTime}

SUCCESSFUL RESPONSE

{
    "success": true,
    "data": [
        {
            "id": "810583329213284361",
            "marketCode": "BTC-oUSD-SWAP-LIN",
            "payment": "-122.17530872",
            "fundingRate": "-0.00005",
            "position": "-61.093",
            "indexPrice": "39996.5",
            "createdAt": "1627617632190"
        }
    ]
}

Python
import os
import time
import hmac
import hashlib
import base64
import requests
from dotenv import load_dotenv

load_dotenv()

def fetch_funding_data(market_code, limit=100, start_time=None, end_time=None):
    api_key = os.getenv('API_KEY')
    secret_key = os.getenv('API_SECRET').encode('utf-8')
    ts = time.strftime('%Y-%m-%dT%H:%M:%S', time.gmtime())
    nonce = str(int(time.time() * 1000))
    method = "/v3/funding"
    api_url = "api.ox.fun"
    
    query_string = f"marketCode={market_code}&limit={limit}&startTime={start_time}&endTime={end_time}"
    msg_string = f"{ts}\n{nonce}\nGET\n{api_url}\n{method}\n{query_string}"
    
    sign = base64.b64encode(hmac.new(secret_key, msg_string.encode('utf-8'), hashlib.sha256).digest()).decode('utf-8')
    
    headers = {
        'Content-Type': 'application/json',
        'AccessKey': api_key,
        'Timestamp': ts,
        'Signature': sign,
        'Nonce': nonce
    }
    
    try:
        response = requests.get(f"https://{api_url}{method}?{query_string}", headers=headers)
        response.raise_for_status()
        return response.json()
    except requests.exceptions.RequestException as error:
        print('Error fetching funding data:', error)

# Example usage
# start time and end time are in milliseconds and must be within 7 days of each other
start_time = int(time.time() * 1000) - 24 * 60 * 60 * 1000  # 24 hours ago in milliseconds
end_time = int(time.time() * 1000)
response = fetch_funding_data('BTC-USD-SWAP-LIN', 100, start_time, end_time)
print(response)
Javascript
require('dotenv').config();
const axios = require('axios');
const CryptoJS = require("crypto-js");

async function fetchFundingData(marketCode, limit = 100, startTime, endTime) {
  const apiKey = process.env.API_KEY;
  const secretKey = process.env.API_SECRET;
  const ts = new Date().toISOString();
  const nonce = Math.random().toString(36).substring(2);
  const method = "/v3/funding";
  const queryString = `marketCode=${marketCode}&limit=${limit}&startTime=${startTime}&endTime=${endTime}`;
  const msgString = `${ts}\n${nonce}\nGET\napi.ox.fun\n${method}\n${queryString}`;
  const sign = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(msgString, secretKey));

  try {
    const response = await axios.get(`https://api.ox.fun${method}?${queryString}`, {
      headers: {
        'Content-Type': 'application/json',
        'AccessKey': apiKey,
        'Timestamp': ts,
        'Signature': sign,
        'Nonce': nonce
      }
    });

    if (response.data.success) {
      return response;
    } else {
      console.error('Failed to fetch funding data');
    }
  } catch (error) {
    console.error('Error fetching funding data:', error.response ? error.response.data : error.message);
  }
}

// Example usage
// start time and end time are in milliseconds and must be within 7 days of each other
(async () => {
  const startTime = Date.now() - 24 * 60 * 60 * 1000; // 24 hours in milliseconds
  const endTime = Date.now();
  const response = await fetchFundingData('BTC-USD-SWAP-LIN', 100, startTime, endTime);
  console.log(response);
})();

Request Parameters
Type
Required
Description

marketCode

STRING

NO

e.g. BTC-oUSD-SWAP-LIN

limit

LONG

NO

default is 200, max is 500

startTime

LONG

NO

Millisecond timestamp. Default 24 hours ago. startTime and endTime must be within 7 days of each other. startTime is INCLUSIVE

endTime

LONG

NO

Millisecond timestamp. Default time now. startTime and endTime must be within 7 days of each other. endTime is EXCLUSIVE

Response Fields
Type
Description

id

STRING

A unique ID

marketCode

STRING

Market code

payment

STRING

Funding payment

fundingRate

STRING

Funding rate

position

STRING

Position

indexPrice

STRING

index price

createdAt

STRING

Timestamp of this response

PreviousREST API V3NextDeposits & Withdrawals - Private

Last updated 3 months ago

🔌