Market Ask Order Tutorial

This tutorial shows how to create a market sell order for digital assets that a user already holds, using the Upbit API.

Tutorial Example Code Guide
This tutorial includes step-by-step partial code and API call/response examples to aid user understanding.
The full code examples can be found in the Recipes menu.
Click the button above to navigate to the full code Recipe page of this tutorial.

Get Started

The typical steps an Upbit user follows when selling digital assets are as follows:

  1. Select the digital asset to sell from the user’s holdings.
  2. Check the tradability information of the selected digital asset to confirm the order conditions.
  3. Enter the quantity and place a market sell order.
  4. The order is executed.
  5. Verify the executed order.

In this guide, you will implement a scenario where the user retrieves their holdings and sells 50% of the selected digital asset at market price. Python example code is provided.

This guide includes the process of selling digital assets with real funds.
If you copy and run the code as written here, you may sell your actual assets. If you do not wish to sell digital assets, review only the API usage instructions and avoid calling any functions that execute real sell orders.
To create a sell order, you must first buy the digital asset.
If you need to acquire digital assets before proceeding, please follow the Limit Bid Order Tutorial to purchase them, and then continue with this guide.
Check the proper endpoint based on your region.
The examples in this page is written using Singapore fiat code(SGD). Set the quote currency to match your region. The base_url differs by country/region. Make sure to specify the correct region value for your environment.

- Singapore (sg): https://sg-api.upbit.com
- Indonesia (id): https://id-api.upbit.com
- Thailand (th): https://th-api.upbit.com

Authentication Guide

Please refer to the Authentication document and the recipe below to add the authentication header for all Exchange API calls.


Check Owned Assets and Select Assets to Sell

Implement a function that calls Get Balances held in the user's Upbit account.

def get_pair_and_balance_from_account(currency: str) -> Mapping:
    jwt_token = _create_jwt(access_key, secret_key)
    url = "https://sg-api.upbit.com/v1/accounts"
    headers = {
        "Authorization": "Bearer {jwt_token}".format(jwt_token=jwt_token),
        "Content-Type": "application/json"
    }
    response = requests.get(url, headers=headers).json()
    trading_pair_list = [item for item in response if item.get("currency") == currency]
    if len(trading_pair_list) == 0:
        raise ValueError("Currency {currency} is not found".format(currency=currency))
    else:
        pair = trading_pair_list[0]
        return {
            "pair": "{unit_currency}-{currency}".format(unit_currency=pair.get('unit_currency'), currency=pair.get('currency')),
            "balance": pair.get('balance')
        }

When the function runs, it retrieves information about all assets in the user’s Upbit account. If the user holds an asset matching the input currency, the function returns its trading pair and available quantity.

[
  {
    "currency": "SGD",
    "balance": "1000000.0",
    "locked": "0.0",
    "avg_buy_price": "0",
    "avg_buy_price_modified": false,
    "unit_currency": "SGD"
  },
  {
    "currency": "BTC",
    "balance": "2.0",
    "locked": "0.0",
    "avg_buy_price": "101000",
    "avg_buy_price_modified": false,
    "unit_currency": "SGD"
  }
]

Check Order Chance

Implement a function that calls the Get Available Order Information API to check whether the selected digital asset can be traded and to retrieve the order conditions required for creating a market sell order..

def get_order_chance(trading_pair: str) -> Mapping:
    params = {
        "market": trading_pair
    }
    query_string = _build_query_string(params)
    jwt_token = _create_jwt(access_key, secret_key, query_string)
    url = "https://sg-api.upbit.com/v1/orders/chance"
    headers = {
        "Authorization": "Bearer {jwt_token}".format(jwt_token=jwt_token),
        "Content-Type": "application/json"
    }
    response = requests.get(url, headers=headers, params=params).json()
    min_total = response.get("market").get("ask").get("min_total")
    ask_types = response.get("market").get("ask_types")
    if "market" not in ask_types:
        raise ValueError("This pair does not support market order. {ask_types}".format(ask_types=ask_types))
    else:
        order_type_market = True

    return {
        "order_type_market": order_type_market,
        "min_total": min_total
    }

When the function is executed, the order availability information for the user-input pair can be checked.

