NAV
javascript python

Change Log

25-10-2024

  1. New Endpoints to get wallet balance:
    • Get futures wallet details(GET /v1/wallet/futures-wallet/details)
    • Get funding wallet details(GET /v1/wallet/funding-wallet/details)

  2. New Endpoints for close all positions and open orders:
    • Cancel all the orders(DELETE /v1/order/cancel-all-orders)
    • Close all the positions(DELETE /v1/positions/close-all-positions)

  3. New update preference endpoint:
    • To Update leverage and margin-mode(POST /v1/exchange/update/preference)


17-09-2024

  1. Additional authentication method with private web socket using listen key.
  2. New Endpoints for listen key
    • Create new listen key for web-socket connection (POST /v1/retail/listen-key)
    • Update expiry time for listen key (PUT /v1/retail/listen-key)
    • Delete listen key (DELETE /v1/retail/listen-key)
  3. Endpoints for CRUD Operations on api-key which are typically done through UI
    • Create a new api-key (POST /v1/retail/create-api-key)
    • Get all api-keys for user (GET /v1/retail/all-api-keys)
    • Delete api-key for user (DELETE /v1/retail/delete-api-key)
    • Update api-key trading permissions (POST /v1/retail/update-api-key-permissions)
    • Whitelist IPs for api-key (POST /v1/retail/add-allowed-ips)
    • Remove whitelisted IPs for api-key (POST /v1/retail/remove-allowed-ips)

17-07-2024

  1. Added Enum Value GST_ON_FUNDING_FEE in TransactionType
  2. Exchange Info
    • Added optional query param market
    • Added markets, tags, assetPrecisions, conversionRates in the response
    • For each contract, from the response:
      • Removed: marginAsset, maintMarginPercent
      • Added: market, marginAssetsSupported, fundingFeeInterval
  3. Open Orders, Order History, Linked Orders
    • Added baseAsset, quoteAsset in response
    • Added lockedMarginInMarginAsset, lockedMargin, stopPrice, marginAsset, leveragedQty in Order History response
  4. Add Margin/ Reduce Margin
    • Added asset in response
  5. Get order using client order ID, Get order using ref ID
    • Added lockedMarginInMarginAsset(optional), baseAsset, quoteAsset, marginAsset in response
  6. Place Order
    • Added optional field marginAsset in body
    • Added lockedMarginInMarginAsset, baseAsset, quoteAsset, marginAsset in response
  7. Transaction History, Get Transaction using ID
    • Added baseAsset, quoteAsset in response
  8. Trade History, Get Trade using ID
    • Added baseAsset, quoteAsset , marginAsset, feeInMarginAsset(optional), realizedProfitInMarginAsset(optional) in response
  9. Get Positions, Get Position using position id
    • Added baseAsset, quoteAsset , marginAsset, marginInMarginAsset(optional), realizedProfitInMarginAsset(optional) in response
  10. Web Socket Updates
    • New Events Added:
      • Market Info ( marketInfo)
      • Mark Price Stream for All market ( markPriceArr)
      • All Market Tickers Streams( tickerArr)
    • Added new fields in the Response of following events
      • Order Events : marginAsset, market , baseAsset, quoteAsset
      • Position Events:market, marginAsset, marginConversionRate, marginSettlementRate, marginInMarginAsset, realizedProfitInMarginAsset
      • Trade Events: feeInMarginAsset

9-07-2024

  1. Pagination update of following APIs: orderHistory, tradeHistory, transactionHistory, openOrders, positions
    • Removed timestamp query param.
    • Added optional query params namely:
      • startTimestamp (lower bound)
      • endTimestamp (upper bound)
      • sortOrder(asc or desc)
    • Response: nextTimestamp which is used in the next paginated API call.
    • Examples added in the API descriptions section in the doc.
  2. New Endpoint
    • Margin History ( GET /v1/order/fetch-margin-history)

19-06-2024

  1. Updated Pagination of following APIs: orderHistory, tradeHistory, transactionHistory, openOrders
    • Pagination changed from page basis to timestamp basis.
    • Introduced timestamp basis pagination in positions API.
    • Response gives a field nextTimestamp, which is used for next API call.

06-06-2024

  1. New Endpoints added
    • Get Depth Update( GET /v1/market/depth/:contractPair)
    • Get Aggregate trade update ( GET /v1/market/aggTrade/:contractPair)
    • Get order details using ref ID ( GET /v1/order/ref-id)
    • Get user id and account ID using ref ID ( GET /v1/integration/user)
    • Get fiat order details using reference ID ( GET /v1/integration/fiat-order-details)
    • Get 24hr ticker update ( GET /v1/market/ticker24Hr/:contractPair)
    • Get trade history based on trade ID ( GET /v1/user-data/trade-history/{id})
    • Get transaction history based on transaction ID ( GET /v1/user-data/transaction-history/{id})
  2. Updated Endpoints
    • Two new optional query params( tradeId and positionId) added in ( GET /v1/user-data/transaction-history).
    • Updates in body of ( POST /v1/integration/event-replay)
  3. Added optional field refId in the responses of place order, get order details using client order id, order history, open orders, linked orders endpoints.
  4. Secure Web Socket Updates: a. In each event, eventTime will be in nanoseconds and type will be string.

28-05-2024

  1. New Endpoints
    • Get Order ( GET /v1/order?clientOrderId=abc)
    • Get Position ( GET /v1/positions?positionId=abc)
    • Event Replay ( POST /v1/integration/event-replay): This is just endpoint, we're still deploying the changes.

  2. Secure Web Socket Updates:
    a. Added new event for Funding Fee named fundingFee

20-05-2024

  1. Added lockedMargin field in the place-order API response

10-05-2024

  1. New Endpoint: INR Deposit and Withdraw History ( GET /v1/integration/deposit-withdraw-history)
  2. New enums: PaymentType, PaymentStatus
  3. Added optional query params for pagination for the following endpoints
    • Order History
    • Open Orders
    • Transaction History
    • Trade History
  4. Updated public key sharing under Authenticated endpoints.
  5. Secure Web Socket Updates:
    • Added eventTime field in all the events.
    • Updated response of order events. In case of orderPartiallyFilled event, use filledAmount instead of cumQty for total filled quantity. c. New Events:
    • Margin Call (marginCallAlert)
    • Liquidation ( liquidationAlert)
    • Trade stream (newTrade)

Introduction

Pi42 offers a suite of public-facing APIs designed to facilitate integration with various applications and systems, particularly within the domains it specializes in. Here is a high-level introduction to the key features and functionalities of Pi42's public-facing APIs:

  1. Authentication and Authorization:

    • OAuth 2.0 Support: Pi42 APIs utilize OAuth 2.0 for secure authentication and authorization, ensuring that only authorized users and applications can access the data.
    • API Keys: For simpler integrations, Pi42 also supports API keys, allowing developers to authenticate their requests with a unique key.

  2. Data Access and Management:

    • Data Retrieval: APIs provide endpoints for retrieving various types of data, such as user information, transaction history, and analytics reports.
    • Data Insertion and Updates: Developers can use the APIs to insert new data or update existing records in the Pi42 system.
    • Search and Filtering: Advanced search and filtering capabilities allow developers to query the data efficiently, using parameters like date ranges, status filters, and more.

  3. Analytics and Reporting:

    • Real-time Analytics: Access real-time analytics data, enabling applications to display up-to-the-minute information.
    • Custom Reports: APIs allow the generation of custom reports based on specified criteria, providing flexibility in data analysis.

  4. Developer Resources:

    • Comprehensive Documentation: Detailed API documentation, including endpoint descriptions, request and response formats, error codes, and usage examples.

  5. Compliance and Security:

    • Data Encryption: All data transmitted via the APIs is encrypted to ensure security and privacy.
    • Compliance: Pi42 APIs adhere to industry standards and regulations, such as GDPR making them suitable for use in regulated industries like finance.

Getting Started with Pi42 APIs

APIs provided by Pi42 classifications ensure that only authorized users can access sensitive functionalities, while still allowing open access to non-sensitive information or system statuses.

Authenticated APIs

The Authenticated endpoints require users to provide valid credentials before access is granted. These endpoints are secured, ensuring that only authorized users can interact with sensitive data or perform privileged operations. Authentication typically involves the use of tokens, API keys, or OAuth, which must be included in the request header. These endpoints are designed for operations that involve personal data, secure transactions, or actions that could impact the system's state or other users.

APIs that require trade permissions:

/v1/order/place-order
/v1/order/delete-order
/v1/order/add-margin
/v1/order/reduce-margin
/v1/exchange/update/leverage
/v1/order/cancel-all-orders
/v1/positions/close-all-positions

Public APIs

The Public endpoints are accessible without any authentication, allowing open access to certain resources or information. These endpoints are designed to handle requests that do not require user identification or secure access, such as fetching general information, retrieving publicly available data, or providing status updates. While public, these endpoints are still subject to rate limiting and monitoring to prevent abuse or misuse of the system.

Endpoints which DO NOT require api-key and signature authentication:

/v1/market/klines
/v1/market/depth
/v1/market/aggTrade
/v1/market/ticker24Hr

To begin using Pi42 Authenticated APIs, follow these steps:

  1. API Key Creation
    Users can create an API key, which will be associated with a secret. The secret will be shown only once during the creation process.

  2. Signature Generation

    • For each authenticated request, users need to generate a signature using their secret key.
    • For GET requests: The data to be signed is the query string, which includes the timestamp and any other query parameters.
    • For POST/PUT/DELETE requests: The data to be signed is the body of the request, which includes the timestamp, and any other fields.
    • The signature is generated by applying HMAC-SHA256 to the data (query string or body) using the user's secret key.
    • The generated signature is sent in the request headers along with the API key.

getRequest Function

The getRequest function sends a GET request to an API endpoint, handling both market and non-market endpoints differently. It adds a timestamp to the parameters for request uniqueness, generates a signature for authentication, and processes the response.

Sends a GET request to the specified endpoint with the given parameters:

/**
 * Sends a GET request to the specified endpoint with the given parameters.
 *
 * @param {string} endpoint - The API endpoint to send the request to.
 * @param {Object} [params={}] - The query parameters to include in the request.
 * @returns {Promise<Object>} - The response data from the API.
 */
async function getRequest(endpoint, params = {}) {
    // Add a timestamp to the parameters for request uniqueness
    const timestamp = Date.now().toString();
    params.timestamp = timestamp;

    // Determine if the endpoint is a market endpoint
    const isMarketEndpoint = endpoint.startsWith("/v1/market");
    let url = "";
    const queryString = new URLSearchParams(params).toString();

    // Construct the URL based on the endpoint type
    if (isMarketEndpoint) {
        url = `${publicBaseUrl}${endpoint}`;
    } else {
        url = `${baseUrl}${endpoint}?${queryString}`;
    }

    // Generate a signature for the request
    const signature = crypto
      .createHmac("sha256", apiSecret)
      .update(queryString)
      .digest("hex");

    try {
        // Send the GET request
        const response = await axios.get(
            url,
            !isMarketEndpoint ? {
                headers: {
                    "api-key": apiKey,
                    "signature": signature,
                },
            } : {}
        );
        // Log and return the response data
        console.log("Response:", response.data);
        return response.data;
    } catch (error) {
        // Handle and log any errors that occur during the request
        console.error(
            "Error:",
            error.response ? error.response.data : error.message
        );
    }
}

Response

Returns: A Promise that resolves to the response data from the API.

Error Handling: If an error occurs during the request, it logs the error message or response data to the console.

postRequest Function

The function sends POST requests to an API endpoint, handling both authenticated and public requests based on the endpoint URL.

// Generic POST request function
async function postRequest(endpoint, params = {}) {
  const timestamp = Date.now().toString();
  const isMarketEndpoint = endpoint.startsWith("/v1/market");
  const baseUrlToUse = isMarketEndpoint ? publicBaseUrl : baseUrl;
  const url = `${baseUrlToUse}${endpoint}`;

  if (!isMarketEndpoint) {
    params.timestamp = timestamp;
  }

  const signature = crypto
    .createHmac("sha256", apiSecret)
    .update(JSON.stringify(params))
    .digest("hex");

  try {
    const response = await axios.post(
      url,
      params,
      isMarketEndpoint
        ? {}
        : {
            headers: {
              "api-key": apiKey,
              signature: signature,
            },
          }
    );
    console.log("Response:", response.data);
    return response.data;
  } catch (error) {
    console.error(
      "Error:",
      error.response ? error.response.data : error.message
    );
    throw error; // Optional: re-throw the error if you want to handle it further up the call stack
  }
}

Response

console.log("Response:", response.data);
Logs the response data to the console.

return response.data;
Returns the response data for further use.

putRequest Function

This function, putRequest, is an asynchronous JavaScript function designed to send a signed PUT HTTP request to a specified API endpoint. Here's a breakdown of its components and behavior:

const crypto = require('crypto');
const axios = require('axios');

async function putRequest(endpoint, params = {}) {
  const timestamp = Date.now().toString();
  params.timestamp = timestamp;

  const signature = crypto
    .createHmac("sha256", apiSecret)
    .update(JSON.stringify(params))
    .digest("hex");

  const url = `${baseUrl}${endpoint}`;

  try {
    const response = await axios.put(url, params, {
      headers: {
        "api-key": apiKey,
        "signature": signature,
      },
    });

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

  } catch (error) {
    console.error(
      "Error:",
      error.response ? error.response.data : error.message
    );
  }
}

Response

If the request is successful, the response data is logged to the console and returned by the function.

deleteRequest Function

This deleteRequest function is an asynchronous JavaScript function designed to send a signed DELETE HTTP request to a specified API endpoint. Below is a detailed explanation of its components and behavior:

const crypto = require('crypto');
const axios = require('axios');

