Call Your First Authenticated API
With the Access Key and Secret Key from your issued API Key, you can call authenticated APIs.
Introduction
Once you have issued your API Key, you are ready to generate an authentication token and call the Exchange API. This guide explains how to generate an authentication token using a Shell script and how to call an authenticated API using cURL.
- Singapore (sg): https://sg-api.upbit.com
- Indonesia (id): https://id-api.upbit.com
- Thailand (th): https://th-api.upbit.com
Understanding the Authentication Method
Refer to the Authentication documentation for details on the structure and creation of authentication tokens used in Upbit’s REST API and WebSocket. Reviewing the structure and process of token generation in advance will help you proceed smoothly with this guide.
Shell Script for Generating an Authentication Token
While cURL is a powerful HTTP tool, it does not natively support generating tokens or handling hashes and parameters required for Upbit authentication. To address this, this guide shows how to use a Shell script to generate authentication tokens in terminal environments (macOS/Linux shell or Windows cmd/PowerShell).
On Windows, you can’t run shell scripts directly in PowerShell or CMD. Install a Bash environment—such as Git Bash or WSL (Windows Subsystem for Linux)—and run the scripts there. Please refer to one of the setup guides below to configure your Bash environment.
wsl --install
Once your Bash environment is set up, you can run shell scripts using Bash commands as shown below.
bash auth_curl.sh "curl --request GET --url 'https://{region}-api.upbit.com/v1/accounts' --header 'accept: application/json'"
Before writing and running the Shell script, make sure that both jq
and OpenSSL
(for cryptography) are installed on your computer. Refer to the OS-specific installation guides below to check your environment.
jq
and openssl
are pre-installed. You can check if they are available by running the following commands in your terminal:If the version information appears, the utilities are properly installed and ready to use. The version numbers may vary depending on your environment.jq --version
openssl --version
If either utility is not installed, you can install it via Homebrew with the following commands:
brew install jq
brew install openssl
cmd
or PowerShell
, check if the utilities are installed by running:
If version information is displayed, they are correctly installed and ready for use. Version numbers may differ by environment.jq --version
openssl --version
If not installed, follow these steps to set them up:
Install jq
- Download the Windows jq binary from https://stedolan.github.io/jq/download/
- Save it to a desired folder and add that folder to your system PATH environment variable.
Install openssl
- Download the Windows OpenSSL installer from https://slproweb.com/products/Win32OpenSSL.html
- After installation, add the directory (e.g.,
C:Program FilesOpenSSL-Win64in
) to your PATH environment variable.
sudo apt update
sudo apt install jq openssl
Copy the Shell script below and save it as a file, such as auth_curl.sh
. Be sure to replace ACCESS_KEY and SECRET_KEY with your issued API Key values before saving the file. This script generates an Upbit authentication token and:
- Accepts a cURL command as an input argument and generates the required authentication header using the API Key and request parameters.
- Outputs a cURL command with the authentication header included. Copy and execute this command to call the authenticated API.
#!/bin/bash
ACCESS_KEY="YOUR_ACCESS_KEY"
SECRET_KEY="YOUR_SECRET_KEY"
INPUT_CURL=$1
METHOD=$(echo "$INPUT_CURL" | sed -n "s/.*-X \([A-Z]*\).*/\1/p")
URL=$(echo "$INPUT_CURL" | sed -n "s/.*--url '\([^']*\)'.*/\1/p")
BODY=$(echo "$INPUT_CURL" | sed -n "s/.*--data '\([^']*\)'.*/\1/p")
if [[ "$METHOD" == "POST" ]]; then
QUERY_STRING=$(echo "$BODY" | tr -d '{}' | sed 's/\"//g' | tr ',' '&' | tr ':' '=' | sed 's/ //g')
elif [[ "$METHOD" == "GET" || "$METHOD" == "DELETE" ]]; then
QUERY_STRING=$(echo "$URL" | awk -F '?' '{print $2}')
fi
if [ -z "$QUERY_STRING" ]; then
QUERY_HASH=""
else
QUERY_HASH=$(echo -n "$QUERY_STRING" | openssl dgst -sha512 | sed 's/^.* //')
fi
NONCE=$(uuidgen)
HEADER='{"alg":"HS512","typ":"JWT"}'
PAYLOAD=$(jq -n --arg ak "$ACCESS_KEY" --arg n "$NONCE" --arg qh "$QUERY_HASH" --arg alg "SHA512" \
'{access_key: $ak, nonce: $n, query_hash: $qh, query_hash_alg: $alg}')
HEADER_BASE64=$(echo -n "$HEADER" | openssl base64 -A | tr '+/' '-_' | tr -d '=')
PAYLOAD_BASE64=$(echo -n "$PAYLOAD" | openssl base64 -A | tr '+/' '-_' | tr -d '=')
SIGNATURE=$(echo -n "$HEADER_BASE64.$PAYLOAD_BASE64" | \
openssl dgst -sha512 -hmac "$SECRET_KEY" -binary | \
openssl base64 -A | tr '+/' '-_' | tr -d '=')
JWT="$HEADER_BASE64.$PAYLOAD_BASE64.$SIGNATURE"
CLEANED_CURL=$(echo "$INPUT_CURL" | sed "s/-H 'Authorization: Bearer [^']*'//g")
if echo "$CLEANED_CURL" | grep -q "Content-Type"; then
FINAL_CURL=$(echo "$CLEANED_CURL" | sed "s/curl /curl -H 'Authorization: Bearer $JWT' /")
else
FINAL_CURL=$(echo "$CLEANED_CURL" | sed "s/curl /curl -H 'Authorization: Bearer $JWT' -H 'Content-Type: application\/json' /")
fi
echo "[+] Signed curl command:"
echo "$FINAL_CURL"
Since utilities such as jq and openssl are used in the process of generating an authentication token, you need to grant execute permissions in macOS and other UNIX-based environments by running the following command.
chmod +x auth_curl.sh
Get Account Balance
As your first authenticated API call, let’s query your account balance using the Get Account Balances. Pass the cURL command for this API as an argument to the saved Shell script. You can get the example cURL request for this API in the Reference section.
% ./auth_curl.sh "curl --request GET --url https://{region}-api.upbit.com/v1/accounts --header 'accept: application/json'"
[+] Signed curl command:
curl -H 'Authorization: Bearer eyJhbGciO...TvcqiPUoNTg' --request GET --url https://{region}-api.upbit.com/v1/accounts --header 'accept: application/json'
The script outputs a cURL command with the authentication header. Copy and run the command in your terminal to see a response like the following:
[{"currency": "{fiat}","balance": "10000.0","locked": "0.0","avg_buy_price": "0","avg_buy_price_modified": false,"unit_currency": "{fiat}"},{"currency": "BTC","balance": "2.0","locked": "0.0","avg_buy_price": "1400000","avg_buy_price_modified": false,"unit_currency": "{fiat}"}]
Creating a Bid Order
Now let’s try a POST request to place a buy order. For example, you can place a limit buy order at a sufficiently low price in the {fiat}-BTC
market. Pass the following cURL request (for Create Order) to the Shell script. You can get back a cURL with the authentication token included. (The JWT part is abbreviated as ...
)
% ./auth_curl.sh "curl -X POST --url 'https://{region}-api.upbit.com/v1/orders' --header 'accept: application/json' --header 'content-type: application/json' --data '{\"market\":\"{fiat}-BTC\",\"side\":\"bid\",\"volume\":\"0.0001\",\"price\":\"500000\",\"ord_type\":\"limit\"}'"
[+] Signed curl command:
curl -H 'Authorization: Bearer eyJhbGciOi...a0uejONDLQ' -X POST --url 'https://{region}-api.upbit.com/v1/orders' --header 'accept: application/json' --header 'content-type: application/json' --data '{"market":"{fiat}-BTC","side":"bid","volume":"0.0001","price":"500000","ord_type":"limit"}'
Copy the generated cURL command, paste it in your terminal, and execute it to place the order in the {fiat}-BTC
market.
Understanding Authentication Token Generation
The following lines in the provided Shell script generate a JWT token:
if [ -z "$QUERY_STRING" ]; then
QUERY_HASH=""
else
QUERY_HASH=$(echo -n "$QUERY_STRING" | openssl dgst -sha512 | sed 's/^.* //')
fi
NONCE=$(uuidgen)
HEADER='{"alg":"HS512","typ":"JWT"}'
PAYLOAD=$(jq -n --arg ak "$ACCESS_KEY" --arg n "$NONCE" --arg qh "$QUERY_HASH" --arg alg "SHA512" \
'{access_key: $ak, nonce: $n, query_hash: $qh, query_hash_alg: $alg}')
HEADER_BASE64=$(echo -n "$HEADER" | openssl base64 -A | tr '+/' '-_' | tr -d '=')
PAYLOAD_BASE64=$(echo -n "$PAYLOAD" | openssl base64 -A | tr '+/' '-_' | tr -d '=')
SIGNATURE=$(echo -n "$HEADER_BASE64.$PAYLOAD_BASE64" | \
openssl dgst -sha512 -hmac "$SECRET_KEY" -binary | \
openssl base64 -A | tr '+/' '-_' | tr -d '=')
JWT="$HEADER_BASE64.$PAYLOAD_BASE64.$SIGNATURE"
This code hashes the query string, then creates a JWT header, payload, and signature following Upbit’s authentication token format. You can see that the payload includes the fields access_key
, nonce
, query_hash
, and query_hash_alg
.
For POST requests with no query string, the script converts the JSON body into a query string, hashes it, and then creates the authentication token in the same way as for GET requests:
(Example)
:
is encoded as %3A
and +
is encoded as %2B.
BODY=$(echo "$INPUT_CURL" | sed -n "s/.*--data '\([^']*\)'.*/\1/p")
if [[ "$METHOD" == "POST" ]]; then
QUERY_STRING=$(echo "$BODY" | tr -d '{}' | sed 's/"//g' | tr ',' '&' | tr ':' '=' | sed 's/ //g')
elif [[ "$METHOD" == "GET" || "$METHOD" == "DELETE" ]]; then
QUERY_STRING=$(echo "$URL" | awk -F '?' '{print $2}')
fi
Wrapping Up
We used cURL to make quick calls to the Upbit API. After you’ve tested enough to understand the API, set up a real development environment to implement your trading strategy. See the Development Environment Setup Guide to configure your language environment instead of cURL, or read REST API Integration Best Practices for more advanced integration patterns.
Updated 6 days ago