{
  "bid_fee": "0.0025",
  "ask_fee": "0.0025",
  "maker_bid_fee": "0.0025",
  "maker_ask_fee": "0.0025",
  "market": {
    "id": "SGD-BTC",
    "name": "BTC/SGD",
    "order_types": [
      "limit"
    ],
    "order_sides": [
      "ask",
      "bid"
    ],
    "bid_types": [
      "best_fok",
      "best_ioc",
      "limit",
      "limit_fok",
      "limit_ioc",
      "price"
    ],
    "ask_types": [
      "best_fok",
      "best_ioc",
      "limit",
      "limit_fok",
      "limit_ioc",
      "market"
    ],
    "bid": {
      "currency": "SGD",
      "min_total": "1"
    },
    "ask": {
      "currency": "BTC",
      "min_total": "1"
    },
    "max_total": "1000000",
    "state": "active"
  },
  "bid_account": {
    "currency": "SGD",
    "balance": "0",
    "locked": "0",
    "avg_buy_price": "0",
    "avg_buy_price_modified": true,
    "unit_currency": "SGD"
  },
  "ask_account": {
    "currency": "BTC",
    "balance": "0",
    "locked": "0",
    "avg_buy_price": "0",
    "avg_buy_price_modified": false,
    "unit_currency": "SGD"
  }
}

Create Order

To create a market sell order for a digital asset at the current price, the following values are required:

  1. The trading pair of the digital asset to sell (e.g., SGD-BTC)
  2. Order side (buy or sell)
  3. Order type (limit, market, etc.)
  4. Quantity of the digital asset to sell

This tutorial creates a market sell order, so the order side and order type are predefined. Therefore, you can calculate the pair and quantity of the digital asset to sell and create a market sell order.

Implement a function that creates a market sell order. This function calls the Create Order API and returns the UUID of the newly created order.

def create_order(
    market: str,
    volume: str
) -> str:
    body = {
        "market": market,
        "side": "ask",
        "ord_type": "market",
        "volume": volume
    }
    query_string = _build_query_string(body)
    jwt_token = _create_jwt(access_key, secret_key, query_string)
    url = "https://sg-api.upbit.com/v1/orders"
    headers = {
        "Authorization": "Bearer {jwt_token}".format(jwt_token=jwt_token),
        "Content-Type": "application/json"
    }
    response = requests.post(url, headers=headers, json=body).json()
    uuid = response.get('uuid')
    if uuid is None:
        raise ValueError("Please check the response. {response}".format(response=response))
    else:
        return uuid

Check Order Status

Implement a function that calls the Get Order API to check the current status of an order using the UUID returned at the time of creation..

def get_order(uuid: str) -> Mapping:
    params = {
        "uuid": uuid
    }
    query_string = _build_query_string(params)
    jwt_token = _create_jwt(access_key, secret_key, query_string)
    url = "https://sg-api.upbit.com/v1/order"
    headers = {
        "Authorization": "Bearer {jwt_token}".format(jwt_token=jwt_token),
        "Content-Type": "application/json"
    }
    response = requests.get(url, headers=headers, params=params).json()
    return response

When executed, the function returns the order details matching the UUID provided by the user. You can check the current status of the order through the state field, such as whether it is waiting or done.

{
  "market": "SGD-BTC",
  "uuid": "9ca023a5-851b-4fec-9f0a-48cd83c2eaae",
  "side": "ask",
  "ord_type": "limit",
  "price": "153559.00",
  "state": "done",
  "created_at": "2025-07-04T15:00:00",
  "volume": "1.0",
  "remaining_volume": "0.0",
  "executed_volume": "1.0",
  "reserved_fee": "0.0",
  "remaining_fee": "0.0",
  "paid_fee": "383.8975",
  "locked": "0.0",
  "prevented_volume": "0",
  "prevented_locked": "0",
  "trades_count": 1,
  "trades": [
    {
      "market": "SGD-BTC",
      "uuid": "9e8f8eba-7050-4837-8969-cfc272cbe083",
      "price": "153559.00",
      "volume": "1.0",
      "funds": "153559.00",
      "side": "ask"
    }
  ]
}

Full Code Example

