REST API
门户位置:
https://<your-domain>/apidoc处的 API 参考(公开)以及/api-keys处的 API 密钥。管理后台位置: Customers › API keys (/customers/apikeys) 列出了客户创建的密钥。
功能说明
客户在门户中可以执行的每项操作——列出和控制虚拟机、阅读账单、管理 SSH Keys、Kubernetes、存储、支持工单——均可通过 https://<your-domain>/v1/ 下的版本化 REST API 使用。客户通过带有作用域的 API key 从脚本和 CI 中调用它。同一个 API 为 cmp command-line tool 和 MCP server 提供支持,并且参考文档由运行中的安装实例生成,因此它总是精确列出你已启用的功能。
前提条件
| 项目 | 要求 |
|---|---|
| 公网HTTPS地址 | 该 API 在你的主域名(以及每个分销商自己的域名)上提供。 |
| API key | 由客户在门户中创建;参见 API keys。 |
| 依赖项 | 无。未启用的模块(例如 Kubernetes 或 Object Storage)的端点将从参考文档中隐藏并被拒绝。 |
准备基础设施
无需安装。如果 NexCMP 前面有反向代理,请将 /v1/、/mcp、/cli/ 和 /apidoc 转发给面板(安装程序的 nginx 配置已完成此操作)。
在NexCMP中连接
交互式参考
打开 https://cloud.example.com/apidoc(将主机替换为你的域名;分销商的客户会在分销商的域名上看到带有分销商名称的参考文档)。它包含带有 curl、cmp CLI、JavaScript、Python 和 Go 的请求与响应示例的端点文档、搜索框(Ctrl 或 Cmd + K)以及一个 Try it 面板。「Try it」仅向同一站点发送请求,并使用访问者粘贴的密钥(保存在浏览器会话中);默认情况下它是只读的,写入或付费调用需要额外的开关和确认。
下载与机器可读文档
所有文档均公开、无需密钥且按站点生成:
| 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客户端。
认证
在 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。 - 使用
GET /v1/apikeys/self检查密钥:它返回调用密钥的名称、作用域、过期时间以及剩余的速率限制额度(所有密钥均可调用)。
示例
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 中获取每个操作的具体请求字段。
错误
每个错误都是带有稳定 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;模拟会话中不允许此操作。 |
| 404 | not_found | 未找到——对于属于其他人的资源也会返回此错误。 |
| 422 | invalid_argument | 验证错误(响应中会指明字段)。 |
| 429 | rate_limited | 请求过多;请等待 Retry-After。 |
| 503 | maintenance | 维护模式已开启:只读操作正常,写入操作被拒绝。 |
速率限制
| 限制 | 默认值 |
|---|---|
| 每个密钥 | 每分钟120个请求 |
| 每个账户(所有密钥合计) | 每分钟300个请求 |
每个响应都带有 X-RateLimit-Limit、X-RateLimit-Remaining 和 X-RateLimit-Reset;429 状态码会增加 Retry-After。
幂等性
涉及资金或不可重复的命令(创建、更改套餐、购买、删除等)必须提供 Idempotency-Key 请求头(任何最长200个字符的字符串;使用UUID效果很好)。在超时后使用相同的键再次发送,服务器将返回原始结果(带有 Idempotency-Replayed: 1),而不是重复执行该操作。将同一个键复用于不同的命令会响应422;仍在进行中的请求会响应409/Retry-After。如果没有该请求头,付费调用将被拒绝。
验证
在门户中创建具有
vm:read作用域的密钥(API keys › Create key)。运行:
bashcurl -i https://cloud.example.com/v1/apikeys/self -H "Authorization: Bearer vk_XXXX"您将获得HTTP 200以及速率限制响应头。
curl -s https://cloud.example.com/v1/vm -H "Authorization: Bearer vk_XXXX"列出账户的虚拟机。在门户中,密钥的 Last used 列和 Key usage log 会显示调用情况。
限制与注意事项
- 对密钥永远不可用: 充值、提现、更改银行卡或自动充值、修改密码、邮箱或2FA、删除账户、创建、编辑或撤销其他密钥。这些操作需要已登录的浏览器会话。
- 隐藏模块: 参考文档和OpenAPI文档仅列出在该站点上启用的功能。
- 响应大小与分页: 列表端点采用分页机制(
page、per_page);请阅读各端点的OpenAPI文档。 - 时间和金额: 除非字段名称另有说明,否则金额单位均为美元分。
- 管理员API: 管理后台拥有自己的 System › Admin › API 页面和用于管理的管理员密钥(
ofw_...);它们与此处描述的客户API是分开的。 - **版本控制:**路径前缀
/v1是稳定的;未来可能会向响应中添加新字段。
故障排查
| 症状 | 原因 | 解决办法 |
|---|---|---|
| 在新密钥上返回 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中启用该模块。 |