async function deleteRequest(endpoint, params = {}) {
  // Generate a timestamp and add it to the params
  const timestamp = Date.now().toString();
  params.timestamp = timestamp;

  // Create a cryptographic signature using HMAC with SHA-256
  const signature = crypto
    .createHmac("sha256", apiSecret)
    .update(JSON.stringify(params))
    .digest("hex");

  // Construct the full request URL
  const url = `${baseUrl}${endpoint}`;

  try {
    // Send the DELETE request using axios
    const response = await axios.delete(url, {
      headers: {
        "api-key": apiKey,
        "signature": signature,
      },
      data: params,
    });

    // Log and return the response data if the request is successful
    console.log("Response:", response.data);
    return response.data;

  } catch (error) {
    // Handle and log any errors that occur during the request
    console.error(
      "Error:",
      error.response ? error.response.data : error.message
    );
  }
}

API Rate Limits

Rate limits are mechanisms used to control the frequency of requests that can be made to an API. These rate limits are essential for maintaining optimal performance and avoiding server overloads, ensuring a smooth and reliable user experience across all API interactions.

Different endpoints may have varying rate limits depending on their purpose and the resources they consume.

Endpoint Interval Limit
v1/order/place-order 1 second (1s) 20 requests
v1/order/delete-order 1 minute (1m) 30 requests
All other endpoints 1 minute (1m) 60 requests

Orders

Place an Order

def generate_signature(api_secret, data_to_sign):
    return hmac.new(api_secret.encode('utf-8'), data_to_sign.encode('utf-8'), hashlib.sha256).hexdigest()

POST /v1/order/place-order

Place an order (either a market order or a limit order) on Pi42's trading platform. It allows users to submit an order to buy or sell a specific asset.

async function placeOrder(orderType, quantity = 38, price = null) {
  // Validate orderType
  if (!["MARKET", "LIMIT", "STOP_MARKET", "STOP_LIMIT"].includes(orderType)) {
    throw new Error("Invalid order type. Must be MARKET, LIMIT, STOP_MARKET or STOP_LIMIT.");
  }

  // Validate quantity
  if (quantity <= 0) {
    throw new Error("Quantity must be greater than 0.");
  }

  const params = {
    placeType: "ORDER_FORM",
    quantity: quantity, // Dynamically set quantity
    side: "BUY",
    symbol: "GRTINR",
    reduceOnly: false,
    marginAsset: "INR",
    type: orderType, // Set the order type dynamically
  };

  // Add additional parameters if the order is a LIMIT order
  if (orderType === "LIMIT") {
    if (price === null || price <= 0) {
      throw new Error("Price must be specified and greater than 0 for LIMIT orders.");
    }
    params.price = price; // Dynamically set price for LIMIT orders
  }

  const endpoint = "/v1/order/place-order";

  try {
    // Call the postRequest function
    const response = await postRequest(endpoint, params);
    return response;
  } catch (error) {
    console.error("Failed to place order:", error);
    throw error;
  }
}

// Example usage for market order
placeOrder("MARKET");

// Example usage for limit order with price
placeOrder("LIMIT", 38, 11.9);
def place_order():
    # Generate the current timestamp in milliseconds
    timestamp = str(int(time.time() * 1000))

    # Define the order parameters
    params = {
        'timestamp': timestamp,        # Current timestamp in milliseconds
        'placeType': 'ORDER_FORM',     # Type of order placement, e.g., 'ORDER_FORM'
        'quantity': 0.002,             # Quantity of the asset to trade
        'side': 'BUY',                 # Order side, either 'BUY' or 'SELL'
        'symbol': 'BTCUSDT',           # Trading pair, e.g., Bitcoin to USDT
        'type': 'MARKET',              # Order type, either 'MARKET' or 'LIMIT'
        'reduceOnly': False,           # Whether to reduce an existing position only
        'marginAsset': 'INR',          # The asset used as margin (INR in this case)
        'deviceType': 'WEB',           # Device type (e.g., WEB, MOBILE)
        'userCategory': 'EXTERNAL',    # User category (e.g., EXTERNAL, INTERNAL)
        'price': 50000,                # Price for the limit order (included here but irrelevant for market orders)
    }

    # Convert the parameters to a JSON string to sign
    data_to_sign = json.dumps(params, separators=(',', ':'))

    # Generate the signature for authentication
    signature = generate_signature(api_secret, data_to_sign)

    # Define the headers including the API key and the signature
    headers = {
        'api-key': api_key,
        'signature': signature,
    }

    try:
        # Send the POST request to place the order
        response = requests.post(f'{base_url}/v1/order/place-order', json=params, headers=headers)

        # Raise an HTTPError if the response status is 4xx or 5xx
        response.raise_for_status()

        # Parse the JSON response data
        response_data = response.json()

        # Print the success message with the order details
        print('Order placed successfully:', json.dumps(response_data, indent=4))

    except requests.exceptions.HTTPError as err:
        # Handle HTTP errors specifically
        print(f"Error: {err.response.text if err.response else err}")

    except Exception as e:
        # Handle any other unexpected errors
        print(f"An unexpected error occurred: {str(e)}")
Parameter Type Required Description
quantity number No The amount of the asset to be ordered. Specify the desired quantity.
price number Conditional The price at which to place the LIMIT/STOP_LIMIT order. Must be specified if orderType is "LIMIT" or "STOP_LIMIT".
placeType string Yes Fixed value "ORDER_FORM". Indicates the type of order placement.
side string Yes The side of the order, which is "BUY" in this case.
symbol string Yes The trading pair symbol, for example, "GRTINR".
reduceOnly boolean No Indicates whether the order should only reduce the position. Default is false.
marginAsset string Yes The asset used for margin, such as "INR".
orderType string Yes The type of the order. It can be MARKET, LIMIT, STOP_MARKET or STOP_LIMIT.
takeProfitPrice number No Price at which take profit order should be executed.
stopLossPrice number No Price at which stop loss order should be executed.
stopPrice number No Compulsory for STOP_MARKET and STOP_LIMIT orders

Response

The response parameters are described below:

# Response
{
    "clientOrderId": "19db8caf3cd3e5a08cfa-6895-ext",
    "time": "2024-09-13T08:19:18.029Z",
    "symbol": "BTCUSDT",
    "contractType": "PERPETUAL",
    "type": "MARKET",
    "side": "BUY",
    "price": 58002,
    "orderAmount": 0.003,
    "filledAmount": 0,
    "availableBalance": 8564.64,
    "linkId": "19db8caf3cd3e5a08cfa-6895-ext",
    "linkType": "ORDER",
    "subType": "PRIMARY",
    "placeType": "ORDER_FORM",
    "lockedMargin": 19.5274,
    "baseAsset": "BTC",
    "quoteAsset": "USDT",
    "marginAsset": "INR",
    "lockedMarginInMarginAsset": 1698.88
}
Parameter Description
clientOrderId Unique identifier for the client order (19db8caf3cd3e5a08cfa-6895-ext).
time Timestamp when the order was placed (2024-09-13T08:19:18.029Z).
symbol The trading pair for the order (BTCUSDT), indicating Bitcoin (BTC) traded against USDT (Tether).
contractType The type of contract for the order (PERPETUAL), indicating a perpetual futures contract.
type The type of order (MARKET), indicating a market order.
side The side of the order (BUY).
price The price at which the order is to be executed (58002 USDT).
orderAmount The amount of the order (0.003 BTC).
filledAmount The amount of the order that has been filled (0, indicating no amount has been filled yet).
availableBalance The available balance for the order (8564.64 INR).
linkId Link identifier associated with the order (19db8caf3cd3e5a08cfa-6895-ext).
linkType The type of link for the order (ORDER).
subType Subtype of the order (PRIMARY).
placeType The method used to place the order (ORDER_FORM).
lockedMargin The amount of margin locked for the order (19.5274 INR).
baseAsset The base asset being traded (BTC).
quoteAsset The currency used for the transaction (USDT).
marginAsset The asset used for margin (INR).
lockedMarginInMarginAsset The amount of margin locked in the margin asset (1698.88 INR).

Add Margin

POST /v1/order/add-margin

Add margin to a specific position. It requires a unique position ID and the amount of margin to be added. This operation helps in increasing the margin available for a given position, which can be used for trading or managing positions.

async function addMargin() {
    // Define the API endpoint for adding margin
    const endpoint = "/v1/order/add-margin";

    // Define the fixed values for positionId and amount
    const positionId = "18c6c979-b089-4e67-b627-4c2072d0d5cb";  // Unique identifier for the position
    const amount = 1;  // The amount of margin to be added

    // Prepare request payload
    const params = {
        positionId: positionId,  // ID of the position to which margin is being added
        amount: amount,          // Amount of margin to add
    };

    // Call the postRequest function to send the POST request to the API
    return await postRequest(endpoint, params);
}
def add_margin():
    position_id = input("Enter the positionId: ")
    amount_input = input("Enter the amount: ")

    add_margin_url = "https://fapi.pi42.com/v1/order/add-margin"

    try:
        amount = int(amount_input)
    except ValueError:
        amount = float(amount_input)

    timestamp = str(int(time.time() * 1000))

    params = {
        'positionId': position_id,
        'amount': amount,
        'timestamp': timestamp
    }

    data_to_sign = json.dumps(params, separators=(',', ':'))
    signature = generate_signature(api_secret, data_to_sign)

    headers = {
        'api-key': api_key,
        'Content-Type': 'application/json',
        'signature': signature,
    }

    try:
        response = requests.post(add_margin_url, json=params, headers=headers)
        response.raise_for_status()
        response_data = response.json()
        print('Margin added successfully:', json.dumps(response_data, indent=4))

    except requests.exceptions.HTTPError as err:
        print(f"Failed {response.status_code}: {response.text}")
    except Exception as e:
        print(f"An unexpected error occurred: {str(e)}")
Parameter Type Required Description
positionId string Yes Unique identifier for the position to which margin is being added
amount number Yes Amount of margin to be added to the specified position

Response

The response parameters are described below:

# Response
{
  "lockedBalance": 870,
  "withdrawableBalance": 9393.52,
  "asset": "INR",
  "message": "Margin added successfully"
}
Parameter Description
lockedBalance The amount of balance that is locked and cannot be withdrawn (870 INR).
withdrawableBalance The amount of balance available for withdrawal (9393.52 INR).
asset The asset or currency being used (INR).
message A confirmation message indicating that margin was added successfully.

Reduce Margin

POST /v1/order/reduce-margin

Reduce the margin on an existing trading position.

async function reduceMargin() {
    // Define the API endpoint for reducing margin
    const endpoint = "/v1/order/reduce-margin";

    // Define the fixed values for positionId and amount
    const positionId = "18c6c979-b089-4e67-b627-4c2072d0d5cb";  // Unique identifier for the position
    const amount = 1;  // The amount of margin to be reduced

    // Prepare request payload
    const params = {
        positionId: positionId,  // ID of the position from which margin is being reduced
        amount: amount,          // Amount of margin to reduce
    };

    // Call the postRequest function to send the POST request to the API
    return await postRequest(endpoint, params);
}
def reduce_margin():
    # Collect position ID and amount to reduce from user input
    position_id = input("Enter the positionId: ")
    amountInput = input("Enter the amount to reduce: ")

    try:
        # Convert input to integer or float as necessary
        amount = int(amountInput)
    except ValueError:
        amount = float(amountInput)

    # Generate current timestamp in milliseconds
    timestamp = str(int(time.time() * 1000))

    # Prepare the request payload (JSON)
    params = {
        'positionId': position_id,
        'amount': amount,
        'timestamp': timestamp
    }

    # Convert the payload to a JSON string for signature
    data_to_sign = json.dumps(params, separators=(',', ':'))

    # Generate the signature using a helper function
    signature = generate_signature(api_secret, data_to_sign)

    # Set the headers for the POST request
    headers = {
        'api-key': api_key,
        'Content-Type': 'application/json',
        'signature': signature
    }

    # Construct the full API endpoint URL
    reduce_margin_url = f"{base_url}/v1/order/reduce-margin"

    try:
        # Send the POST request to reduce margin
        response = requests.post(reduce_margin_url, json=params, headers=headers)
        response.raise_for_status()  # Raises an error for HTTP responses with 4xx/5xx status codes
        response_data = response.json()
        print('Margin reduced successfully:', json.dumps(response_data, indent=4))
    except requests.exceptions.HTTPError as err:
        print(f"Error: {err.response.text if err.response else err}")
    except Exception as e:
        print(f"An unexpected error occurred: {str(e)}")
Parameter Type Required Description
positionId string Yes Unique identifier for the position from which margin is being reduced
amount number Yes Amount of margin to reduce from the specified position

Response

The JSON body returned in the response is as follows:


# Response
{
    "lockedBalance": 870,
    "withdrawableBalance": 9393.52,
    "asset": "INR",
    "message": "Margin reduced successfully"
}
Parameter Description
lockedBalance The amount of balance that is locked and cannot be withdrawn (870 INR).
withdrawableBalance The amount of balance available for withdrawal (9393.52 INR).
asset The asset or currency being used (INR).
message A confirmation message indicating that margin was reduced successfully.

Get Open Orders

GET /v1/order/open-orders

Retrieves the open orders for a given account. It supports filtering results based on optional parameters such as page size, sorting order, and timestamps. The symbol parameter can be used to filter the results to a specific trading pair.
This endpoint is useful for fetching the current active orders and managing them accordingly.

def get_open_orders():
# Generate the current timestamp
    timestamp = str(int(time.time() * 1000))

# Prepare parameters with the current timestamp
    params = f"timestamp={timestamp}"

# Generate the signature using the current timestamp
    signature = generate_signature(api_secret, params)

# Prepare headers
    headers = {
    'api-key': api_key,
    'signature': signature,
    }
    open_orders_url = f"{base_url}/v1/order/open-orders"
    try:

# Send GET request to fetch open orders with the timestamp parameter
    response = requests.get(open_orders_url, headers=headers, params={'timestamp': timestamp})
    response.raise_for_status() # Raises an error for bad HTTP responses
    response_data = response.json()
    print('Open orders fetched successfully:', json.dumps(response_data, indent=4))
    except requests.exceptions.HTTPError as err:
    print(f"Failed {response.status_code}: {response.text}")
    except Exception as e:
    print(f"An unexpected error occurred: {str(e)}")
