# REST API

## 接入准备

如需使用 API，请先 [登录](https://www.bitget.com/zh-CN/login) 网页端，完成 API Key 的申请和权限配置，再据此文档详情进行开发和交易。

您可以点击 [API Key 管理](https://www.bitget.com/zh-CN/account/newapi) 创建 API Key。

每个 UID 可创建 10 组 Api Key，每个 Api Key 可对应设置读取、交易等权限。

### 子账户 API Key

子账户（虚拟子账户及普通子账户）支持自行创建和管理 API Key，无需母账户代为操作。

**前提条件**：母账户需为该子账户开启 **API Key 管理** 权限开关，该开关默认关闭，母账户可在子账户权限设置中进行配置。

开启后，子账户可对自己的 API Key 执行以下操作：

- 创建 API Key
- 查看 API Key
- 编辑 API Key 权限
- 删除 API Key

母账户保留全局管控能力，可随时查看、编辑或删除任意子账户的 API Key。

权限说明如下：

- **读取权限**：读取权限用于对数据的查询，例如：行情数据。
- **交易权限**：交易权限用于下单、撤单等接口。
- **划转权限**：划转权限用于在用户账户之间划转加密货币。
- **提币权限**：提币权限用于从 Bitget 账户转出资产。请注意，您只能通过 IP 白名单提币。

创建成功后请务必记住以下信息：

- `APIKey` — API 交易的身份标识，随机算法生成。
- `SecretKey` — 私钥，由系统随机生成，用于 [签名](#签名) 的生成。
- `Passphrase` — 口令，由用户自己设定。需要注意的是，Passphrase 忘记之后是无法找回的，需要重新创建 APIKey。

:::tip{title="安全提示"}
出于安全考虑，在创建 API Key 时强烈建议您绑定 IP 地址。
:::

:::tip{title="风险提示"}
这三个密钥与账号安全密切相关，请牢记 **Passphrase**，无论何时都请勿向他人透露。这三个密钥任意一个泄露可能会造成您的资产损失，若发现 APIKey 泄露请尽快删除该 APIKey。
:::

## API 域名

您可以自行使用 Rest API 接入方式进行操作。

| 域名 | API | 描述 |
|------|-----|------|
| REST 域名 1 | https://api.bitget.com | 主域名 |
| websocket 公共频道 | wss://ws.bitget.com/v2/ws/public | 主域名，公共频道 |
| websocket 私有频道 | wss://ws.bitget.com/v2/ws/private | 主域名，私有频道 |

## 接口类型

本章节主要为接口类型分以下两个方面：

- 公共接口
- 私有接口

**公共接口**

公共接口可用于获取配置信息和行情数据。公共请求无需认证即可调用。

**私有接口**

私有接口可用于订单管理和账户管理。每个私有请求必须使用规范的验证形式进行 [签名](#签名)。

私有接口需要使用您的 APIKey 进行验证。

## 访问限制

本章节主要为访问限制：

- Rest API 当访问超过频率限制时，将返回 429 状态：请求太频繁。

**Rest API**

有些接口是根据 UID 进行限频，有些是根据 IP 进行限频，具体规则会在各接口文档中标注。

限速规则：

1. 各 API 端口频率限制规则在文档有标注；
2. 各 API 接口的限频互相独立计算；
3. 总体有 6000 次/IP/分钟的限频规则

## SDK

支持以下开发语言

| SDK 链接 | 代码路径 |
|:---------|:---------|
| [Java](https://github.com/BitgetLimited/v3-bitget-api-sdk/tree/master/bitget-java-sdk-api) | 查看包 `com.bitget.openapi.api.v2` |
| [Python](https://github.com/BitgetLimited/v3-bitget-api-sdk/tree/master/bitget-python-sdk-api) | 查看 `v2` |
| [NodeJs](https://github.com/BitgetLimited/v3-bitget-api-sdk/tree/master/bitget-node-sdk-api) | 查看 `src/lib/v2` |
| [Golang](https://github.com/BitgetLimited/v3-bitget-api-sdk/tree/master/bitget-golang-sdk-api) | 查看 `pkg/client/v2` |
| [PHP](https://github.com/BitgetLimited/v3-bitget-api-sdk/tree/master/bitget-php-sdk-api) | 查看 `src/api/v2` |

## 签名

### API 验证

#### 发起请求

所有 REST 请求的 header 都必须包含以下 key：

- **ACCESS-KEY**：API KEY 作为一个字符串。
- **ACCESS-SIGN**：使用 base64 编码签名（参考下方 HMAC 示例）。
- **ACCESS-TIMESTAMP**：您请求的时间戳。
- **ACCESS-PASSPHRASE**：您在创建 API KEY 时设置的口令。
- **Content-Type**：统一设置为 `application/json`。
- **locale**：支持多语言，如：中文 (zh-CN)，英语 (en-US)

#### 获取时间戳

```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;
```

### 生成签名

ACCESS-SIGN 的请求头是对 `timestamp + method.toUpperCase() + requestPath + "?" + queryString + body` 字符串（+ 表示字符串连接）使用 **HMAC SHA256** 方法加密，通过 **BASE64** 编码输出而得到的。

#### 签名各字段说明

- **timestamp**：与 ACCESS-TIMESTAMP 请求头相同。
- **method**：请求方法 (POST/GET)，字母全部大写。
- **requestPath**：请求接口路径。
- **queryString**：请求 URL 中（? 后的请求参数）的查询字符串。
- **body**：请求主体对应的字符串，如果请求没有主体（通常为 GET 请求）则 body 可省略。

**queryString 为空时，签名格式：**

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

**queryString 不为空时，签名格式：**

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

#### 举例说明

获取合约深度信息，以 BTCUSDT 为例：

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

生成待签名字符串：

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

合约下单，以 BTCUSDT 为例：

- 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"}`

生成待签名字符串：

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

#### 生成最终签名的步骤

**HMAC**

1. 使用私钥 **secretKey** 对待签名字符串进行 HMAC SHA256 加密
2. 对加密结果进行 Base64 编码

也支持 RSA 签名：使用 RSA 私钥对待签名字符串进行 SHA-256 加密，然后 Base64 编码。

### HMAC 签名示例代码

```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 示例
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))
```

## 请求说明

所有请求均基于 HTTPS 协议，POST 请求头中的 Content-Type 应设置为 `application/json`。

### 请求交互说明

- **请求参数**：根据接口请求参数封装参数。
- **提交请求参数**：通过 GET/POST 将封装的请求参数提交到服务器。
- **服务器响应**：服务器首先对用户请求数据进行参数安全验证，验证通过后根据业务逻辑以 JSON 格式返回响应数据。
- **数据处理**：处理服务器响应数据。

#### 成功

HTTP 状态码 200 表示响应成功，可能包含内容。如果响应包含内容，将在相应的返回内容中显示。

#### 常见错误码

- 400 Bad Request – 无效的请求格式
- 401 Unauthorized – 无效的 API Key
- 403 Forbidden – 您无权访问请求的资源
- 404 Not Found – 未找到请求
- 429 Too Many Requests – 请求过于频繁，被系统限制
- 500 Internal Server Error – 服务器出现问题

如果失败，返回体通常会指示错误消息。另请参阅 [错误码](/zh-CN/docs/api/error-code) 页面。

### 标准规范

#### 时间戳

HTTP 请求签名中 ACCESS-TIMESTAMP 的单位是毫秒。请求的时间戳必须在 API 服务器时间的 30 秒以内，否则请求将被视为过期并拒绝。如果本地服务器时间与 API 服务器时间有较大偏差，我们建议您通过查询 API 服务器时间来比较时间戳。

#### 频率限制规则

如果请求过于频繁，系统将自动限制请求并返回 429 too many requests 状态码。

- **公共接口**：对于行情信息接口，统一频率限制为每秒最多 20 次请求。
- **授权接口**：使用 apikey 限制授权接口的调用，频率限制规则请参考各接口的频率限制规则。

#### 请求格式

目前仅支持两种请求方法：GET 和 POST

- **GET**：参数通过 queryString 在路径中传输到服务器。
- **POST**：参数以 JSON 格式发送到服务器。
