---
title: REST API
description: 调用 NexCMP 安装实例的客户 API：身份验证、交互式参考、OpenAPI 和 Postman 下载、错误、速率限制、幂等性以及 curl 示例。
url: https://nexcmp.com/zh-cn/docs/developers/api/
applies_to: NexCMP 1.6.1
updated: 2026-11-02
---

# REST API

> **门户位置：** `https://<your-domain>/apidoc` 处的 API 参考（公开）以及 `/api-keys` 处的 API 密钥。**管理后台位置：** Customers › API keys (`/customers/apikeys`) 列出了客户创建的密钥。

## 功能说明 {#what-it-does}

客户在门户中可以执行的每项操作——列出和控制虚拟机、阅读账单、管理 SSH Keys、Kubernetes、存储、支持工单——均可通过 `https://<your-domain>/v1/` 下的版本化 REST API 使用。客户通过带有作用域的 **API key** 从脚本和 CI 中调用它。同一个 API 为 [`cmp` command-line tool](https://nexcmp.com/zh-cn/docs/developers/cmp-cli/) 和 [MCP server](https://nexcmp.com/zh-cn/docs/developers/mcp/) 提供支持，并且参考文档由运行中的安装实例生成，因此它总是精确列出你已启用的功能。

## 前提条件 {#requirements}

| 项目 | 要求 |
|---|---|
| 公网HTTPS地址 | 该 API 在你的主域名（以及每个分销商自己的域名）上提供。 |
| API key | 由客户在门户中创建；参见 [API keys](https://nexcmp.com/zh-cn/docs/developers/api-keys/)。 |
| 依赖项 | 无。未启用的模块（例如 Kubernetes 或 Object Storage）的端点将从参考文档中隐藏并被拒绝。 |

## 准备基础设施 {#prepare-the-infrastructure}

无需安装。如果 NexCMP 前面有反向代理，请将 `/v1/`、`/mcp`、`/cli/` 和 `/apidoc` 转发给面板（安装程序的 nginx 配置已完成此操作）。

## 在NexCMP中连接 {#connect-in-nexcmp}

### 交互式参考 {#the-interactive-reference}

打开 `https://cloud.example.com/apidoc`（将主机替换为你的域名；分销商的客户会在分销商的域名上看到带有分销商名称的参考文档）。它包含带有 curl、`cmp` CLI、JavaScript、Python 和 Go 的请求与响应示例的端点文档、搜索框（Ctrl 或 Cmd + K）以及一个 **Try it** 面板。「Try it」仅向同一站点发送请求，并使用访问者粘贴的密钥（保存在浏览器会话中）；默认情况下它是只读的，写入或付费调用需要额外的开关和确认。


### 下载与机器可读文档 {#downloads-and-machine-readable-documents}

所有文档均公开、无需密钥且按站点生成：

| URL | 内容 |
|---|---|
| `/apidoc` | 交互式参考。 |
| `/v1/public/openapi.json` | OpenAPI 3.1 文档。 |
| `/v1/public/openapi.yaml` | 同上，YAML 格式。 |
| `/v1/public/postman.json` | Postman 集合。 |
| `/v1/public/insomnia.json` | Insomnia 导出。 |
| `/v1/public/api.md` | 以单个 Markdown 文件形式提供的参考。 |
| `/v1/public/api-catalog` | 轻量JSON：品牌、基础URL、密钥前缀、每个作用域和每个端点（包含方法、路径、作用域以及是否需要 `Idempotency-Key`）。 |

```bash
curl -s https://cloud.example.com/v1/public/api-catalog | python3 -m json.tool | head -40
curl -sO https://cloud.example.com/v1/public/openapi.yaml
```

在Postman中选择 **Import › Link** 并粘贴 `https://cloud.example.com/v1/public/postman.json`。参考页面还提供适用于JavaScript和Python的单文件API客户端。

### 认证 {#authentication}

在 `Authorization` 头中发送密钥：

```bash
curl -s https://cloud.example.com/v1/billing/wallet \
  -H "Authorization: Bearer vk_XXXX"
```

- 客户密钥以 `vk_` 开头。密钥是**站点绑定的**：在 `cloud.example.com` 上创建的密钥在分销商域名上无效。
- 浏览器会话令牌（`pt_...`）仅用于门户；自动化请使用密钥。
- 密钥的**作用域**决定了它可调用的内容；缺少作用域会响应HTTP 403 `scope_required`。请参阅 [API keys](https://nexcmp.com/zh-cn/docs/developers/api-keys/)。
- 使用 `GET /v1/apikeys/self` 检查密钥：它返回调用密钥的名称、作用域、过期时间以及剩余的速率限制额度（所有密钥均可调用）。

### 示例 {#examples}

```bash
# List virtual machines
curl -s "https://cloud.example.com/v1/vm?page=1" -H "Authorization: Bearer vk_XXXX"

# Start one (needs vm:write)
curl -s -X POST https://cloud.example.com/v1/vm/3f2a1c9e-0000-4000-8000-000000000000/start \
  -H "Authorization: Bearer vk_XXXX"

# Create a VM (paid: needs vm:create and an Idempotency-Key)
curl -s -X POST https://cloud.example.com/v1/vm \
  -H "Authorization: Bearer vk_XXXX" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d @vm.json
```

从 `/apidoc` 中获取每个操作的具体请求字段。

### 错误 {#errors}

每个错误都是带有稳定 `code` 和人类可读的 `message` 的JSON：

```json
{"error": {"code": "scope_required", "message": "Key lacks scope vm:write"}}
```

| HTTP | 典型 `code` | 说明 |
|---|---|---|
| 401 | `unauthenticated`, `key_invalid`, `key_revoked`, `key_expired`, `key_ip_denied`, `site_mismatch`, `api_keys_disabled` | 密钥缺失或未知、已撤销、已过期、调用方IP超出密钥白名单、来自其他站点的密钥，或API密钥已关闭。 |
| 403 | `scope_required`, `endpoint_not_public`, `account_blocked`, `quota_exceeded`, `impersonate_forbidden` | 密钥缺少作用域；端点对密钥不可用；账户已被锁定；达到 [quota](https://nexcmp.com/zh-cn/docs/billing/quotas/)；模拟会话中不允许此操作。 |
| 404 | `not_found` | 未找到——对于属于其他人的资源也会返回此错误。 |
| 422 | `invalid_argument` | 验证错误（响应中会指明字段）。 |
| 429 | `rate_limited` | 请求过多；请等待 `Retry-After`。 |
| 503 | `maintenance` | 维护模式已开启：只读操作正常，写入操作被拒绝。 |

### 速率限制 {#rate-limits}

| 限制 | 默认值 |
|---|---|
| 每个密钥 | 每分钟120个请求 |
| 每个账户（所有密钥合计） | 每分钟300个请求 |

每个响应都带有 `X-RateLimit-Limit`、`X-RateLimit-Remaining` 和 `X-RateLimit-Reset`；429 状态码会增加 `Retry-After`。

### 幂等性 {#idempotency}

涉及资金或不可重复的命令（创建、更改套餐、购买、删除等）**必须**提供 `Idempotency-Key` 请求头（任何最长200个字符的字符串；使用UUID效果很好）。在超时后使用相同的键再次发送，服务器将返回**原始**结果（带有 `Idempotency-Replayed: 1`），而不是重复执行该操作。将同一个键复用于不同的命令会响应422；仍在进行中的请求会响应409/`Retry-After`。如果没有该请求头，付费调用将被拒绝。

## 验证 {#verify}

1. 在门户中创建具有 `vm:read` 作用域的密钥（**API keys › Create key**）。
2. 运行：

   ```bash
   curl -i https://cloud.example.com/v1/apikeys/self -H "Authorization: Bearer vk_XXXX"
   ```

   您将获得HTTP 200以及速率限制响应头。
3. `curl -s https://cloud.example.com/v1/vm -H "Authorization: Bearer vk_XXXX"` 列出账户的虚拟机。在门户中，密钥的 **Last used** 列和 **Key usage log** 会显示调用情况。

## 限制与注意事项 {#limits-notes}

- **对密钥永远不可用：** 充值、提现、更改银行卡或自动充值、修改密码、邮箱或2FA、删除账户、创建、编辑或撤销其他密钥。这些操作需要已登录的浏览器会话。
- **隐藏模块：** 参考文档和OpenAPI文档仅列出在该站点上启用的功能。
- **响应大小与分页：** 列表端点采用分页机制（`page`、`per_page`）；请阅读各端点的OpenAPI文档。
- **时间和金额：** 除非字段名称另有说明，否则金额单位均为美元分。
- **管理员API：** 管理后台拥有自己的 **System › Admin › API** 页面和用于管理的管理员密钥（`ofw_...`）；它们与此处描述的客户API是分开的。
- **版本控制：**路径前缀 `/v1` 是稳定的；未来可能会向响应中添加新字段。

## 故障排查 {#troubleshooting}

| 症状 | 原因 | 解决办法 |
|---|---|---|
| 在新密钥上返回 401 | 密钥来自另一个域名、已过期或输入时带有空格 | 在您调用的域上创建密钥；检查`Authorization: Bearer vk_...`标头。 |
| 403 `scope_required` | 缺少作用域 | 在门户中编辑密钥并添加作用域。 |
| 401 `key_ip_denied` 或 `site_mismatch` | 密钥受限于其他IP（“允许的IP”）或在另一个域上创建 | 将您服务器的IP添加到密钥的允许IP中，或调用创建密钥的域。 |
| 现有虚拟机返回404 | 该虚拟机属于另一个账户 | 使用所有者的密钥。 |
| 400/422要求提供`Idempotency-Key` | 付费操作缺少标头 | 添加`Idempotency-Key: <uuid>`。 |
| 429 | 超出限制 | 降低频率；使用`Retry-After`。 |
| `/apidoc`显示的内容少于预期 | 模块已关闭 | 在License & updates中启用该模块。 |