async function getOpenOrders() {
const pageSize = 100;
const sortOrder = "desc";
const startTimestamp = "1696425435000";
const endTimestamp = "1725451568979";
const symbol = "BTCUSDT";
const params = {
 // Optional Params
    pageSize: pageSize.toString(),
    sortOrder: sortOrder,
    startTimestamp: startTimestamp,
    endTimestamp: endTimestamp,
    symbol: symbol,
    };

const endpoint = "/v1/order/open-orders"; // Your endpoint for fetching open orders

// Call the postRequest function
return await getRequest(endpoint, params);
}
Parameter Type Required Description
pageSize string No The number of results to return per page
sortOrder string No The sorting order for the results (e.g., "asc" or "desc")
startTimestamp string No The start timestamp (in milliseconds) for filtering open orders
endTimestamp string No The end timestamp (in milliseconds) for filtering open orders
symbol string No The trading pair symbol to filter the orders (e.g., BTCUSDT)

Response

The response parameters are described below:

[
  {
    "clientOrderId": "ccef6a84a5cf6a463353-6238-ext",
    "time": "2024-09-13T07:57:15.305Z",
    "symbol": "BTCINR",
    "contractType": "PERPETUAL",
    "type": "MARKET",
    "side": "BUY",
    "price": 5170418,
    "orderAmount": 0.002,
    "filledAmount": 0,
    "linkId": "ccef6a84a5cf6a463353-6238-ext",
    "linkType": "ORDER",
    "subType": "PRIMARY",
    "placeType": "ORDER_FORM",
    "baseAsset": "BTC",
    "quoteAsset": "INR"
  }
]
Parameter Description
clientOrderId Unique identifier for the client's order (ccef6a84a5cf6a463353-6238-ext).
time Timestamp when the order was placed (2024-09-13T07:57:15.305Z).
symbol Trading pair involved (BTCINR), indicating Bitcoin (BTC) traded against Indian Rupees (INR).
contractType Type of contract (PERPETUAL), suggests a perpetual futures contract.
type The order type (MARKET), meaning the order will be executed immediately at the current market price.
side Indicates whether the order is to buy or sell (BUY).
price The price per unit of Bitcoin at the time the order was placed (5170418 INR per BTC).
orderAmount The amount of Bitcoin to be purchased (0.002 BTC).
filledAmount Amount of the order that has been filled so far (0, indicating it hasn't been executed yet).
linkId Additional reference that ties this order to a broader system or linked entities (ccef6a84a5cf6a463353-6238-ext).
linkType The type of link (ORDER).
subType Order classification (PRIMARY), indicating the main order type.
placeType Describes where the order was placed from (ORDER_FORM).
baseAsset The asset being bought (Bitcoin).
quoteAsset The currency used for the transaction (INR).

Get Order History

GET /v1/order/order-history

Provides historical order data for a given account.

It supports optional filtering by page size, sorting order, and timestamps to narrow down the results. The symbol parameter allows filtering the results to a specific trading pair.

This endpoint is helpful for reviewing past orders and analyzing historical trading activity.

# Function to fetch and display order history
def order_history():
timestamp = str(int(time.time() * 1000))
order_history_url = "https://fapi.pi42.com/v1/order/order-history"
params = {
'sortOrder': 'desc',
'pageSize': 100,
'timestamp': timestamp
 }

query_string = f"sortOrder={params['sortOrder']}&pageSize={params['pageSize']}&timestamp=
{params['timestamp']}"

signature = generate_signature(api_secret, query_string)

headers = {
'api-key': api_key,
'signature': signature,
}

try:
response = requests.get(f"{order_history_url}?{query_string}", headers=headers)
response.raise_for_status()
response_data = response.json()
print('Order history fetched successfully:', json.dumps(response_data, indent=4))
except requests.exceptions.HTTPError as err:
print(f"Failed {response.status_code}: {response.text}")
//Get Order History
async function getOrderHistory() {
  const pageSize = 100;
  const sortOrder = "desc";
  const startTimestamp = "1696425435000";
  const endTimestamp = "1725451568979";
  const symbol = "BTCUSDT";
  const params = {
    // Optional Params
    pageSize: pageSize.toString(),
    sortOrder: sortOrder,
    startTimestamp: startTimestamp,
    endTimestamp: endTimestamp,
    symbol: symbol,
  };
  const endpoint = "/v1/order/order-history"; // Your endpoint for fetching order history
  // Call the postRequest function
  return await getRequest(endpoint, params);
}
Parameter Type Required Description
pageSize string No The number of results to return per page
sortOrder string No The sorting order for the results (e.g., "asc" or "desc")
startTimestamp string No The start timestamp (in milliseconds) for filtering order history
endTimestamp string No The end timestamp (in milliseconds) for filtering order history
symbol string No The trading pair symbol to filter the orders (e.g., BTCUSDT)

Response

The details of the JSON object returned in the response body are as follows:

[
  {
    "clientOrderId": "c707985129f41a13ab40-6238-ext",
    "updatedAt": "2024-09-13T10:48:57.630Z",
    "symbol": "BTCINR",
    "type": "MARKET",
    "isIsolated": true,
    "side": "SELL",
    "price": "5182995",
    "avgPrice": "5182656",
    "origQty": "10365.31",
    "cumQty": "0.002",
    "executedQty": "0.002",
    "reduceOnly": false,
    "status": "FILLED",
    "leverage": 25,
    "subType": "PRIMARY",
    "stopPrice": null,
    "lockedMargin": 0,
    "lockedMarginInMarginAsset": 0,
    "marginAsset": "INR",
    "contractType": "PERPETUAL",
    "iconUrl": "https://storage.googleapis.com/pi42-dev-static/contract-icons/btc.png",
    "quoteAsset": "INR",
    "baseAsset": "BTC",
    "leveragedQty": 0.002
  }
]
Parameter Description
clientOrderId Unique identifier for the client's order (c707985129f41a13ab40-6238-ext).
updatedAt The timestamp when the order was last updated (2024-09-13T10:48:57.630Z).
symbol The trading pair involved (BTCINR), indicating Bitcoin (BTC) traded against Indian Rupees (INR).
type The order type (MARKET), meaning the order was executed at the current market price.
isIsolated Indicates whether the order is isolated (true), meaning it's an isolated margin trade.
side Indicates whether the order is to buy or sell (SELL).
price The price per unit of Bitcoin at the time the order was placed (5182995 INR per BTC).
avgPrice The average price at which the order was executed (5182656 INR per BTC).
origQty The original quantity in INR before conversion to BTC (10365.31 INR).
cumQty The cumulative amount of Bitcoin executed so far (0.002 BTC).
executedQty The total executed quantity of the order (0.002 BTC).
reduceOnly A flag indicating if the order is only to reduce an existing position (false).
status The current status of the order (FILLED), meaning the order is completely executed.
leverage The leverage applied to the trade (25x).
subType The order classification (PRIMARY), indicating the main order type.
stopPrice The stop price associated with the order (null), as this is not a stop order.
lockedMargin The amount of margin locked in INR (0 INR).
lockedMarginInMarginAsset The amount of margin locked in the margin asset (0 INR).
marginAsset The asset used for margin (INR).
contractType The type of contract (PERPETUAL), indicating a perpetual futures contract.
iconUrl The URL of the contract icon (BTC Icon).
quoteAsset The currency used for the transaction (INR).
baseAsset The asset being traded (Bitcoin).
leveragedQty The quantity of Bitcoin being traded with leverage (0.002 BTC).

Get Linked Orders

GET /v1/order/linked-orders

Retrieves orders that are linked by a specific link ID. It is used to fetch all orders associated with a given link ID, which can help in tracking related orders or managing linked order groups.

# Function to fetch linked orders based on linkId
def linked_orders():
link_id = input("Enter the Link Id: ")
timestamp = str(int(time.time() * 1000))
linked_orders_url = "https://fapi.pi42.com/v1/order/linked-orders"

url = f"{linked_orders_url}/{link_id}"

params = {
'timestamp': timestamp
}
query_string = f"timestamp={params['timestamp']}"

signature = generate_signature(api_secret, query_string)

headers = {
'api-key': api_key,
'signature': signature,
'accept': '*/*'
 }
try:
response = requests.get(f"{url}?{query_string}", headers=headers)
response.raise_for_status()
response_data = response.json()
print('Linked orders fetched successfully:', json.dumps(response_data, indent=4))
except requests.exceptions.HTTPError as err:
print(f"Failed {response.status_code}: {response.text}")
// Get Linked Orders
async function linkedOrders(linkId) {
  const linkId = "6acd808ba5957340b009-6238-ext"
  const endpoint = `/v1/order/linked-orders/${linkId}`; // Endpoint for fetching linked orders

// Call the getRequest function (similar to postRequest)
  return await getRequest(endpoint);
}

// Fetch Margin History
async function fetchMarginHistory() {
 const endpoint = "/v1/order/fetch-margin-history";
 const pageSize = 100;
 const sortOrder = "desc";
 const startTimestamp = "1696425435000";
 const endTimestamp = "1725451568979";
 const symbol = "BTCUSDT";

// Prepare query parameters
 const params = {

// Optional Params
 pageSize: pageSize.toString(),
 sortOrder: sortOrder,
 startTimestamp: startTimestamp,
 endTimestamp: endTimestamp,
 symbol: symbol,
 };
Parameter Type Required Description
linkId string Yes The unique identifier for the linked orders

Response

The details returned in the response body as are as follows:


// Response
[
  {
    "clientOrderId": "m2l-1f04cd91efa7ebe09cad-6238-ext",
    "time": "2024-09-11T12:14:03.706Z",
    "symbol": "BTCINR",
    "contractType": "PERPETUAL",
    "type": "MARKET",
    "side": "BUY",
    "price": 5054068,
    "orderAmount": 0.002,
    "filledAmount": 0,
    "linkId": "m2l-1f04cd91efa7ebe09cad-6238-ext",
    "subType": "PRIMARY",
    "linkType": "ORDER_SL",
    "takeProfitPrice": null,
    "stopLossPrice": null,
    "status": "NEW",
    "placeType": "ORDER_FORM",
    "baseAsset": "BTC",
    "quoteAsset": "INR"
  }
]
Parameter Description
clientOrderId Unique identifier for the client's order (m2l-1f04cd91efa7ebe09cad-6238-ext).
time The timestamp when the order was created (2024-09-11T12:14:03.706Z).
symbol The trading pair involved (BTCINR), indicating Bitcoin (BTC) traded against Indian Rupees (INR).
contractType The type of contract (PERPETUAL), indicating a perpetual futures contract.
type The order type (MARKET), meaning the order was executed at the current market price.
side Indicates whether the order is to buy or sell (BUY).
price The price per unit of Bitcoin at the time the order was placed (5054068 INR).
orderAmount The total amount of Bitcoin to be bought (0.002 BTC).
filledAmount The amount of Bitcoin that has been filled so far (0 BTC).
linkId Unique identifier for the linked order (m2l-1f04cd91efa7ebe09cad-6238-ext).
subType The order classification (PRIMARY), indicating the main order type.
linkType Indicates the link type of the order (ORDER_SL), possibly linking to a stop-loss order.
takeProfitPrice The take-profit price associated with the order (null), indicating no take-profit price set.
stopLossPrice The stop-loss price associated with the order (null), indicating no stop-loss price set.
status The current status of the order (NEW), meaning the order has been placed but not filled.
placeType The method by which the order was placed (ORDER_FORM), likely using an order form interface.
baseAsset The base asset being traded (BTC).
quoteAsset The currency used for the transaction (INR).

Fetch Margin History

GET /v1/order/fetch-margin-history

Retrieves the margin history for an account.

It supports optional filtering parameters like page size, sorting order, timestamps, and trading symbol.

This endpoint is useful for analyzing past margin activities and historical changes in margin levels.

def fetch_margin_history():
    endpoint = "/v1/order/fetch-margin-history"
    symbol = input("Enter the symbol (e.g., BTCUSDT): ").upper()

    pageSize = 100
    sortOrder = "desc"

# Generate current timestamp for signing
 timestamp = str(int(time.time() * 1000))

# Prepare query parameters
    params = {
    'pageSize': str(pageSize),
    'sortOrder': sortOrder,
    'symbol': symbol,
    'timestamp': timestamp
    }

# Convert params to query string
    query_string = '&'.join([f"{key}={value}" for key, value in params.items()])

# Generate signature
    signature = generate_signature(api_secret, query_string)

# Headers for the request
    headers = {
    'api-key': api_key,
     'signature': signature,
    'accept': '*/*'
    }
full_url = f"{base_url}{endpoint}?{query_string}"

try:
# Send the GET request to fetch margin history
response = requests.get(full_url, headers=headers)
response.raise_for_status() # Raises an error for 4xx/5xx responses
response_data = response.json()
print('Margin history fetched successfully:', json.dumps(response_data, indent=4))
except requests.exceptions.HTTPError as err:
print(f"Error: {err.response.text if err.response else err}")
except Exception as e:
print(f"An unexpected error occurred: {str(e)}")
// Fetch Margin History
async function fetchMarginHistory() {
  const endpoint = "/v1/order/fetch-margin-history";

  const pageSize = 100;
  const sortOrder = "desc";
  const startTimestamp = "1696425435000";
  const endTimestamp = "1725451568979";
  const symbol = "BTCUSDT";

// Prepare query parameters
  const params = {

// Optional Params
    pageSize: pageSize.toString(),
    sortOrder: sortOrder,
    startTimestamp: startTimestamp,
    endTimestamp: endTimestamp,
    symbol: symbol,
  };

// Call the getRequest function
  return await getRequest(endpoint, params);
}
Parameter Type Required Description
pageSize string No The number of results to return per page
sortOrder string No The sorting order for the results (e.g., "asc" or "desc")
startTimestamp string No The start timestamp (in milliseconds) for filtering margin history
endTimestamp string No The end timestamp (in milliseconds) for filtering margin history
symbol string No The trading pair symbol to filter the margin history (e.g., BTCUSDT)

Response

The response details are as follows:

// Response
{
  "data": [
    {
      "id": 549,
      "amount": 0.1,
      "refId": null,
      "marginInMarginAsset": 8.7,
      "marginAsset": "INR",
      "positionId": "90483119-0c3a-4cc0-9afa-25366f907fca",
      "operation": "REDUCE_MARGIN",
      "createdAt": "2024-09-12T08:59:57.707Z",
      "updatedAt": "2024-09-12T08:59:57.707Z"
    }
  ],
  "totalCount": 45,
  "nextTimestamp": "1725624883814"
}
Parameter Description
id Unique identifier for the margin operation (549).
amount The amount involved in the margin operation (0.1).
refId Reference ID associated with the operation (null, indicating no reference ID).
marginInMarginAsset Margin in the margin asset (8.7 INR).
marginAsset The asset used for margin (INR).
positionId Unique identifier for the position associated with the margin operation (90483119-0c3a-4cc0-9afa-25366f907fca).
operation The type of operation performed (REDUCE_MARGIN).
createdAt Timestamp when the margin operation was created (2024-09-12T08:59:57.707Z).
updatedAt Timestamp when the margin operation was last updated (2024-09-12T08:59:57.707Z).
totalCount The total number of margin operations recorded (45).
nextTimestamp The next timestamp for fetching data (1725624883814).

Get Positions

GET /v1/positions

Retrieves positions based on their status.

It allows filtering positions by their status (e.g., "OPEN") and supports additional optional parameters such as timestamps, sorting order, page size, and trading symbol.

This endpoint is useful for fetching current or historical positions and managing your trading portfolio.

# Function to fetch positions
def fetch_positions():
position_status = input("Enter position status (open, closed, liquidated): ").upper()
symbol = input("Enter the trading pair (e.g., BTCINR): ").upper()

if position_status not in ["OPEN", "CLOSED", "LIQUIDATED"]:
print("Invalid position status. Please enter 'open', 'closed', or 'liquidated'.")
return

# Optional parameters
sort_order = "desc" # Default sort order
page_size = 100 # Default page size

# Prepare the query parameters
params = {
'sortOrder': sort_order,
'pageSize': str(page_size),
'symbol': symbol,
  }

# Generate current timestamp
timestamp = str(int(time.time() * 1000))
params['timestamp'] = timestamp

# Generate signature based on the parameters
query_string = '&'.join([f"{key}={value}" for key, value in params.items()])
signature = generate_signature(api_secret, query_string)

# Headers for the GET request
headers = {
'api-key': api_key,
'signature': signature,
'accept': '*/*'
 }

# Construct the full URL including the path parameter for position status
full_url = f"{base_url}/v1/positions/{position_status}?{query_string}"

try:
# Send the GET request to fetch positions
response = requests.get(full_url, headers=headers)
response.raise_for_status() # Raises an error for 4xx/5xx responses
response_data = response.json()
print('Positions fetched successfully:', json.dumps(response_data, indent=4))
except requests.exceptions.HTTPError as err:
print(f"Error: {err.response.text if err.response else err}")
except Exception as e:
print(f"An unexpected error occurred: {str(e)}")
async function fetchPositions() {
  const endpoint = "/v1/positions/";

  const positionStatus = "OPEN"; // Required parameter
  const startTimestamp = "1696425435000"; // Optional
  const endTimestamp = "1725451568979"; // Optional
  const sortOrder = "desc"; // Optional
  const pageSize = 100; // Optional
  const symbol = "BTCINR"; // Optional

  const params = {
    // Optional Params
    // pageSize: pageSize.toString(),
    // sortOrder: sortOrder,
    // startTimestamp: startTimestamp,
    // endTimestamp: endTimestamp,
    // symbol: symbol,
  };
  const url = `${endpoint}${positionStatus}`;

// Call the getRequest function
  return await getRequest(url, params);
}

Parameter Type Required Description
positionStatus string Yes The status of the positions to retrieve (e.g., "OPEN")
startTimestamp string No The start timestamp (in milliseconds) for filtering positions
endTimestamp string No The end timestamp (in milliseconds) for filtering positions
sortOrder string No The sorting order for the results (e.g., "asc" or "desc")
pageSize string No The number of results to return per page
symbol string No The trading pair symbol to filter positions (e.g., BTCINR)

Response

The response parameters are described below:

{
  "id": 5454,
  "contractPair": "GRTINR",
  "contractType": "PERPETUAL",
  "entryPrice": 12.541,
  "leverage": 10,
  "liquidationPrice": 11.4,
  "marginType": "ISOLATED",
  "margin": 45.6,
  "marginInMarginAsset": 45.6,
  "positionAmount": 36,
  "positionId": "8b56348d-0d5d-4de1-85e1-3325bdf84087",
  "positionSize": 451.48,
  "positionStatus": "OPEN",
  "positionType": "LONG",
  "realizedProfit": null,
  "quantity": 36,
  "baseAsset": "GRT",
  "marginAsset": "INR",
  "quoteAsset": "INR",
  "createdTime": "2024-09-16T09:39:41.689Z",
  "updatedTime": "2024-09-16T09:39:41.689Z"
}
Parameter Description
id Unique identifier for the position (5454).
contractPair The trading pair for the contract (GRTINR), indicating GRT traded against INR.
contractType The type of contract (PERPETUAL), indicating a perpetual futures contract.
entryPrice The price at which the position was entered (12.541 INR per GRT).
leverage The leverage applied to the trade (10x).
liquidationPrice The price at which the position would be liquidated (11.4 INR per GRT).
marginType The type of margin used for the position (ISOLATED).
margin The amount of margin allocated to the position (45.6 INR).
marginInMarginAsset The amount of margin in the margin asset (45.6 INR).
positionAmount The amount of the position (36 GRT).
positionId Unique identifier for the position (8b56348d-0d5d-4de1-85e1-3325bdf84087).
positionSize The size of the position in terms of value (451.48 INR).
positionStatus The current status of the position (OPEN).
positionType The type of position (LONG).
realizedProfit The profit realized from the position (null, indicating no realized profit yet).
quantity The quantity of the asset involved (36 GRT).
baseAsset The base asset being traded (GRT).
marginAsset The asset used for margin (INR).
quoteAsset The currency used for the transaction (INR).
createdTime The timestamp when the position was created (2024-09-16T09:39:41.689Z).
updatedTime The timestamp when the position was last updated (2024-09-16T09:39:41.689Z).

Get Position Status

GET /v1/positions/{positionStatus}

Retrieves details for a specific position identified by its unique position ID.

It returns information related to the specified position, such as current status, asset details, and other relevant data.

def get_positions():
 position_status = input("Enter position status (open, closed, liquidated): ").upper()

  if position_status not in ["OPEN", "CLOSED", "LIQUIDATED"]:
  print("Invalid position status. Please enter 'open', 'closed', or 'liquidated'.")
  return

# Generate the current timestamp
    timestamp = str(int(time.time() * 1000))

# Prepare the query parameters
    params = {
    'sortOrder': 'desc',
    'pageSize': 100,
    'timestamp': timestamp
    }

# Convert the params into a query string to sign
    query_string = f"sortOrder={params['sortOrder']}&pageSize={params['pageSize']}&timestamp=
    {params['timestamp']}"

# Generate the signature
 signature = generate_signature(api_secret, query_string)

# Headers for the GET request
headers = {
'api-key': api_key,
'signature': signature,
'accept': '*/*'
 }

# Construct the full URL including the path parameter for position status
full_url = f"{base_url}/v1/positions/{position_status}?sortOrder={params['sortOrder']}&pageSize=
{params['pageSize']}&timestamp={params['timestamp']}"

try:
# Send the GET request to fetch positions
response = requests.get(full_url, headers=headers)
response.raise_for_status() # Raises an error for 4xx/5xx responses
response_data = response.json()
print('Positions fetched successfully:', json.dumps(response_data, indent=4))
except requests.exceptions.HTTPError as err:
print(f"Error: {err.response.text if err.response else err}")
except Exception as e:
print(f"An unexpected error occurred: {str(e)}")
async function getPosition() {
  const endpoint = "/v1/positions";
  const positionId = "sample-2c52-45cb-addf-9c1fde92fce5";

  const params = {
    positionId,
  };

  return await getRequest(endpoint, params);
}
Parameter Type Required Description
positionId string Yes The unique identifier for the position to retrieve

Response

// Response
[
    {
        "contractPair": "BTCUSDT",
        "entryPrice": 58003.7,
        "leverage": 9,
        "liquidationPrice": 52173.1,
        "marginType": "ISOLATED",
        "marginAsset": "INR",
        "margin": 19.404,
        "marginInMarginAsset": 1688.15,
        "positionAmount": 0.003,
        "positionId": "dd89732b-3a9d-4500-acec-64e1384c7149",
        "positionSize": 174.0111,
        "positionStatus": "OPEN",
        "positionType": "LONG",
        "realizedProfit": 0,
        "quantity": 0.003,
        "createdAt": "2024-09-13T08:19:18.642Z",
        "contractType": "PERPETUAL",
        "iconUrl": "https://storage.googleapis.com/pi42-dev-static/contract-icons/btc.png",
        "baseAsset": "BTC",
        "quoteAsset": "USDT"
    }
]
Parameter Description
contractPair The trading pair for the contract (BTCUSDT), indicating Bitcoin (BTC) traded against USDT (Tether).
entryPrice The price at which the position was entered (58003.7 USDT).
leverage The leverage applied to the trade (9x).
liquidationPrice The price at which the position would be liquidated (52173.1 USDT).
marginType The type of margin used for the position (ISOLATED).
marginAsset The asset used for margin (INR).
margin The amount of margin allocated to the position (19.404 INR).
marginInMarginAsset The amount of margin in the margin asset (1688.15 INR).
positionAmount The amount of the position (0.003 BTC).
positionId Unique identifier for the position (dd89732b-3a9d-4500-acec-64e1384c7149).
positionSize The size of the position in terms of value (174.0111 USDT).
positionStatus The current status of the position (OPEN).
positionType The type of position (LONG).
realizedProfit The profit realized from the position (0, indicating no realized profit yet).
quantity The quantity of the asset involved (0.003 BTC).
createdAt The timestamp when the position was created (2024-09-13T08:19:18.642Z).
contractType The type of contract (PERPETUAL), indicating a perpetual futures contract.
iconUrl The URL for the contract icon (https://storage.googleapis.com/pi42-dev-static/contract-icons/btc.png).
baseAsset The base asset being traded (BTC).
quoteAsset The currency used for the transaction (USDT).

Get User's Trade History

GET /v1/user-data/trade-history

Retrieves the trade history for a user.

It supports optional filtering parameters such as timestamps, sorting order, page size, and trading symbol to help users access their historical trade data efficiently.

async function fetchUserTradeHistory() {
  const endpoint = "/v1/user-data/trade-history";
  const startTimestamp = "1696425435000"; // Optional
  const endTimestamp = "1725451568979"; // Optional
  const sortOrder = "desc"; // Optional
  const pageSize = 100; // Optional
  const symbol = "BTCINR"; // Optional

const params = {
   //Optional Params
    pageSize: pageSize.toString(),
    sortOrder: sortOrder,
    startTimestamp: startTimestamp,
    endTimestamp: endTimestamp,
    symbol: symbol,
  };

// Call the getRequest function
  return await getRequest(endpoint, params);
}
# Function to fetch trade history
def trade_history():
    timestamp = str(int(time.time() * 1000))
    trade_history_url = "https://fapi.pi42.com/v1/user-data/trade-history"

params = {
    sortOrder': 'desc',
    'pageSize': 100,
    'timestamp': timestamp
 }

query_string = f"sortOrder={params['sortOrder']}&pageSize={params['pageSize']}&timestamp=
{params['timestamp']}"

 signature = generate_signature(api_secret, query_string)

 headers = {
    'api-key': api_key,
    'signature': signature,
    'accept': '*/*'
 }

try:
    response = requests.get(f"{trade_history_url}?{query_string}", headers=headers)
    response.raise_for_status()
    response_data = response.json()
    print('Trade history fetched successfully:', json.dumps(response_data, indent=4))
except requests.exceptions.HTTPError as err:
    print(f"Failed {response.status_code}: {response.text}")
Parameter Type Required Description
startTimestamp string No The start timestamp (in milliseconds) for filtering trade history
endTimestamp string No The end timestamp (in milliseconds) for filtering trade history
sortOrder string No The sorting order for the results (e.g., "asc" or "desc")
pageSize string No The number of results to return per page
symbol string No The trading pair symbol to filter trade history (e.g., BTCINR)

Response

The response parameters are as follows:

[
  {
    "id": 26260,
    "time": "2024-09-16T09:39:41.675Z",
    "symbol": "GRTINR",
    "type": "LIMIT",
    "side": "BUY",
    "price": 12.541,
    "quantity": 36,
    "role": "MAKER",
    "fee": 0,
    "realizedProfit": 0,
    "contractType": "PERPETUAL",
    "clientOrderId": "8acc0af94a3516126cdf-6238-ext",
    "baseAsset": "GRT",
    "quoteAsset": "INR",
    "marginAsset": "INR"
  }
]
Parameter Description
id Unique identifier for the order (26260).
time Timestamp when the order was placed (2024-09-16T09:39:41.675Z).
symbol The trading pair for the order (GRTINR), indicating GRT (The Graph) traded against INR (Indian Rupee).
type The type of order (LIMIT), indicating a limit order.
side The side of the order (BUY).
price The price at which the order is to be executed (12.541 INR).
quantity The quantity of the order (36 GRT).
role The role of the order in the trade (MAKER), indicating the order added liquidity to the market.
fee The fee charged for the order (0, indicating no fee).
realizedProfit The profit realized from the order (0, indicating no realized profit yet).
contractType The type of contract for the order (PERPETUAL), indicating a perpetual futures contract.
clientOrderId Unique identifier for the client order (8acc0af94a3516126cdf-6238-ext).
baseAsset The base asset being traded (GRT).
quoteAsset The currency used for the transaction (INR).
marginAsset The asset used for margin (INR).

Get User's Transaction History

GET/v1/user-data/transaction-history

Retrieves the transaction history for a user, allowing filtering and sorting based on optional parameters.

It provides detailed records of transactions within the specified time range and can be filtered by trading symbol, trade ID, and position ID.

def get_transaction_history():
    # Default values for optional parameters
    start_timestamp = None
    end_timestamp = None
    sort_order = 'desc'
    page_size = 100
    symbol = None
    trade_id = None
    position_id = None

    # Generate the current timestamp (used as part of the authentication/signing process)
    timestamp = str(int(time.time() * 1000))

    # Prepare query parameters with required and optional fields
    params = {
        'sortOrder': sort_order,
        'pageSize': page_size,
        'timestamp': timestamp
    }

    # Include optional parameters only if they are provided
    if start_timestamp:
        params['startTimestamp'] = start_timestamp
    if end_timestamp:
        params['endTimestamp'] = end_timestamp
    if symbol:
        params['symbol'] = symbol
    if trade_id:
        params['tradeId'] = trade_id
    if position_id:
        params['positionId'] = position_id

    # Convert the parameters to a query string to be signed
    query_string = '&'.join([f"{key}={value}" for key, value in params.items()])

    # Generate the signature (assuming `generate_signature` is defined)
    signature = generate_signature(api_secret, query_string)

    # Headers for the GET request
    headers = {
        'api-key': api_key,
        'signature': signature,
        'accept': '*/*'
    }

    # Construct the full URL with the query string
    full_url = f"{base_url}/v1/user-data/transaction-history?{query_string}"

    try:
        # Send the GET request to fetch transaction history
        response = requests.get(full_url, headers=headers)
        response.raise_for_status()  # Raises an error for HTTP 4xx/5xx responses
        response_data = response.json()
        print('Transaction history fetched successfully:', json.dumps(response_data, indent=4))
    except requests.exceptions.HTTPError as err:
        # Handle specific HTTP errors
        print(f"HTTP Error: {err.response.text if err.response else 'No response text'}")
    except Exception as e:
        # Handle any other exceptions
        print(f"Failed {response.status_code}: {response.text}")
async function fetchUserTransactionHistory() {
    const endpoint = "/v1/user-data/transaction-history";

    // Optional parameters for filtering and sorting the transaction history
    const startTimestamp = "1696425435000"; // Start timestamp in milliseconds
    const endTimestamp = "1725451568979";   // End timestamp in milliseconds
    const sortOrder = "desc";               // Sorting order: "asc" or "desc"
    const pageSize = 100;                   // Number of records per page
    const symbol = "BTCINR";                // Trading symbol, e.g., "BTCINR"
    const tradeId = 12;                     // Specific trade ID to filter
    const positionId = "3d5f302b-2c52-45cb-addf-9c1fde92fce5"; // Specific position ID

    // Construct the query parameters object
    const params = {
        pageSize: pageSize.toString(),
        sortOrder: sortOrder,
        startTimestamp: startTimestamp,
        endTimestamp: endTimestamp,
        symbol: symbol,
        tradeId: tradeId,
        positionId: positionId,
    };

    // Call the getRequest function with the endpoint and query parameters
    return await getRequest(endpoint, params);
}
Parameter Type Required Description
startTimestamp string No The start timestamp (in milliseconds) for filtering transaction history
endTimestamp string No The end timestamp (in milliseconds) for filtering transaction history
sortOrder string No The sorting order for the results (e.g., "asc" or "desc")
pageSize string No The number of records to return per page
symbol string No The trading symbol to filter the transaction history (e.g., BTCINR)
tradeId number No The specific trade ID to filter the transaction history
positionId string No The specific position ID to filter the transaction history

Response

[
  {
    "id": 109884,
    "time": "2024-09-16T09:39:28.754Z",
    "type": "COMMISSION",
    "amount": -2.1,
    "asset": "INR",
    "symbol": "BTCINR",
    "contractType": "PERPETUAL",
    "baseAsset": "BTC",
    "quoteAsset": "INR"
  }
]
Parameter Description
id Unique identifier for the transaction (109884).
time Timestamp when the transaction occurred (2024-09-16T09:39:28.754Z).
type The type of the transaction (COMMISSION), indicating a commission fee.
amount The amount of the commission fee (-2.1 INR).
asset The asset for the commission fee (INR).
symbol The trading pair associated with the transaction (BTCINR), indicating Bitcoin (BTC) traded against Indian Rupee (INR).
contractType The type of contract for the transaction (PERPETUAL), indicating a perpetual futures contract.
baseAsset The base asset in the trading pair (BTC).
quoteAsset The currency used for the transaction (INR).

Update Preference

POST /v1/exchange/update/preference

Updates the leverage and margin-mode(Cross or Isolated) for a specified contract. It allows setting the leverage level and margin-mode for trading a particular asset or trading pair.

async function updatePreference() {
    const endpoint = "/v1/exchange/update/preference";

    const leverage = 10;
    const contractName = "BTCINR";
    const marginMode = "CROSS"

    // Prepare request payload
    const params = {
        leverage: leverage,       // Ensure leverage is an integer
        marginMode: marginMode,   // Ensure marginMode is ISOLATED or CROSS
        contractName: contractName,
    };

    // Call the postRequest function
    return await postRequest(endpoint, params);
}
import time
import json
import requests

def update_preference():
    endpoint = "/v1/exchange/update/preference"

    leverage = 10  # Ensure leverage is an integer
    contract_name = "BTCINR"  # Replace with the appropriate contract name
    margin_mode = "CROSS"  # Ensure marginMode is either 'ISOLATED' or 'CROSS'

    # Generate the current timestamp
    timestamp = str(int(time.time() * 1000))

    # Prepare the request body (JSON)
    params = {
        'leverage': leverage,
        'marginMode': margin_mode,
        'contractName': contract_name,
        'timestamp': timestamp
    }

    # Convert the request body to a JSON string for signing
    data_to_sign = json.dumps(params, separators=(',', ':'))

    # Generate the signature (ensure `generate_signature` is properly defined)
    signature = generate_signature(api_secret, data_to_sign)

    # Headers for the POST request
    headers = {
        'api-key': api_key,
        'Content-Type': 'application/json',
        'signature': signature
    }

    # Construct the full URL
    update_preference_url = f"{base_url}{endpoint}"

    try:
        # Send the POST request to update the preference
        response = requests.post(update_preference_url, json=params, headers=headers)
        response.raise_for_status()  # Raises an error for 4xx/5xx responses
        response_data = response.json()
        print('Preference updated successfully:', json.dumps(response_data, indent=4))
    except requests.exceptions.HTTPError as err:
        print(f"Error: {err.response.text if err.response else err}")
    except Exception as e:
        print(f"An unexpected error occurred: {str(e)}")
Parameter Type Required Description
leverage number Yes The leverage level to set for the contract (e.g., 10). Must be an integer.
marginMode string Yes Margin mode to set for the contract (CROSS/ISOLATED). Must be a string
contractName string Yes The trading pair or contract name to which the leverage applies (e.g., BTCINR)

Response

The response parameters are described below:

// Response
{
  "contractName": "ETHINR",
  "marginMode": "CROSS",
  "updatedLeverage": 10
}
Parameter Description
contractName The name of the contract (ETHINR), indicating Ethereum (ETH) traded against Indian Rupee (INR).
marginMode Updated margin mode for (ETHINR) is (CROSS)
updatedLeverage The updated leverage for the contract (10).

Update Leverage

POST /v1/exchange/update/leverage

Updates the leverage for a specified contract. It allows setting the leverage level for trading a particular asset or trading pair.

This endpoint is used to adjust the leverage settings for risk management and trading strategies.

async function updateLeverage() {
    const endpoint = "/v1/exchange/update/leverage";

    const leverage = 10;
    const contractName = "BTCINR";

    // Prepare request payload
    const params = {
        leverage: leverage,       // Ensure leverage is an integer
        contractName: contractName,
    };

    // Call the postRequest function
    return await postRequest(endpoint, params);
}
def update_leverage():
  leverage = int(input("Enter the leverage value: "))
  contract_name = input("Enter the contract name: ")

  # Generate the current timestamp
  timestamp = str(int(time.time() * 1000))

  # Prepare the request body (JSON)
  params = {
      'leverage': int(leverage),
      'contractName': contract_name,
      'timestamp': timestamp
  }

  # Convert the request body to a JSON string for signing
  data_to_sign = json.dumps(params, separators=(',', ':'))

  # Generate the signature
  signature = generate_signature(api_secret, data_to_sign)

  # Headers for the POST request
  headers = {
      'api-key': api_key,
      'Content-Type': 'application/json',
      'signature': signature
  }

  # Construct the full URL
  update_leverage_url = f"{base_url}/v1/exchange/update/leverage"

  try:
      # Send the POST request to update the leverage
      response = requests.post(update_leverage_url, json=params, headers=headers)
      response.raise_for_status() # Raises an error for 4xx/5xx responses
      response_data = response.json()
      print('Leverage updated successfully:', json.dumps(response_data, indent=4))
  except requests.exceptions.HTTPError as err:
      print(f"Error: {err.response.text if err.response else err}")
  except Exception as e:
      print(f"An unexpected error occurred: {str(e)}")
Parameter Type Required Description
leverage number Yes The leverage level to set for the contract (e.g., 10). Must be an integer.
contractName string Yes The trading pair or contract name to which the leverage applies (e.g., BTCINR)

Response

The response parameters are described below:

// Response
{
  "updatedLeverage": 10,
  "contractName": "ETHINR"
}
Parameter Description
updatedLeverage The updated leverage for the contract (10).
contractName The name of the contract (ETHINR), indicating Ethereum (ETH) traded against Indian Rupee (INR).

Deleting an Order

DELETE /v1/order/delete-order

deletes a specific order based on its client order ID.

It requires the client order ID (clientOrderID) to identify the order to be deleted and a timestamp for request validation.

async function deleteOrder() {
    const endpoint = "/v1/order/delete-order";
    const clientOrderId = "a9c5ba9893c99828e4b5-6238-ext";
    const timestamp = Date.now().toString();

    // Prepare request payload
    const params = {
        clientOrderId: clientOrderId,
        timestamp: timestamp,
    };

    // Call the deleteRequest function
    return await deleteRequest(endpoint, params);
}
def delete_order():
    client_order_id = input("Enter the clientOrderId to delete: ")
    delete_order_url = "https://fapi.pi42.com/v1/order/delete-order"

    timestamp = str(int(time.time() * 1000))

    params = {
        'clientOrderId': client_order_id,
        'timestamp': timestamp
    }

    data_to_sign = json.dumps(params, separators=(',', ':'))
    signature = generate_signature(api_secret, data_to_sign)

    headers = {
        'api-key': api_key,
        'Content-Type': 'application/json',
        'signature': signature,
    }

    try:
        response = requests.delete(delete_order_url, json=params, headers=headers)
        response.raise_for_status()
        print(f"Order with clientOrderId {client_order_id} deleted successfully.")
    except requests.exceptions.HTTPError as err:
        print(f"Failed {response.status_code}: {response.text}")
Parameter Type Required Description
clientOrderId string Yes The unique identifier for the order to be deleted (e.g., a9c5ba9893c99828e4b5-6238-ext)
timestamp string Yes The current timestamp (in milliseconds) for request validation

Response

{
  "clientOrderId": "93513fe2a8af44157234-6238-ext",
  "orderId": 24717,
  "status": "CANCELED",
  "success": true
}
Parameter Description
clientOrderId Unique identifier for the client order (93513fe2a8af44157234-6238-ext).
orderId Unique identifier for the order (24717).
status The status of the order (CANCELED).
success Indicates whether the operation was successful (true).

Cancel all the orders

DELETE /v1/order/cancel-all-orders

Deletes all the open orders.

async function cancelAllOrders() {
    const endpoint = "/v1/order/cancel-all-orders";
    const timestamp = Date.now().toString();

    // Prepare request payload
    const params = {
        timestamp: timestamp,
    };

    // Call the deleteRequest function
    return await deleteRequest(endpoint, params);
}
import time
import json
import requests

def cancel_all_orders():
    endpoint = "/v1/order/cancel-all-orders"

    # Generate the current timestamp
    timestamp = str(int(time.time() * 1000))

    # Prepare the request payload
    params = {
        'timestamp': timestamp
    }

    # Convert the request body to a JSON string for signing
    data_to_sign = json.dumps(params, separators=(',', ':'))

    # Generate the signature (ensure `generate_signature` is properly defined)
    signature = generate_signature(api_secret, data_to_sign)

    # Headers for the DELETE request
    headers = {
        'api-key': api_key,
        'Content-Type': 'application/json',
        'signature': signature
    }

    # Construct the full URL
    cancel_orders_url = f"{base_url}{endpoint}"

    try:
        # Send the DELETE request to cancel all orders
        response = requests.delete(cancel_orders_url, json=params, headers=headers)
        response.raise_for_status()  # Raises an error for 4xx/5xx responses
        response_data = response.json()
        print('All orders canceled successfully:', json.dumps(response_data, indent=4))
    except requests.exceptions.HTTPError as err:
        print(f"Failed {response.status_code}: {response.text}")
    except Exception as e:
        print(f"An unexpected error occurred: {str(e)}")
Parameter Type Required Description
timestamp string Yes The current timestamp (in milliseconds) for request validation

Response

{
  "success": true,
  "data": [
    {
      "clientOrderId": "02f8c7b42c904b5475b6-6238-ext",
      "status": "CANCELED",
      "message": "Order is cancelled"
    },
  ]
}
Parameter Description
clientOrderId Unique identifier for the client order (93513fe2a8af44157234-6238-ext).
status The status of the order (CANCELED).
message Order is cancelled.

Close all the positions

DELETE /v1/positions/close-all-positions

Closes all the Positions.

async function closeAllPositions() {
    const endpoint = "/v1/positions/close-all-positions";
    const timestamp = Date.now().toString();

    // Prepare request payload
    const params = {
        timestamp: timestamp,
    };

    // Call the deleteRequest function
    return await deleteRequest(endpoint, params);
}
import time
import json
import requests

def close_all_positions():
    endpoint = "/v1/positions/close-all-positions"

    # Generate the current timestamp
    timestamp = str(int(time.time() * 1000))

    # Prepare the request payload
    params = {
        'timestamp': timestamp
    }

    # Convert the request body to a JSON string for signing
    data_to_sign = json.dumps(params, separators=(',', ':'))

    # Generate the signature (ensure `generate_signature` is properly defined)
    signature = generate_signature(api_secret, data_to_sign)

    # Headers for the DELETE request
    headers = {
        'api-key': api_key,
        'Content-Type': 'application/json',
        'signature': signature
    }

    # Construct the full URL
    cancel_orders_url = f"{base_url}{endpoint}"

    try:
        # Send the DELETE request to cancel all orders
        response = requests.delete(cancel_orders_url, json=params, headers=headers)
        response.raise_for_status()  # Raises an error for 4xx/5xx responses
        response_data = response.json()
        print('All orders canceled successfully:', json.dumps(response_data, indent=4))
    except requests.exceptions.HTTPError as err:
        print(f"Failed {response.status_code}: {response.text}")
    except Exception as e:
        print(f"An unexpected error occurred: {str(e)}")
Parameter Type Required Description
timestamp string Yes The current timestamp (in milliseconds) for request validation

Response

{
  "success": true,
  "data": [
    {
      "positionId": "2d29687c-2aab-4378-ada3-f18ecb73b332",
      "status": "CLOSED",
      "message": "Position is closed."
    }
  ]
}
Parameter Description
positionId Unique identifier for the position (2d29687c-2aab-4378-ada3-f18ecb73b332).
status The status of the order (CLOSED).
message Position is closed.

Get futures wallet details

GET /v1/wallet/futures-wallet/details

Get all details of Futures wallet.

async function getFuturesWallet() {
  const params = {
    // Optional Params
    marginAsset: "INR"
  };

  const endpoint = "/v1/wallet/futures-wallet/details";

  // Call the postRequest function
  return await getRequest(endpoint, params);
}
import time
import json
import requests

def get_futures_wallet_details():
    endpoint = "/v1/wallet/futures-wallet/details"

    # Generate the current timestamp
    timestamp = str(int(time.time() * 1000))

    # Optional parameters with timestamp
    params = {
        'marginAsset': 'INR',
        'timestamp': timestamp
    }

    # Convert the request body to a JSON string for signing
    data_to_sign = json.dumps(params, separators=(',', ':'))

    # Generate the signature (ensure `generate_signature` is properly defined)
    signature = generate_signature(api_secret, data_to_sign)

    # Headers for the GET request
    headers = {
        'api-key': api_key,
        'Content-Type': 'application/json',
        'signature': signature
    }

    # Construct the full URL
    wallet_details_url = f"{base_url}{endpoint}"

    try:
        # Send the GET request to fetch the futures wallet details
        response = requests.get(wallet_details_url, headers=headers, params=params)
        response.raise_for_status()  # Raises an error for 4xx/5xx responses
        response_data = response.json()
        print('Futures wallet details:', json.dumps(response_data, indent=4))
    except requests.exceptions.HTTPError as err:
        print(f"Failed {response.status_code}: {response.text}")
    except Exception as e:
        print(f"An unexpected error occurred: {str(e)}")

Parameter Type Required Description
timestamp string Yes The current timestamp (in milliseconds) for request validation
marginAsset string No MarginAsset of Futures wallet (INR).

Response

// Response
{
  "inrBalance": "1941.50",
  "walletBalance": "1941.50",
  "withdrawableBalance": "1468.50",
  "maintenanceMargin": "0.00",
  "unrealisedPnlCross": "0.00",
  "unrealisedPnlIsolated": "0.00",
  "maxWithdrawableBalance": "1468.50",
  "lockedBalance": "473.00",
  "marginBalance": "1468.52",
  "pnlPercentCross": "0.00",
  "pnlPercentIsolated": "0.00",
  "lockedBalanceCross": "0.00",
  "lockedBalanceIsolated": "473.00",
  "marginAsset": "INR"
}
Parameter Description
inrBalance INR balance of Futures wallet (INR).
walletBalance Total wallet balance in INR.
withdrawableBalance Amount of INR that can be withdrawn from the wallet.
maintenanceMargin Amount of INR locked as maintenance margin.
unrealisedPnlCross Unrealized profit and loss (PnL) in cross margin mode in INR.
unrealisedPnlIsolated Unrealized profit and loss (PnL) in isolated margin mode in INR.
maxWithdrawableBalance Maximum amount of INR that can be withdrawn, factoring in margins and locked funds.
lockedBalance Total locked balance in INR, which cannot be withdrawn or used.
marginBalance Total margin balance in INR, including any unrealized PnL.
pnlPercentCross Percentage of unrealized PnL in cross margin mode.
pnlPercentIsolated Percentage of unrealized PnL in isolated margin mode.
lockedBalanceCross Amount of INR locked in cross margin mode.
lockedBalanceIsolated Amount of INR locked in isolated margin mode.
marginAsset Asset type used for margin, in this case, INR.

Get funding wallet details

GET /v1/wallet/funding-wallet/details

Get details of funding wallet.

async function getFundingWallet() {
  const params = {
    // Optional Params
    marginAsset: "INR"
  };

  const endpoint = "/v1/wallet/funding-wallet/details";

  // Call the postRequest function
  return await getRequest(endpoint, params);
}
import time
import json
import requests

def get_funding_wallet_details():
    endpoint = "/v1/wallet/funding-wallet/details"

    # Generate the current timestamp
    timestamp = str(int(time.time() * 1000))

    # Optional parameters with timestamp
    params = {
        'marginAsset': 'INR',
        'timestamp': timestamp
    }

    # Convert the request body to a JSON string for signing
    data_to_sign = json.dumps(params, separators=(',', ':'))

    # Generate the signature (ensure `generate_signature` is properly defined)
    signature = generate_signature(api_secret, data_to_sign)

    # Headers for the GET request
    headers = {
        'api-key': api_key,
        'Content-Type': 'application/json',
        'signature': signature
    }

    # Construct the full URL
    funding_wallet_url = f"{base_url}{endpoint}"

    try:
        # Send the GET request to fetch the funding wallet details
        response = requests.get(funding_wallet_url, headers=headers, params=params)
        response.raise_for_status()  # Raises an error for 4xx/5xx responses
        response_data = response.json()
        print('Funding wallet details:', json.dumps(response_data, indent=4))
    except requests.exceptions.HTTPError as err:
        print(f"Failed {response.status_code}: {response.text}")
    except Exception as e:
        print(f"An unexpected error occurred: {str(e)}")
Parameter Type Required Description
timestamp string Yes The current timestamp (in milliseconds) for request validation
marginAsset string No MarginAsset of Futures wallet (INR).

Response

// Response
{
  "inrBalance": "601.00",
  "walletBalance": "601.00",
  "withdrawableBalance": "601.00",
  "lockedBalance": "0.00",
  "marginAsset": "INR"
}
Parameter Description
inrBalance INR balance of Futures wallet (INR).
walletBalance Total wallet balance in INR.
withdrawableBalance Amount of INR that can be withdrawn from the wallet.
lockedBalance Total locked balance in INR, which cannot be withdrawn or used.
marginAsset Asset type used for margin, in this case, INR.

Public Endpoints

Public endpoints in Pi42 are designed to facilitate easy access to various functionalities of the Pi42 platform, particularly for integration with external systems and applications. Below is an overview of the public endpoints available in Pi42, their typical uses, and example API calls.

Ticker Update (24Hr)

GET /v1/market/ticker24Hr

Fetches the 24-hour market ticker data for a specific trading pair.

It provides details such as the last traded price, volume, and other market metrics over the past 24 hours.

async function fetchTicker() {
    const endpoint = "/v1/market/ticker24Hr/";  // API endpoint for fetching the 24-hour market ticker
    const contractPair = "BTCINR";              // The trading pair for which the ticker data is being requested
    const url = `${endpoint}${contractPair}`;   // Constructs the full URL by appending the trading pair to the endpoint

    // Call the getRequest function with the constructed URL
    return await getRequest(url, {});
}
import requests
import json

def get_24hr_ticker_update():
    # Get the contract pair input from the user
    contract_pair = input("Enter the contract pair (e.g., btc, eth): ").lower()

    # Validate the input
    if not contract_pair:
        print("Invalid contract pair. Please enter a valid contract pair (e.g., btc, eth).")
        return

    # Construct the full URL for the API request using the provided contract pair
    full_url = f"https://api.pi42.com/v1/market/ticker24Hr/{contract_pair}"

    try:
        # Send the GET request to the API
        response = requests.get(full_url)
        response.raise_for_status()  # Raise an error for HTTP 4xx/5xx responses

        # Parse the JSON response data
        response_data = response.json()

        # Print the 24-hour ticker update in a formatted manner
        print('24-hour ticker update fetched successfully:', json.dumps(response_data, indent=4))
    except requests.exceptions.HTTPError as err:
        # Handle HTTP errors specifically
        print(f"Error: {err.response.text if err.response else err}")
    except Exception as e:
        # Handle any other unexpected errors
        print(f"An unexpected error occurred: {str(e)}")
Parameter Type Required Description
contractPair string Yes The trading pair for which to fetch the ticker data (e.g., BTCINR)

Response

The response parameters are as follows:

// Response
{
  "data": {
    "e": "24hrTicker",
    "E": 1726313209122,
    "s": "BTCINR",
    "p": "139470.66",
    "P": "2.718",
    "w": "5230573.12",
    "c": "5271387.66",
    "Q": "0.081",
    "o": "5131917",
    "h": "5344655.41",
    "l": "5079790.8",
    "v": "274282.584",
    "q": "16265932028.08",
    "O": 1726226760000,
    "C": 1726313209120,
    "F": 5380307688,
    "L": 5383597456,
    "n": 3289757
  }
}
Parameter Description
e The event type (24hrTicker), indicating a 24-hour ticker event.
E The event time in milliseconds since epoch (1726313209122).
s The trading pair symbol (BTCINR), indicating Bitcoin (BTC) traded against Indian Rupee (INR).
p The price change in the last 24 hours (139470.66 INR).
P The percentage price change in the last 24 hours (2.718%).
w The weighted average price in the last 24 hours (5230573.12 INR).
c The last price (5271387.66 INR).
Q The last quantity traded (0.081 BTC).
o The open price of the 24-hour period (5131917 INR).
h The highest price in the last 24 hours (5344655.41 INR).
l The lowest price in the last 24 hours (5079790.8 INR).
v The total traded volume in the last 24 hours (274282.584 BTC).
q The total traded quote asset volume in the last 24 hours (16265932028.08 INR).
O The start time of the 24-hour period in milliseconds since epoch (1726226760000).
C The end time of the 24-hour period in milliseconds since epoch (1726313209120).
F The first trade ID in the 24-hour period (5380307688).
L The last trade ID in the 24-hour period (5383597456).
n The number of trades in the 24-hour period (3289757).

Aggregate Trade Update

GET /v1/market/aggTrade

Retrieves aggregated trade data for a specific trading pair.

Aggregated trades provide summarized information about trade activities, such as total volume and price changes, for the given trading pair.

async function fetchAggTrade() {
    const endpoint = "/v1/market/aggTrade/";   // Define the API endpoint for aggregated trades
    const contractPair = "BTCINR";             // Specify the trading pair (e.g., Bitcoin to Indian Rupee)
    const url = `${endpoint}${contractPair}`;  // Construct the full URL by appending the trading pair to the endpoint

    // Call the getRequest function to send the GET request to the API
    return await getRequest(url, {});
}
import requests
import json

def get_trade_updates():
    # Prompt the user to enter a contract pair
    contract_pair = input("Enter the contract pair (e.g., btc, eth): ").lower()

    # Validate the user input
    if not contract_pair:
        print("Invalid contract pair. Please enter a valid contract pair (e.g., btc, eth).")
        return

    # Construct the URL for the API request using the provided contract pair
    full_url = f"https://api.pi42.com/v1/market/aggTrade/{contract_pair}"

    try:
        # Send the GET request to fetch trade updates
        response = requests.get(full_url)
        response.raise_for_status()  # Raise an exception for HTTP error responses

        # Parse the JSON response data
        response_data = response.json()

        # Print the trade updates in a formatted manner
        print('Trade updates fetched successfully:', json.dumps(response_data, indent=4))
    except requests.exceptions.HTTPError as err:
        # Handle HTTP errors specifically
        print(f"Error: {err.response.text if err.response else err}")
    except Exception as e:
        # Handle any other unexpected errors
        print(f"An unexpected error occurred: {str(e)}")

Parameter Type Required Description
contractPair string Yes The trading pair for which to fetch aggregated trade data (e.g., BTCINR)

Response

The response body parameters are described as follows:

// Response
{
  "data": [
    {
      "e": "aggTrade",
      "E": 1726313202969,
      "a": 2329235556,
      "s": "BTCINR",
      "p": "5271343.57",
      "q": "0.002",
      "f": 5383597285,
      "l": 5383597285,
      "T": 1726313202966,
      "m": true
    }
  ]
}
Parameter Description
e The event type (aggTrade), indicating an aggregated trade event.
E The event time in milliseconds since epoch (1726313202969).
a The aggregate trade ID (2329235556).
s The trading pair symbol (BTCINR), indicating Bitcoin (BTC) traded against Indian Rupee (INR).
p The price of the trade (5271343.57 INR).
q The quantity of the trade (0.002 BTC).
f The first trade ID in the aggregate trade (5383597285).
l The last trade ID in the aggregate trade (5383597285).
T The trade time in milliseconds since epoch (1726313202966).
m Whether the buyer is the market maker (true).

Depth Update

GET /v1/market/depth/

Fetches the order book depth data for a specific trading pair.

It provides information about the current market depth, including bid and ask prices and their respective volumes, which is essential for understanding market liquidity.

async function fetchDepth() {
    const endpoint = "/v1/market/depth/";   // API endpoint for fetching order book depth data
    const contractPair = "BTCINR";           // Trading pair for which the depth data is requested
    const url = `${endpoint}${contractPair}`; // Constructs the full URL by appending the trading pair to the endpoint

    // Call the getRequest function with the constructed URL
    return await getRequest(url, {});
}
def get_depth_update():
    # Prompt the user to enter a contract pair
    contract_pair = input("Enter the contract pair (e.g., btc, eth): ").lower()

    # Validate the user input
    if not contract_pair:
        print("Invalid contract pair. Please enter a valid contract pair (e.g., btc, eth).")
        return

    # Construct the URL for the API request using the provided contract pair
    full_url = f"https://api.pi42.com/v1/market/depth/{contract_pair}"

    try:
        # Send the GET request to fetch depth updates
        response = requests.get(full_url)
        response.raise_for_status()  # Raises an error for 4xx/5xx responses

        # Parse the JSON response data
        response_data = response.json()

        # Print the depth update in a formatted manner
        print('Depth update fetched successfully:', json.dumps(response_data, indent=4))
    except requests.exceptions.HTTPError as err:
        # Handle HTTP errors specifically
        print(f"Error: {err.response.text if err.response else err}")
    except Exception as e:
        # Handle any other unexpected errors
        print(f"An unexpected error occurred: {str(e)}")
Parameter Type Required Description
contractPair string Yes The trading pair for which to fetch the order book depth data (e.g., BTCINR)

Response

The parameters contained in the response body are as follows:

// Response
{
  "data": {
    "e": "depthUpdate",
    "E": 1726313210012,
    "T": 1726313210009,
    "s": "BTCINR",
    "U": 5339856484581,
    "u": 5339856497601,
    "pu": 5339856483867,
    "b": [
      [
        "5271043.69",
        "0.554"
      ]
    ],
    "a": [
      [
        "5271396.49",
        "0.866"
      ]
    ]
  }
}
Parameter Description
e The event type (depthUpdate), indicating a market depth update.
E The event time in milliseconds since epoch (1726313210012).
T The transaction time in milliseconds since epoch (1726313210009).
s The trading pair symbol (BTCINR), indicating Bitcoin (BTC) traded against Indian Rupee (INR).
U The first update ID in the update (5339856484581).
u The last update ID in the update (5339856497601).
pu The previous update ID (5339856483867).
b Current bid prices and quantities. Each entry is an array where the first element is the price and the second element is the quantity. Example: [["5271043.69", "0.554"]].
a Current ask prices and quantities. Each entry is an array where the first element is the price and the second element is the quantity. Example: [["5271396.49", "0.866"]].

Get Klines

POST /v1/market/klines

Retrieves candlestick (kline) data for a specified trading pair and time interval.

It provides historical price data that can be used for charting and analysis, including start and end times, and limits on the number of records returned.

async function getKlines() {
    const endpoint = "/v1/market/klines";

    // Define the fixed values for positionId and amount (though not used in this function)
    const positionId = "18c6c979-b089-4e67-b627-4c2072d0d5cb"; // Replace with your actual position ID
    const amount = 1; // Replace with the actual amount you want to add

    // Prepare request payload
    const params = {
        pair: "BTCINR",
        interval: "1m",
        // Optional
        startTime: 1696425435000,
        endTime: 1696425435999,
        limit: 1000
    };

    // Call the postRequest function
    return await postRequest(endpoint, params);
}
def get_kline_data():
  try:
      # User inputs
      pair = input("Enter the trading pair (e.g., BTCINR): ").upper()
      interval = input("Enter the interval (e.g., 1m, 5m, 1h): ").lower()

      # Prepare the request body (JSON)
      params = {
          'pair': pair,
          'interval': interval,
          'limit': 1000
      }

      # Headers for the POST request (no API key or signature required)
      headers = {
          'Content-Type': 'application/json'
      }

      # Construct the full URL for the Kline endpoint
      kline_url = "https://api.pi42.com/v1/market/klines"

      # Send the POST request to get Kline data
      response = requests.post(kline_url, json=params, headers=headers)
      response.raise_for_status() # Raises an error for 4xx/5xx responses
      response_data = response.json()
      print('Kline data fetched successfully:', json.dumps(response_data, indent=4))

  except ValueError:
      print("Please enter valid inputs for pair, interval.")
  except requests.exceptions.HTTPError as err:
      print(f"Error: {err.response.text if err.response else err}")
  except Exception as e:
      print(f"An unexpected error occurred: {str(e)}")
Parameter Type Required Description
pair string Yes The trading pair for which to fetch kline data (e.g., BTCINR)
interval string Yes The interval for each kline (e.g., "1m" for 1 minute, "5m" for 5 minutes)
startTime number No The start time (in milliseconds) for the kline data (timestamp)
endTime number No The end time (in milliseconds) for the kline data (timestamp)
limit number No The maximum number of kline records to return

Response

The response parameters are described below:

[
  {
    "startTime": "1726312200000",
    "open": "5270382.19",
    "high": "5270408.64",
    "low": "5270382.19",
    "close": "5270382.19",
    "endTime": "1726312259999",
    "volume": "59.102"
  },
]
Parameter Description
startTime The start time of the interval in milliseconds since epoch (1726312200000).
open The opening price of the interval (5270382.19 INR).
high The highest price during the interval (5270408.64 INR).
low The lowest price during the interval (5270382.19 INR).
close The closing price of the interval (5270382.19 INR).
endTime The end time of the interval in milliseconds since epoch (1726312259999).
volume The trading volume during the interval (59.102 BTC).

Exchange

GET /v1/exchange/exchangeInfo

Retrieve exchange information

async function getExchangeInfo() {
    const endpoint = "/v1/exchange/exchangeInfo";

    // Prepare request payload
    const params = {
        // Optional
        market:"INR"
    };

    // Call the postRequest function
    return await getRequest(endpoint, params);
}

def get_exchange_info():

  # Construct the URL
  full_url = f"{base_url}/v1/exchange/exchangeInfo"

  try:
      # Send the GET request to fetch exchange information
      response = requests.get(full_url)
      response.raise_for_status()  # Raises an error for 4xx/5xx responses
      response_data = response.json()
      print('Exchange information fetched successfully:', json.dumps(response_data, indent=4))
  except requests.exceptions.HTTPError as err:
      print(f"Error: {err.response.text if err.response else err}")
  except Exception as e:
      print(f"An unexpected error occurred: {str(e)}")
Parameter Type Required Description
market string No Will return exchangeInfo for market (e.g., INR/USDT)

Response

The response parameters are described below:

Parameter Description
market A list of markets included in the response.
contracts An array of contract objects that contain detailed information about specific trading contracts.
name The name of the trading pair (e.g., "BTCINR" for Bitcoin to INR)
contractName The full name of the contract (e.g., "Bitcoin").
filters A list of filters that apply to the contract, detailing quantity and order constraints
maxQty The maximum quantity allowed
minQty The minimum quantity allowed
filterType The type of filter (e.g., "MARKET_QTY_SIZE", "LIMIT_QTY_SIZE", "MAX_NUM_ORDERS", "MIN_NOTIONAL").
limit The maximum number of orders allowed.
notional The minimum notional value.
makerFee The fee percentage for makers.
takerFee The fee percentage for takers.
baseAsset The base asset for the contract (e.g., "BTC").
orderTypes The types of orders supported (e.g., "LIMIT", "MARKET").
quoteAsset The quote asset for the contract (e.g., "INR").
maxLeverage The maximum leverage allowed (e.g., "20").
contractType The type of contract (e.g., "PERPETUAL").
marginBuffer The margin buffer value.
depthGrouping The grouping for order book depth (e.g., ["0.1"]).
liquidationFee The fee percentage for liquidation (e.g., "0.020000").
pricePrecision The number of decimal places for prices.
isDefaultContract A boolean indicating if this is the default contract (e.g., true).
quantityPrecision The number of decimal places for quantities.
limitPriceVarAllowed The allowed price variation for limit orders (e.g., "0.2").
marginBufferPercentage The percentage for margin buffer (e.g., "1").
maintenanceMarginPercentage The percentage for maintenance margin (e.g., "1").
iconUrl The URL for the contract's icon (e.g., "string").
reduceMarginAllowedRatioPercent The allowed ratio percentage for reducing margin (e.g., 0.2).
market The market identifier
marginAssetsSupported A list of supported margin assets (e.g., ["INR"]).
fundingFeeInterval The interval for funding fees (e.g., 8).
tags A list of tags associated with the market or contracts (e.g., ["MEME", "DECENTRALIZED"]).
assetPrecisions An object that specifies the precision for assets.
INR The precision for INR (e.g., 2 decimal places).
USDT The precision for USDT (e.g., 4 decimal places).
conversionRates An object that specifies conversion rates for margin and settlement.
INR_MARGIN_USDT The conversion rate for INR margin to USDT (e.g., 88).
INR_MARGIN_INR The conversion rate for INR margin to INR (e.g., 1)
INR_SETTLEMENT_USDT The conversion rate for INR settlement to USDT (e.g., 88).
INR_SETTLEMENT_INR The conversion rate for INR settlement to INR (e.g., 1)
USDT_SETTLEMENT_USDT The conversion rate for USDT settlement to USDT (e.g., 1).
USDT_MARGIN_USDT The conversion rate for USDT margin to USDT (e.g., 1)

Web Sockets

WebSockets are used to provide real-time updates and maintain a continuous connection between clients (traders) and servers (exchanges).

Here's how different web sockets work:

Authenticated Web Sockets

Authenticated WebSockets require user validation to ensure that only authorized users can access the data or functionality provided such as receiving real-time updates about a trader's account.

For example, balance changes, order executions, or margin updates.

The WebSocket client connects to a server using a listen key and listens for various events related to trading activities and session management. Each event handler logs specific information when the event is received.

Event listeners are described below:

Event Description
connect Triggered when the connection to the WebSocket server is open.
newPosition Triggered when a new position is received from the server.
orderFilled Triggered when an order is completely filled.
orderPartiallyFilled Triggered when an order is partially filled.
orderCancelled Triggered when an order is cancelled.
orderFailed Triggered when an order fails.
newOrder Triggered when a stop order is executed.
updateOrder Triggered when a stop limit order is executed.
updatePosition Triggered when a position is updated.
closePosition Triggered when a position is closed.
balanceUpdate Triggered when the balance is updated.
newTrade Triggered when a new trade occurs.
sessionExpired Triggered when the session expires.
disconnect Triggered when the connection to the WebSocket server is closed.
const serverUrl = `https://fawss.pi42.com/auth-stream/${listenKey}`;

// Create a new socket connection
const socket = io(serverUrl);

// Event listener for when the connection is open
socket.on('connect', () => {
  console.log('Connected to WebSocket server');
});

// Event listener for messages from the server

// Event listener for newPosition events
socket.on('newPosition', (data: any) => {
  console.log('New position received:', data);
});

// Listen for order filled event
socket.on('orderFilled', (data: any) => {
  console.log('Order filled:', data);
});

// Listen for order partially filled event
socket.on('orderPartiallyFilled', (data: any) => {
  console.log('Order partially filled:', data);
});

// Listen for order cancelled event
socket.on('orderCancelled', (data: any) => {
  console.log('Order cancelled:', data);
});

// Listen for order failed event
socket.on('orderFailed', (data: any) => {
  console.log('Order failed:', data);
});

// Listen for new order event
socket.on('newOrder', (data: any) => {
  console.log('New order:', data);
});

// Listen for update position event
socket.on('updatePosition', (data: any) => {
  console.log('Position updated:', data);
});

// Listen for close position event
socket.on('closePosition', (data: any) => {
  console.log('Position closed:', data);
});

// Listen for balance update event
socket.on('balanceUpdate', (data: any) => {
  console.log('Balance updated:', data);
});

// Listen for new trade event
socket.on('newTrade', (data: any) => {
  console.log('New trade:', data);
});

// Listen for session expiry
socket.on('sessionExpired', (data: any) => {
  console.log('Session Expired:', data);
});

// Event listener for when the connection is closed
socket.on('disconnect', () => {
  console.log('Disconnected from WebSocket server');
});
# Required installations:
# python-socketio asyncio aiohttp

import socketio
import asyncio

# WebSocket server URL (without namespace)
server_url = 'Pi42-Authenticated-websocket-url'

# Namespace path for authorized streaming
namespace_path = '/auth-stream/your-listen-key'

# Create a new asynchronous Socket.IO client
sio = socketio.AsyncClient()

# Event listener for a successful connection to the server
@sio.event
async def connect():
    print('Successfully connected to the WebSocket server')

# Event listener for when the connection to the server is closed
@sio.event
async def disconnect():
    print('Disconnected from the WebSocket server')

# Event handler for receiving a new position update from the server
@sio.on('newPosition', namespace=namespace_path)
async def on_new_position(data):
    print("New position received:", data)

# Event handler for receiving an order filled notification
@sio.on('orderFilled', namespace=namespace_path)
async def on_order_filled(data):  # Accept data parameter
    print("Order filled:", data)

# Event handler for receiving a partially filled order update
@sio.on('orderPartiallyFilled', namespace=namespace_path)
async def on_order_partially_filled(data):
    print("Order partially filled:", data)

# Event handler for receiving a cancelled order notification
@sio.on('orderCancelled', namespace=namespace_path)
async def on_order_cancelled(data):
    print("Order cancelled:", data)

# Event handler for receiving a failed order notification
@sio.on('orderFailed', namespace=namespace_path)
async def on_order_failed(data):
    print("Order failed:", data)

# Event handler for receiving a new order(TP/SL) notification
@sio.on('newOrder', namespace=namespace_path)
async def on_new_order(data):
    print("New order:", data)

# Event handler for receiving a position update
@sio.on('updatePosition', namespace=namespace_path)
async def on_update_position(data):
    print("Position updated:", data)

# Event handler for receiving a position close notification
@sio.on('closePosition', namespace=namespace_path)
async def on_close_position(data):
    print("Position closed:", data)

# Event handler for balance update notifications
@sio.on('balanceUpdate', namespace=namespace_path)
async def on_balance_update(data):
    print("Balance updated:", data)

# Event handler for receiving a new trade notification
@sio.on('newTrade', namespace=namespace_path)
async def on_new_trade(data):
    print("New trade:", data)

# Event handler for session expiration notifications
@sio.on('sessionExpired', namespace=namespace_path)
async def on_session_expired(data):
    print("Session expired:", data)

# Event listener for connection errors
@sio.event
async def connect_error(data):
    print('Failed to connect to the WebSocket server:', data)

# Main function to initiate and maintain the WebSocket connection
async def main():
    try:
        # Attempt to connect to the server with specified transports
        await sio.connect(server_url, transports=["websocket"])
        await sio.wait()  # Keeps the connection open to listen for events
    except Exception as e:
        print("Connection error:", e)

# Entry point for the asyncio program
# Uses asyncio.run() to execute the main coroutine
if __name__ == '__main__':
    asyncio.run(main())

Public Web Sockets

Public WebSockets are open to all clients and do not require authentication to establish a connection. They are useful for scenarios where the data being transmitted is not sensitive or where the application does not require user-specific interactions.

For example, to receive real-time updates on market data such as price changes, order book depth, and trade history without requiring authentication.

Once connected, users can subscribe to different topics mentioned below:

Parameter Example Listening Topic
contract_pair@depth_minGrouping btcinr@depth _ 0.1 depthUpdate
contract _pair@kline _ interval btcinr@kline _ 1m kline
contract _pair@markPrice btcinr@markPrice markPriceUpdate
contract _pair@aggTrade btcinr@aggTrade aggTrade
contract _pair@ticker btcinr@ticker 24hrTicker
contract _pair@marketInfo btcinr@marketInfo marketInfo
markPriceArr N/A markPriceArr
tickerArr N/A tickerArr
All contracts details N/A allContractDetails
import { io } from 'socket.io-client';

// WebSocket server URL
const serverUrl = 'https://fawss.pi42.com/';

// Create a new socket connection
const socket = io(serverUrl);

// Event listener for when the connection is open
socket.on('connect', () => {
  console.log('Connected to WebSocket server');
  subscribeToTopics();
});

// Event listener for when the connection is closed
socket.on('disconnect', () => {
  console.log('Disconnected from WebSocket server');
});

// Event listener for errors
socket.on('error', (error: any) => {
  console.error('Socket.IO error:', error);
});

// Function to subscribe to various WebSocket topics
function subscribeToTopics() {
  const topics = ['btcinr@depth_0.1', 'btcinr@markPrice']; // List of topics you want to subscribe to

  // Subscribe to each topic
  socket.emit('subscribe', {
    params: topics, // Sends the topics array to the WebSocket server
  });

  // Event listener for updates on various data topics
  socket.on('depthUpdate', (data) => {
    console.log('depthUpdate: ', data);
  });

  socket.on('kline', (data) => {
    console.log('kline: ', data);
  });

  socket.on('markPriceUpdate', (data) => {
    console.log('markPriceUpdate: ', data);
  });

  socket.on('aggTrade', (data) => {
    console.log('aggTrade: ', data);
  });

  socket.on('24hrTicker', (data) => {
    console.log('24hrTicker: ', data);
  });

  socket.on('marketInfo', (data) => {
    console.log('marketInfo: ', data);
  });

  socket.on('markPriceArr', (data) => {
    console.log('markPriceArr: ', data);
  });

  socket.on('tickerArr', (data) => {
    console.log('tickerArr: ', data);
  });

  socket.on('marginRate', (data) => {
    console.log('marginRate: ', data);
  });
}
# Required installations:
# pip install python-socketio

import socketio

# WebSocket server URL
server_url = 'https://fawss.pi42.com/'

# Create a new Socket.IO client
sio = socketio.Client()

# Event listener for when the connection is open
@sio.event
def connect():
    print('Connected to WebSocket server')
    subscribe_to_topics()

# Event listener for when the connection is closed
@sio.event
def disconnect():
    print('Disconnected from WebSocket server')

# Event listener for errors
@sio.event
def connect_error(data):
    print('Socket.IO connection error:', data)

# Event listener for general errors
@sio.on('error')
def handle_error(data):
    print('Socket.IO error:', data)

# Function to subscribe to various WebSocket topics
def subscribe_to_topics():
    topics = ['btcinr@depth_0.1', 'btcinr@markPrice']  # List of topics to subscribe to

    # Subscribe to each topic
    sio.emit('subscribe', {
        'params': topics  # Sends the topics array to the WebSocket server
    })

    # Event listeners for updates on various data topics
    @sio.on('depthUpdate')
    def on_depth_update(data):
        print('depthUpdate:', data)

    @sio.on('kline')
    def on_kline(data):
        print('kline:', data)

    @sio.on('markPriceUpdate')
    def on_mark_price_update(data):
        print('markPriceUpdate:', data)

    @sio.on('aggTrade')
    def on_agg_trade(data):
        print('aggTrade:', data)

    @sio.on('24hrTicker')
    def on_24hr_ticker(data):
        print('24hrTicker:', data)

    @sio.on('marketInfo')
    def on_market_info(data):
        print('marketInfo:', data)

    @sio.on('markPriceArr')
    def on_mark_price_arr(data):
        print('markPriceArr:', data)

    @sio.on('tickerArr')
    def on_ticker_arr(data):
        print('tickerArr:', data)

    @sio.on('marginRate')
    def on_margin_rate(data):
        print('marginRate:', data)

# Connect to the WebSocket server
sio.connect(server_url)

# Keep the connection open
sio.wait()

Create Listen Key

POST /v1/retail/listen-key

Creates a new listen key for WebSocket connections.

A listen key is used to maintain a persistent connection to the WebSocket server, allowing you to receive real-time updates on user account data.

const baseUrl = process.env.PI42_BASE_URL + '/v1/retail/listen-key';

// Function to generate a signature for the request
const generateSignature = (params: object, apiSecret: string) => {
  return crypto
    .createHmac('sha256', apiSecret)
    .update(JSON.stringify(params))
    .digest('hex');
};

// Function to call Create Listen Key API
async function createListenKey(apiKey: string, apiSecret: string) {
  const params = {
    timestamp: Date.now().toString(),
  };

  const signature = generateSignature(params, apiSecret);

  try {
    const response = await axios.post(baseUrl, params, {
      headers: {
        'api-key': apiKey,
        'Content-Type': 'application/json',
        'signature': signature,
      },
    });
    console.log('Create Listen Key Response:', response.data);
    return response.data.listenKey;
  } catch (error) {
    console.error(
      'Error creating Listen Key:',
      error.response ? error.response.data : error.message
    );
    throw error; // Rethrow the error for further handling
  }
}
Parameter Type Required Description
timestamp string Yes The current timestamp in milliseconds to ensure request uniqueness and prevent replay attacks

The createListenKey function also requires an apiKey and apiSecret for authentication, and these are included in the headers of the request:

The function generates a signature using HMAC SHA-256 encryption of the request parameters and sends a POST request to the API endpoint to create a new listen key. If successful, it logs and returns the listen key; otherwise, it logs and throws the error for further handling.

Reponse

The response parameters are described below:

// Response

{
  "listenKey": "c44ec0b16e1e79d82473283a9736d2d037f105c39190ad48539fd6479a5b8ecc"
}
Parameter Description
listenKey The unique identifier for the Listen Key, used to maintain a persistent connection for real-time data streams. Example: c44ec0b16e1e79d82473283a9736d2d037f105c39190ad48539fd6479a5b8ecc.

Get Listen Key

POST /v1/retail/listen-key

Retrieves a new listen key for WebSocket connections.

A listen key is used to maintain a persistent WebSocket connection, allowing you to receive real-time updates.

async function getListenKey() {
    const endpoint = "/v1/retail/listen-key";

    // Call the postRequest function
    return await postRequest(endpoint, {});
}
def create_or_update_listen_key():
  timestamp = str(int(time.time() * 1000))

  params = {
      'timestamp': timestamp
  }

  # Convert the parameters to a query string (if signing a query string)
  data_to_sign = json.dumps(params, separators=(',', ':'))
  signature = generate_signature(api_secret, data_to_sign)

  # Headers for the request
  headers = {
      'api-key': api_key,
      'Content-Type': 'application/json',
      'signature': signature,
  }

  try:
      # Send the POST request to create or update a listen key
      response = requests.post(f'{listen_key_url}', json=params, headers=headers)
      response.raise_for_status()
      response_data = response.json()
      print('Listen key created or updated successfully:', json.dumps(response_data, indent=4))
  except requests.exceptions.HTTPError as err:
      print(f"Failed {response.status_code}: {response.text}")
Parameter Type Required Description
None N/A No Retrieves a new listen key for WebSocket connections.
A listen key is used to maintain a persistent WebSocket connection, allowing you to receive real-time updates.

Update Listen Key

PUT /v1/retail/listen-key

Updates the listen key for WebSocket connections.

Updating the listen key is necessary to maintain an active WebSocket connection and prevent disconnections due to inactivity.

Parameter Type Required Description
None N/A No Updates the listen key for WebSocket connections.
async function updateListenKey() {
    const endpoint = "/v1/retail/listen-key";

    // Call the getRequest function
    return await putRequest(endpoint, {});
}
def update_listen_key_expiry():
  timestamp = str(int(time.time() * 1000))

  params = {
      'timestamp': timestamp
  }

  data_to_sign = json.dumps(params, separators=(',', ':'))

  # Generate the signature using the provided helper function
  signature = generate_signature(api_secret, data_to_sign)

  # Headers for the PUT request
  headers = {
      'api-key': api_key,
      'signature': signature,
  }

  try:
      # Send the PUT request to update the listen key expiry
      response = requests.put(listen_key_url, json=params, headers=headers)
      print('Listen key expiry updated successfully:', response)
  except Exception as e:
      print(f"Failed {response.status_code}: {response.text}")

Response

The response contains a message as shown:

// Response
   Listen Key expiry time updated successfully.

Delete Listen Key

DELETE /v1/retail/listen-key

Deletes the listen key for WebSocket connections.

This action terminates the connection and stops the receipt of real-time updates.

async function deleteListenKey() {
    const endpoint = "/v1/retail/listen-key";

    // Call the deleteRequest function
    return await deleteRequest(endpoint, {});
}
def delete_listen_key():
  # Generate the current timestamp
  timestamp = str(int(time.time() * 1000))

  # Prepare the data for the request (listenKey is passed in the URL path)
  params = {
      'timestamp': timestamp
  }

  # Generate the signature based on the params
  data_to_sign = json.dumps(params, separators=(',', ':'))
  signature = generate_signature(api_secret, data_to_sign)

  # Headers for the DELETE request
  headers = {
      'api-key': api_key,
      'signature': signature,
      'accept': '*/*'
  }

  # Construct the full URL, inserting the listenKey into the path
  delete_listen_key_url = f"{base_url}/v1/retail/listen-key/"

  try:
      # Send the DELETE request to delete the listen key
      response = requests.delete(delete_listen_key_url, json=params, headers=headers)
      response.raise_for_status() # Raises an error for 4xx/5xx responses
      print('Listen key deleted successfully.')
  except requests.exceptions.HTTPError as err:
      print(f"Error: {err.response.text if err.response else err}")
  except Exception as e:
      print(f"An unexpected error occurred: {str(e)}")
Parameter Type Required Description
None N/A No Deletes the listen key for WebSocket connections

Response

The response body contains the message as shown in the snippet:

Listen key deleted successfully.

Error Codes

Pi42 APIs utilize a set of custom error codes, each associated with an HTTP status code and a specific error message. These codes help users pinpoint the exact issue that caused the request to fail.

Error Code HTTP Status Code Error Message API Endpoints
2303 400 Contract pair not found v1/exchange/update/leverage
2304 400 Leverage value out of range v1/exchange/update/leverage
2305 400 Leverage cannot be updated with open position v1/exchange/update/leverage
2306 400 Leverage cannot be updated with open orders v1/exchange/update/leverage
2307 500 Unable to update user leverage preference v1/exchange/update/leverage
2400 400 Interval value is invalid v1/market/klines
2401 500 Unable to fetch kline data v1/market/klines
2402 400 Invalid contract pair v1/market/depth/{contractPair}
v1/market/aggTrade/{contractPair}
v1/market/ticker24Hr/{contractPair}
2403 500 Unable to fetch depth update for given contract pair v1/market/depth/{contractPair}
2404 500 Unable to fetch trade update for given contract pair v1/market/aggTrade/{contractPair}
2405 500 Unable to fetch 24 hr ticker update for given contract pair v1/market/ticker24Hr/{contractPair}
2406 400 Invalid market is provided v1/market/marketInfo
2407 500 Unable to fetch market information v1/market/marketInfo
2500 400 Account id not found v1/positions/{positionStatus}
2501 500 Unable to fetch positions v1/positions/{positionStatus}
2502 400 No position exists with provided position id v1/positions
2503 400 Invalid contract pair v1/positions
2504 500 Unable to fetch position for provided position id v1/positions
3000 400 Incorrect device type in header values v1/order/place-order
3001 400 Symbol is missing v1/order/place-order
3003 400 Invalid leverage v1/order/place-order
3004 400 Invalid order side v1/order/place-order
3005 400 Order price not present v1/order/place-order
3006 400 Quantity precision should be less than {value} v1/order/place-order
3007 400 Price precision should be less than {value} v1/order/place-order
3008 400 Limit price is required v1/order/place-order
3009 400 Limit price is out of allowed values v1/order/place-order
3010 400 Order quantity is out of range v1/order/place-order
3011 400 Order declined, TP/SL will be activated instantly v1/order/place-order
3012 400 Margin asset {asset} is not supported for this contract v1/order/place-order
3013 400 Order placement for this contract pair is not allowed as there is already an open order v1/order/place-order
3014 400 Order placement for this contract pair is not allowed as there is already an open position v1/order/place-order
3015 400 Take profit/Stop loss orders cannot be placed while reducing position v1/order/place-order
3018 400 Insufficient margin v1/order/place-order
3019 400 Ref id already exists v1/order/place-order
3020 400 API request limit exceeded v1/order/place-order
3021 400 Order type is not supported v1/order/place-order
3022 500 Order execution error v1/order/place-order
3023 500 Order cancellation error v1/order/cancel-order