The complete code for creating a market sell order is as follows. Using the currency value provided by the user, the code first checks whether the specified digital asset is held in the account and gets its available quantity. It then validates whether a market sell order can be created. If eligible, the code creates a market sell order for 50% of the available balance..

from urllib.parse import unquote, urlencode
from collections.abc import Mapping
from typing import Any
import hashlib
import uuid
import jwt # PyJWT
import requests
from decimal import Decimal, ROUND_DOWN

access_key = "<YOUR_ACCESS_KEY>"
secret_key = "<YOUR_SECRET_KEY>"

# Please add the logic here to generate the JWT authentication token.

def get_pair_and_balance_from_account(currency: str) -> Mapping:
    jwt_token = _create_jwt(access_key, secret_key)
    url = "https://sg-api.upbit.com/v1/accounts"
    headers = {
        "Authorization": "Bearer {jwt_token}".format(jwt_token=jwt_token),
        "Content-Type": "application/json"
    }
    response = requests.get(url, headers=headers).json()
    trading_pair_list = [item for item in response if item.get("currency") == currency]
    if len(trading_pair_list) == 0:
        raise ValueError("Currency {currency} is not found".format(currency=currency))
    else:
        pair = trading_pair_list[0]
        return {
            "pair": "{unit_currency}-{currency}".format(unit_currency=pair.get('unit_currency'), currency=pair.get('currency')),
            "balance": pair.get('balance')
        }

def get_order_chance(trading_pair: str) -> Mapping:
    params = {
        "market": trading_pair
    }
    query_string = _build_query_string(params)
    jwt_token = _create_jwt(access_key, secret_key, query_string)
    url = "https://sg-api.upbit.com/v1/orders/chance"
    headers = {
        "Authorization": "Bearer {jwt_token}".format(jwt_token=jwt_token),
        "Content-Type": "application/json"
    }
    response = requests.get(url, headers=headers, params=params).json()
    min_total = response.get("market").get("ask").get("min_total")
    ask_types = response.get("market").get("ask_types")
    if "market" not in ask_types:
        raise ValueError("This pair does not support market order. {ask_types}".format(ask_types=ask_types))
    else:
        order_type_market = True

    return {
        "order_type_market": order_type_market,
        "min_total": min_total
    }

def create_order(
    trading_pair: str,
    volume: str
) -> str:
    body = {
        "market": trading_pair,
        "side": "ask",
        "ord_type": "market",
        "volume": volume
    }
    query_string = _build_query_string(body)
    jwt_token = _create_jwt(access_key, secret_key, query_string)
    url = "https://sg-api.upbit.com/v1/orders"
    headers = {
        "Authorization": "Bearer {jwt_token}".format(jwt_token=jwt_token),
        "Content-Type": "application/json"
    }
    response = requests.post(url, headers=headers, json=body).json()
    uuid = response.get('uuid')
    if uuid is None:
        raise ValueError("Please check the response. {response}".format(response=response))
    else:
        return uuid

def get_order(uuid: str) -> Mapping:
    params = {
        "uuid": uuid
    }
    query_string = _build_query_string(params)
    jwt_token = _create_jwt(access_key, secret_key, query_string)
    url = "https://sg-api.upbit.com/v1/order"
    headers = {
        "Authorization": "Bearer {jwt_token}".format(jwt_token=jwt_token),
        "Content-Type": "application/json"
    }
    response = requests.get(url, headers=headers, params=params).json()
    return response

# # If you uncomment and run this code, a real market sell order may be created. Please double-check before executing.  

# if __name__ == "__main__":
#     currency = "<Enter your currency>"
#     account_info = get_pair_and_balance_from_account(currency)
#     trading_pair = account_info.get("pair")

#     balance = account_info.get("balance")
#     order_chance = get_order_chance(trading_pair)
#     fifty_percent_volume = str((Decimal(balance) * Decimal("0.5")).quantize(Decimal("1e-8"), rounding=ROUND_DOWN))

#     if order_chance["order_type_market"]:
#         order_uuid = create_order(market_pair, fifty_percent_volume)
#         order_info = get_order(order_uuid)
#         print("order_info: {order_info}".format(order_info=order_info))
#     else:
#         raise ValueError("This pair does not support market order. {order_chance}".format(order_chance=order_chance))