# REST API

## Access Preparation

If you need to use the API, please log in to the [web page](https://www.bitget.com/login), then apply the API key application and complete the permission configuration, and then develop and trade according to the details of this document.

You can click [API Key Management](https://www.bitget.com/account/newapi) to create an API Key after login.

Each UID can create 10 Api Keys, and each Api Key can set permissions as read only or read/write.

### Sub-account API Key

Sub-accounts (virtual sub-accounts and standard sub-accounts) can create and manage their own API Keys independently, without requiring the main account to operate on their behalf.

**Prerequisite**: The main account must enable the **API Key Management** permission for the sub-account. This setting is disabled by default. The main account can configure it under sub-account permission settings.

Once enabled, the sub-account can perform the following operations on its own API Keys:

- Create API Key
- View API Key
- Edit API Key permissions
- Delete API Key

The main account retains full control and can view, edit, or delete any sub-account's API Keys at any time.

The permissions are described as follows:

- **Read-Only permission**: Read permission authorized to query data, such as market data.
- **Trade permission**: Transaction permission authorized to call the interface of placing and cancelling orders.
- **Transfer permission**: With this permission it authorized to transfer coins between accounts.
- **Withdraw permission**: Authorized to withdraw assets from Bitget account. Note that you can only withdraw coins through a whitelisted IP address.

After successfully created the API key, please remember the following information:

- `APIKey` — The identity of API transactions, generated by a random algorithm.
- `SecretKey` — The private key is randomly generated by the system and used for [Signature](#signature) generation.
- `Passphrase` — The password is set by the user. If you forgot the Passphrase, it cannot be retrieved and the APIKey needs to be recreated.

:::tip{title="Security"}
For security reasons, it is strongly recommended that you bind to an IP address when you create the API key.
:::

:::tip{title="Risk Warning"}
These three keys are highly related to account security. Please keep in mind **DO NOT DISCLOSE SecretKey and Passphrase** to anyone at any circumstances, even with Bitget employees. Leaking any one of these three keys may cause the loss of your assets. If you find by any chance that the APIKey is compromised, please delete the APIKey as soon as possible.
:::

## API Domain

You can use different domain as below Rest API.

| Domain Name | API | Description |
|-------------|-----|-------------|
| REST Domain 1 | https://api.bitget.com | Main Domain |
| websocket Domain | wss://ws.bitget.com/v2/ws/public | Main Domain, Public channel |
| websocket Domain | wss://ws.bitget.com/v2/ws/private | Main Domain, Private channel |

## Interface Type

Interfaces are mainly divided into two types:

- Public Interface
- Private Interface

**Public Interface**

The public interface can be used to obtain configuration information and market data. Public requests can be used without authentication.

**Private Interface**

The private interface can be used for order management and account management. Every private request must be [Signed](#signature).

The private interface will be verified from server side with your API Key info.

## Access Restriction

This chapter mainly focuses on access restrictions:

- Rest API will return 429 status when the access exceeds the frequency limit: the request is too frequent.

**Rest API**

The rate limit of interfaces is based on UID or IP. You can get detailed information from the separated API document page.

Frequency limit rules:

1. The rate limit of each API endpoint is marked on the doc page;
2. The rate limit of each API interface is calculated independently;
3. The overall rate limit is 6000/IP/Min

## SDK

We support below languages

| Language | Code Path |
|:---------|:----------|
| [Java](https://github.com/BitgetLimited/v3-bitget-api-sdk/tree/master/bitget-java-sdk-api) | Check package `com.bitget.openapi.api.v2` |
| [Python](https://github.com/BitgetLimited/v3-bitget-api-sdk/tree/master/bitget-python-sdk-api) | Check `v2` |
| [NodeJs](https://github.com/BitgetLimited/v3-bitget-api-sdk/tree/master/bitget-node-sdk-api) | Check `src/lib/v2` |
| [Golang](https://github.com/BitgetLimited/v3-bitget-api-sdk/tree/master/bitget-golang-sdk-api) | Check `pkg/client/v2` |
| [PHP](https://github.com/BitgetLimited/v3-bitget-api-sdk/tree/master/bitget-php-sdk-api) | Check `src/api/v2` |

## Signature

### API Verification

#### Initiate a request

The header of all REST requests must contain the following http headers:

- **ACCESS-KEY**: API KEY as a string
- **ACCESS-SIGN**: Sign with base64 encoding (see [HMAC](#hmac-signature-demo-code) sample code).
- **ACCESS-TIMESTAMP**: Timestamp of your request. Value equals to milliseconds since Epoch.
- **ACCESS-PASSPHRASE**: The password you set when created the API KEY.
- **Content-Type**: Please set to `application/json` for all POST request
- **locale**: Support language such as: Chinese (zh-CN), English (en-US)

#### How to get ACCESS-TIMESTAMP

```java title="Java"
Long timestamp = System.currentTimeMillis();
```

```python title="Python"
import time
time.time_ns() / 1000000
```

```go title="Go"
import "time"
int64(time.Now().UnixNano() / 1000000)
```

```javascript title="JavaScript"
Math.round(new Date())
```

```php title="PHP"
microtime(true) * 1000;
```

### Generate Signature

The request header of ACCESS-SIGN is to encrypt **timestamp + method.toUpperCase() + requestPath + "?" + queryString + body** string (+ means string concat) by **HMAC SHA256** algorithm with **secretKey**, and encode the encrypted result through **BASE64**.

#### Description of each parameter in the signature

- **timestamp**: Same as ACCESS-TIMESTAMP request header. Value equals to milliseconds since Epoch.
- **method**: Request method (POST/GET), all uppercase.
- **requestPath**: Request interface path.
- **queryString**: The query string in the request URL (the request parameter after the `?`).
- **body**: The request body in string format. If the request body is empty (usually a GET request), the body can be omitted.

**If the queryString is empty, signature content:**

```
timestamp + method.toUpperCase() + requestPath + body
```

**If the queryString not empty, signature content:**

```
timestamp + method.toUpperCase() + requestPath + "?" + queryString + body
```

#### Sample Code

Get contract depth information, let's take BTCUSDT as an example:

- timestamp = 16273667805456
- method = "GET"
- requestPath = "/api/mix/v2/market/depth"
- queryString = "?limit=20&symbol=BTCUSDT"

Generate the content to be signed:

```
16273667805456GET/api/mix/v2/market/depth?limit=20&symbol=BTCUSDT
```

Contract order, take BTCUSDT as an example:

- timestamp = 16273667805456
- method = "POST"
- requestPath = "/api/v2/mix/order/place-order"
- body = `{"productType":"usdt-futures","symbol":"BTCUSDT","size":"8","marginMode":"crossed","side":"buy","orderType":"limit","clientOid":"channel#123456"}`

Generate the content to be signed:

```
16273667805456POST/api/v2/mix/order/place-order{"productType":"usdt-futures","symbol":"BTCUSDT","size":"8","marginMode":"crossed","side":"buy","orderType":"limit","clientOid":"channel#123456"}
```

#### Steps to generate the final signature

**HMAC**

1. Use the private key **secretKey** to encrypt the string to be signed with HMAC SHA256
2. Base64 encoding for Signature

RSA signature is also supported: use the RSA private key to encrypt the string with SHA-256, then Base64 encode the result.

### HMAC Signature Demo Code

```java title="Java"
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class CheckSign {
  private static final String secretKey = "";

  public static String generate(String timestamp, String method, String requestPath,
                                String queryString, String body, String secretKey)
          throws Exception {
    method = method.toUpperCase();
    body = body == null || body.isBlank() ? "" : body;
    queryString = queryString == null || queryString.isBlank() ? "" : "?" + queryString;
    String preHash = timestamp + method + requestPath + queryString + body;
    Mac mac = Mac.getInstance("HmacSHA256");
    mac.init(new SecretKeySpec(secretKey.getBytes("UTF-8"), "HmacSHA256"));
    return Base64.getEncoder().encodeToString(mac.doFinal(preHash.getBytes("UTF-8")));
  }
}
```

```python title="Python"
import hmac
import base64
import json
import time

def sign(message, secret_key):
    mac = hmac.new(bytes(secret_key, encoding='utf8'),
                   bytes(message, encoding='utf-8'),
                   digestmod='sha256')
    return base64.b64encode(mac.digest())

def pre_hash(timestamp, method, request_path, body):
    return str(timestamp) + str.upper(method) + request_path + body

def parse_params_to_str(params):
    params = sorted(params.items(), key=lambda x: x[0])
    url = '?' + '&'.join(f'{k}={v}' for k, v in params)
    return '' if url == '?' else url

# GET example
timestamp = "1684814440729"
request_path = "/api/v2/mix/account/account"
query_string = "marginCoin=usdt&symbol=btcusdt"
sign_content = pre_hash(timestamp, "GET", request_path + "?" + query_string, "")
print(sign(sign_content, API_SECRET_KEY))
```

## Request Interaction

All requests are based on the HTTPS protocol, and the Content-Type in the POST request header should be set to `application/json`.

### Request Interaction Description

- **Request parameters**: Encapsulate parameters according to the interface request parameters.
- **Submit request parameters**: Submit the encapsulated request parameters to the server through GET/POST.
- **Server Response**: The server first performs parameter security verification on the user request data, and returns the response data to the user in JSON format according to the business logic after passing the verification.
- **Data processing**: Process the server response data.

#### Success

HTTP status code 200 indicates a successful response and may contain content. If the response contains content, it will be displayed in the corresponding return content.

#### Common Error Codes

- 400 Bad Request – Invalid request format
- 401 Unauthorized – Invalid API Key
- 403 Forbidden – You do not have access to the requested resource
- 404 Not Found – No request found
- 429 Too Many Requests – Requests are too frequent and are limited by the system
- 500 Internal Server Error – We had a problem with our server

If it fails, the return body usually indicates the error message. See also the [Error Code](/docs/api/error-code) page.

### Standard Specification

#### Timestamp

The unit of ACCESS-TIMESTAMP in the HTTP request signature is milliseconds. The timestamp of the request must be within 30 seconds of the API server time, otherwise the request will be considered expired and rejected. If there is a large deviation between the local server time and the API server time, we recommend that you compare the timestamp by querying the API server time.

#### Frequency Limiting Rules

If the request is too frequent, the system will automatically limit the request and return the 429 too many requests status code.

- **Public interface**: For the market information interfaces, the unified rate limit is a maximum of 20 requests per second.
- **Authorization interface**: apikey is used to restrict the calling of authorization interfaces, refer to the frequency restriction rules of each interface for frequency restriction.

#### Request Format

There are currently only two supported request methods: GET and POST

- **GET**: The parameters are transmitted to the server in the path through queryString.
- **POST**: The parameters are sent to the server in JSON format.
