CryptoVpsHost REST API 参考 - VPS 服务器管理自动化端点
00 · 约定

约定

本文档中的每个端点都遵循同一套规则。先读一遍本节,再跳转到你需要的资源。

身份验证

每个请求都必须在 Authorization 头中携带 Bearer 令牌:

Authorization: Bearer nkv_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2

提供三种权限范围(scope),每一种都严格大于前一种:

  • read——对除账单外所有资源的只读访问。
  • write——读取,外加创建、更新和销毁。无法生成充值地址。
  • billing——write 能做的一切,外加账单相关端点。

令牌在账户 → API 令牌中生成。明文仅在创建时显示一次——我们只保存其 SHA-256 摘要。任何基于时间的校验,允许的时钟偏差为 30 秒。

JSON 与类型

  • 请求体必须为 application/json。除 POST /images 外,我们不接受 multipart/form-data。
  • 键名使用 snake_case。请求中出现未知键会被拒绝,并返回 400;响应中的未知键,你的客户端可以放心忽略。
  • 时间戳采用 UTC 的 RFC 3339 格式,例如 2026-05-12T08:47:12Z。
  • 金额以 USD 的 JSON 数字表示,保留两位小数。币种金额以十进制字符串表示,以保证精度。
  • 资源 ID 是带类型前缀的短字符串,对外不透明。请不要解析它们。

幂等性

每个 POST 端点都接受可选的 Idempotency-Key 头。标准做法是使用 UUIDv4。同一个键对应的首次响应会缓存 24 小时;之后携带相同键的请求会重放缓存的响应。若请求体不同但键相同,则返回 409 conflict_state。

curl -X POST .../v1/servers \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Authorization: Bearer $NOKYC_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{...}'

分页

列表端点默认最多返回 25 条,上限 100 条。采用游标分页,不支持 offset。若还有更多条目,响应会返回 has_more: true 和 next_cursor。将其作为 ?cursor=... 传入即可获取下一页。

json列表响应的结构
{
  "object":      "list",
  "data":        [ /* up to page_size items */ ],
  "has_more":    true,
  "next_cursor": "c_8a1f2c34"
}

使用 page_size 覆盖默认值。filter[field]=value 用于相等过滤(在支持的地方)。sort=-created_at 用于降序排序。

错误

错误始终以 JSON 返回,并使用相同的外层结构:

json错误响应的外层结构
{
  "error": {
    "code":       "invalid_request",
    "message":    "ssh_keys must contain at least one valid key id.",
    "errors": [
      { "field": "ssh_keys", "issue": "min_items", "min": 1 }
    ],
    "request_id": "req_2f8b1c4e9d"
  }
}

请务必在客户端记录 request_id——如果你请求我们排查某次调用,它是我们在日志中定位该调用的唯一依据。(我们只会查看你提供了 request_id 的那些日志行;我们不会浏览客户日志。)

HTTP 状态码及其对应的语义错误码:

HTTP错误码含义
400invalid_request请求体或查询参数未通过校验。详见 errors[]。
401unauthenticated缺少 Bearer 令牌,或令牌格式错误、已过期。
403forbidden_scope该令牌不具备所需的权限范围(scope)。
404not_found资源不存在,或对你的账户不可见。
409conflict_state资源当前所处状态不允许执行此操作(例如挂载一个已挂载的存储卷)。
422unprocessable请求体已解析,但语义校验失败(例如所选套餐在该地区不可用)。
429rate_limited令牌桶已耗尽。Retry-After 头的单位为秒。
451jurisdictional_block该端点因法律原因被拒绝。金丝雀声明中会有所体现。
500internal服务器端错误。仅应重试幂等操作。
503maintenance在已公布的维护窗口期间,该端点暂时不可用。

速率限制

每个令牌每分钟 60 次请求,另允许 10 次请求的突发。令牌桶以每秒 1 次请求的速度补充。部署类端点(POST /servers、POST /images)使用独立的每分钟 200 次请求令牌桶,因为它们天然具有突发性。

X-RateLimit-Limit:     60
X-RateLimit-Remaining: 57
X-RateLimit-Reset:     1747049892
Retry-After:           23           # only on 429

版本管理

API 的版本号包含在路径中:/v1/...。我们承诺:

  • 同一主版本内不做向后不兼容的变更。
  • 在现有版本上进行的增量变更(新字段、新端点),会在更新日志中公告。
  • 在下一个主版本中移除任何端点或字段之前,会先设置 12 个月的弃用期。
  • Beta 端点需要通过 X-Nokyc-Beta: true 开启,可能在不另行通知的情况下发生破坏性变更。
资源

资源

下面的每个资源都由三部分构成:对象结构、作用于它的端点,以及一个或多个附带真实响应体的请求示例。

01 · 核心

服务器

server 是我们虚拟机管理程序池中的一台虚拟机,或是独立服务器产品线中的一个物理节点。本页上的其他资源,要么描述服务器,要么挂接到服务器上,要么由服务器产生事件。

对象

字段类型说明
id ro string 唯一标识符。前缀为 srv_。
object ro string 始终为 "server"。
name string · 1–63 客户指定的名称。格式为 [a-z0-9-],必须以字母开头。
status ro enum provisioning, installing, running, stopped, suspended, destroying.
plan string 套餐 ID(参见套餐)。部署后不可更改。
region string 地区代码(参见地区)。不可更改。
image string 安装时使用的镜像 ID。服务器重建后会更新。
ipv4 ro object · nullable {address, gateway, rdns}。在 running 之前为 null。
ipv6 ro object · nullable {address, prefix, rdns}。始终为已路由的 /64 子网。
ssh_keys array<string> 安装时注入的 SSH 密钥 ID。
user_data_b64 string · write-only Base64 编码的 cloud-init user-data。最大 64 KiB。
tags array<string> 自由格式的标签,便于筛选。
labels object<string,string> 最多 32 个键值对。键必须匹配 [a-z0-9_-]{1,63}。
created_at ro string · RFC 3339 UTC 时间戳。
updated_at ro string · RFC 3339 UTC 时间戳。任何变更都会更新它。

端点

  • GET /servers 列出你的服务器。
  • POST /servers 创建新服务器。
  • GET /servers/{id} 获取单个服务器。
  • PATCH /servers/{id} 更新 name、tags 或 labels。
  • DELETE /servers/{id} 销毁服务器。此操作不可逆。
  • POST /servers/{id}/reboot 重启。添加 ?hard=true 可跳过 ACPI。
  • POST /servers/{id}/rebuild 重新安装操作系统镜像。磁盘数据将被销毁。
  • POST /servers/{id}/rescue 引导进入救援 ISO。
  • POST /servers/{id}/stop 正常停止(ACPI 关机)。
  • POST /servers/{id}/start 启动已停止的服务器。
  • GET /servers/{id}/console 一次性签名的 noVNC URL(有效期 5 分钟)。
  • GET /servers/{id}/metrics 30 天的 CPU / RAM / 磁盘 / 带宽汇总数据。
  • POST /servers/{id}/rdns 为 IPv4 和/或 IPv6 设置反向 DNS。
02 · 资源

镜像

image 是服务器启动所用的磁盘模板。官方镜像由我们维护;自定义镜像则是你上传的 ISO。

对象

字段类型说明
id ro string 前缀为 img_(官方)或 custom_(自定义上传)。
object ro string 始终为 "image"。
type ro enum official 或 custom。
family ro string debian、ubuntu、alpine 等。上传的镜像为 custom。
version ro string 上游版本号(例如 13、24.04、rolling)。
variant ro string · nullable 镜像变体:minimal、cloud 等。
arch ro array<string> 支持的架构:amd64、arm64。
size_gb ro number 磁盘占用大小,单位 GiB。可用于预估部署时间。
cloud_init ro boolean 镜像是否内置 cloud-init。
released_at ro string · ISO 8601 该版本的发布日期。
deprecated_at ro string · ISO 8601 · nullable 若已设置,镜像为只读,并将在该日期 90 天后移除。

端点

  • GET /images 列出镜像(可按 family、arch、type 筛选)。
  • GET /images/{id} 获取单个镜像。
  • POST /images 上传自定义 ISO。使用 multipart/form-data,最大 4 GiB。
  • DELETE /images/{id} 删除自定义镜像(对官方镜像无效)。
02 · 资源

套餐

plan 描述一种可购买的硬件规格。价格以 USD 为参考;每台服务器在部署时从你的余额中一次性预付整个周期的费用,周期可选 1、3、6 或 12 个月(折扣分别为 0%、25%、35% 和 50%)。充值的币种金额按生成账单时的即时汇率折算。

对象

字段类型说明
id ro string 套餐代码。价格调整后保持不变。
object ro string 始终为 "plan"。
category ro enum vps 或 dedicated。
cpu ro integer vCPU 数量(VPS)或物理核心数(独立服务器)。
cpu_model ro string 不含营销用语的处理器型号字符串,例如 "AMD EPYC 7763 (Milan)"。
ram_mb ro integer RAM 容量,单位 MiB。
disk_gb ro integer NVMe 磁盘容量,单位 GiB。
transfer_tb ro number 每月出站流量,单位 TiB。入站流量不限。
price_usd_month ro number 参考月价,单位 USD。
price_usd_hour ro number 折算为每小时的参考价,仅供比较。服务器按周期预付,不按小时计费。
available_in ro array<string> 当前可部署该套餐的地区代码。

端点

  • GET /plans 列出套餐。
  • GET /plans/{id} 获取套餐。
02 · 资源

地区

region 是我们四个 PoP(接入点)之一。每个 PoP 由独立的法律实体运营,并独立路由。

对象

字段类型说明
id ro string 三字母代码:par、rkv、zrh、buh。
object ro string 始终为 "region"。
name ro string 便于阅读的名称(Paris、Reykjavík、Zürich、Bucharest)。
country ro string 国家代码,遵循 ISO 3166-1 alpha-2。
pop_id ro string 内部 PoP 编号(例如 nky-par-01)。
available ro boolean 当前至少有一个套餐可部署时为 true。
ipv4_pool_remaining ro integer 地区地址池中剩余的 IPv4 地址数。低于 50 时,部署可能会停滞。
tor_onion ro string · nullable 该地区的 onion 端点(如有)。

端点

  • GET /regions 列出地区。
  • GET /regions/{id} 获取地区。
02 · 资源

SSH 密钥

安装时注入服务器 authorized_keys 的公钥。私钥部分始终留在你的设备上,我们永远看不到。

对象

字段类型说明
id ro string 前缀为 k_。
object ro string 始终为 "ssh_key"。
name string · 1–63 显示名称,方便你自己识别。
type ro enum ssh-ed25519 · ssh-rsa · ecdsa-sha2-nistp{256,384,521}.
fingerprint ro string SHA-256,base64 编码。格式为 SHA256:<digest>。
public_key string OpenSSH 格式的公钥(为减小体积,列表响应中不包含)。
created_at ro string · RFC 3339

端点

  • GET /ssh-keys 列出 SSH 密钥。
  • POST /ssh-keys 添加新的 SSH 密钥。
  • GET /ssh-keys/{id} 获取密钥。
  • DELETE /ssh-keys/{id} 删除密钥。不影响已部署的服务器。
02 · 资源

API 令牌

用于对该 API 进行身份验证的长期有效密钥。明文令牌仅在创建时返回一次;服务端只保存其 SHA-256 摘要。

对象

字段类型说明
id ro string 前缀为 tok_。
object ro string 始终为 "api_token"。
name string 供你自己记录和管理之用。
scope enum read、write 或 billing。
token string · write-only 明文令牌。仅在 POST 响应中返回一次。格式为 nkv_live_<52 chars>。
last_used_at ro string · RFC 3339 · nullable 每分钟最多更新一次,以限制写放大。
expires_at string · RFC 3339 · nullable 可选。若已设置,令牌将在该时间点失效。
created_at ro string · RFC 3339

端点

  • GET /account/tokens 列出令牌。
  • POST /account/tokens 创建令牌(明文仅返回一次)。
  • DELETE /account/tokens/{id} 立即吊销令牌。
03 · 账单

账单

以读取为主的端点,涵盖你当前的余额、交易历史以及充值流程。

balance 对象

字段类型说明
object ro string 始终为 "balance"。
usd ro number USD 参考余额,保留两位小数。
as_of ro string · RFC 3339 数据快照时间。
runway_until ro string · date · nullable 你所有运行中的服务器预付覆盖到的日历日期(即最早的周期结束日)。没有运行中的服务器时为 null。
active_servers ro integer 当前在已预付周期内运行的服务器。
daily_cost_usd ro number 所有运行中服务器折算为每日的参考成本,仅供比较。不会按日扣费。
low_balance_at ro string · RFC 3339 · nullable 我们何时通过邮件发送低余额提醒(目前为 runway 前 7 天)。

端点

  • GET /billing/balance 当前余额 + runway。
  • GET /billing/ledger 分页的交易历史(扣费、充值、入账)。
  • POST /billing/topup 为指定币种生成一次性充值地址。
  • GET /billing/topup/{id} 轮询充值单状态(pending / confirming / credited / expired)。
04 · 存储

存储卷

可挂载到同一地区服务器上的持久化块存储。存储卷在服务器被销毁后依然保留。

对象

字段类型说明
id ro string 前缀为 vol_。
object ro string 始终为 "volume"。
name string 显示名称。
size_gb integer · 10–4096 容量,单位 GiB。可在线扩容,不可缩容。
region string 地区代码。必须与所挂载服务器的地区一致。
attached_to ro string · nullable 服务器 ID;已卸载时为 null。
device ro string · nullable 挂载后 Linux 块设备的路径(/dev/vdb,…)。
encrypted boolean 卷级别 LUKS 加密,密钥由客户持有,并通过 cloud-init 传入。
filesystem string · nullable 供你自己记录之用。我们不会格式化存储卷。
created_at ro string · RFC 3339

端点

  • GET /volumes 列出存储卷。
  • POST /volumes 创建存储卷。
  • GET /volumes/{id} 获取。
  • PATCH /volumes/{id} 调整容量(只能增大 size_gb)或重命名。
  • DELETE /volumes/{id} 销毁。必须先卸载。
  • POST /volumes/{id}/attach 挂载到服务器(请求体:{"server":"srv_…"})。
  • POST /volumes/{id}/detach 卸载。
04 · 存储

快照

服务器根磁盘在某一时间点的副本。快照经过去重,并加密存储。快照无法导出——它们的作用是让你能从已知良好的状态重建服务器。

对象

字段类型说明
id ro string 前缀为 snap_。
object ro string 始终为 "snapshot"。
server ro string 创建该快照的服务器 ID。创建时即固定。
name string 显示名称。
size_gb ro number 去重后的大小,即你实际支付的存储量。
status ro enum creating · ready · error.
expires_at string · RFC 3339 · nullable 可选的自动删除日期。
created_at ro string · RFC 3339

端点

  • GET /snapshots 列出快照。
  • POST /servers/{id}/snapshots 为服务器创建快照。
  • GET /snapshots/{id} 获取。
  • POST /servers/{id}/restore 从快照恢复服务器(基于 snap_… 重建)。
  • DELETE /snapshots/{id} 删除快照。
05 · 网络

防火墙组

有状态、默认丢弃的包过滤器,在虚拟机管理程序层面执行——位于客户机之外。一个组是一组具名规则;每条规则允许匹配某个五元组的入站或出站流量。

对象

字段类型说明
id ro string 前缀为 fwg_。
object ro string 始终为 "firewall_group"。
name string 显示名称。
applied_to array<string> 继承该组规则的服务器 ID。
rules array<rule> 参见下方的规则对象。顺序很重要:首条匹配的规则生效。
default_action enum drop(推荐)或 accept。
created_at ro string · RFC 3339

规则对象

字段类型说明
id ro string 前缀为 fwr_。由服务端分配。
direction enum in 或 out。
proto enum tcp · udp · icmp · any.
port string · nullable 单个端口("22")、逗号分隔的列表("80,443")或范围("5000-5100")。对无端口的协议为 null。
source string CIDR。接受 0.0.0.0/0 和 ::/0。
action enum accept、drop 或 reject(会发送 RST/ICMP-unreach)。
note string · nullable 可选备注。

端点

  • GET /firewall/groups 列出防火墙组。
  • POST /firewall/groups 创建组。
  • GET /firewall/groups/{id} 获取。
  • PATCH /firewall/groups/{id} 更新 name、default_action、applied_to。
  • DELETE /firewall/groups/{id} 删除组(该组不能处于已应用状态)。
  • POST /firewall/groups/{id}/rules 追加一条规则。
  • PUT /firewall/groups/{id}/rules 替换规则列表(原子操作)。
  • DELETE /firewall/groups/{id}/rules/{rule_id} 删除单条规则。
06 · 自动化

Webhook 订阅

为你账户的事件订阅一个 URL。每当发生值得关注的事情,我们会向你的端点 POST 一个 JSON 事件,并附上可供你验证的 HMAC-SHA256 签名。

对象

字段类型说明
id ro string 前缀为 whk_。
object ro string 始终为 "webhook"。
url string · HTTPS only 我们向其发送 POST 的端点。必须使用 HTTPS 并具备有效证书。
events array<string> 已订阅的事件。["*"] 表示订阅全部。
active boolean 为 false 时,投递将暂停。
secret_hint ro string 签名密钥(whsec_…)的最后 4 个字符,供你参考。完整密钥仅在创建时返回一次。
created_at ro string · RFC 3339

端点

  • GET /webhooks 列出订阅。
  • POST /webhooks 创建。响应中包含 secret(明文,仅此一次)。
  • GET /webhooks/{id} 获取。
  • PATCH /webhooks/{id} 更新 url、events、active。
  • DELETE /webhooks/{id} 取消订阅。
  • POST /webhooks/{id}/test 发送一个合成的 ping 事件。
  • GET /webhooks/{id}/deliveries 最近 7 天的投递尝试记录。
07 · 可观测性

审计日志

针对你账户发出的每一个经过身份验证、会改变状态的请求,并记录发起者。保留 90 天。

对象

字段类型说明
id ro string 前缀为 audit_。
object ro string 始终为 "audit_event"。
action ro string 以点分隔的操作名称(例如 server.create)。
resource ro string · nullable 受影响资源的 ID。
actor_token ro string · nullable 所用令牌的 ID(通过 API 调用时)。
actor_session ro string · nullable 所用会话的 ID(通过控制面板操作时)。
request_id ro string 关联 ID(与原始响应中的 X-Request-Id 头一致)。
ip_country ro string 检测时的 ISO-3166 国家代码。不保存 IP。
result ro enum ok · error · denied.
created_at ro string · RFC 3339

端点

  • GET /audit/events 列出审计事件。可按 action、resource、from、to 筛选。
  • GET /audit/events/{id} 获取单个事件。
示例 · 创建服务器

在一次 shell 会话中完成端到端部署

从“我有一个账户”到“我有一台运行中的服务器”的最简可行流程:

请求

curlPOST /v1/servers
curl https://api.cryptovpshost.com/v1/servers \
  -H "Authorization: Bearer $NOKYC_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name":     "edge-paris",
    "plan":     "vps-s2",
    "region":   "par",
    "image":    "debian-13-minimal",
    "ssh_keys": ["k_5f3a8c91"],
    "tags":     ["production","edge"],
    "labels":   { "owner":"ops" },
    "user_data_b64": null
  }'

响应——201 Created

json服务器对象
{
  "id":         "srv_8a1f2c34",
  "object":     "server",
  "name":       "edge-paris",
  "status":     "provisioning",
  "plan":       "vps-s2",
  "region":     "par",
  "image":      "debian-13-minimal",
  "ipv4":       null,
  "ipv6":       null,
  "ssh_keys":   ["k_5f3a8c91"],
  "tags":       ["production","edge"],
  "labels":     { "owner":"ops" },
  "created_at": "2026-05-12T08:47:12Z",
  "updated_at": "2026-05-12T08:47:12Z"
}

两个 Webhook 事件之后(通常在 60–120 秒内):

jsonserver.running 的 Webhook
{
  "id":         "evt_3c8a1f4b",
  "object":     "event",
  "type":       "server.running",
  "created_at": "2026-05-12T08:48:34Z",
  "data": {
    "server": {
      "id":     "srv_8a1f2c34",
      "status": "running",
      "ipv4":   { "address":"198.51.100.42", "gateway":"198.51.100.1", "rdns":null },
      "ipv6":   { "address":"2001:db8::1",   "prefix":"2001:db8::/64", "rdns":null }
    }
  }
}

现在你可以执行 ssh [email protected] 了。

08 · Webhook 事件

事件目录

每个事件都属于下列类型之一。data 部分包含事件发生时对象的完整内容——除非需要保证最新的视图,否则不必重新获取。

事件触发时机
server.created 新服务器已开始部署。
server.running 服务器已完成安装,可以连接。
server.stopped 服务器已正常关机。
server.rebooted 服务器已完成一次重启。
server.rebuilt 服务器已完成基于镜像的重建。
server.suspended 预付周期已结束,余额不足以支付下一个周期;服务器已停止。
server.destroyed 服务器磁盘已被擦除,IP 已释放。
snapshot.ready 快照已从 creating 变为 ready。
volume.attached 存储卷已成功挂载。
volume.detached 存储卷已卸载。
topup.pending 已在链上检测到充值;等待确认。
topup.confirmed 充值已确认;余额已入账。
topup.expired 汇率锁定在确认前已过期。
billing.charged 已从你的余额扣除周期费用。包含金额及扣费后的余额。
billing.low_balance 预付周期将在 7 天内结束,且余额不足以支付下一个周期。
token.created 已创建新的 API 令牌。
token.revoked API 令牌已被吊销。
firewall.applied 防火墙组已关联到服务器。
09 · Webhook 签名

验证 Webhook 的真实性

每次投递都包含 X-Nokyc-Signature 头。你需要将它与请求体的 HMAC-SHA256 进行比对,该 HMAC 使用订阅时返回给你的密钥计算。

头部格式

X-Nokyc-Signature:   t=1747049892,v1=4f8c1a...e9d
X-Nokyc-Delivery-Id: del_7c3a1f9b
Content-Type:        application/json
  • t——签名生成时的 Unix 时间戳。
  • v1——"{t}.{raw_body}" 的 HMAC-SHA256,小写十六进制。
  • 如果 t 与你的时钟相差超过 5 分钟,请拒绝该次投递。

验证——Python

pythonverify_signature.py
import hmac, hashlib, time

def verify(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    t  = int(parts["t"])
    v1 = parts["v1"]
    if abs(time.time() - t) > tolerance:
        return False
    payload = f"{t}.".encode() + raw_body
    expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
    return hmac.compare_digest(v1, expected)

重试策略

每次投递最多尝试 6 次,退避间隔如下:

attempt 1:  immediate
attempt 2:  + 1   minute
attempt 3:  + 5   minutes
attempt 4:  + 30  minutes
attempt 5:  + 5   hours
attempt 6:  + 24  hours
              => give up

当你的端点在 10 秒内返回 HTTP 2xx 时,投递视为成功。410 Gone 会立即终止后续所有尝试并暂停该订阅。失败的投递可通过 GET /webhooks/{id}/deliveries 查看。

10 · 更新日志

更新日志

v1 内的增量变更。下一个主版本(v2)目前尚无计划。

  1. v1.4 2026-04-22
    • 新增 /servers/{id}/metrics 端点(30 天汇总)。
    • 余额对象新增 runway_until 和 low_balance_at。
    • Webhook 现在包含 X-Nokyc-Delivery-Id,以便安全处理重复投递。
  2. v1.3 2026-01-10
    • 新增“存储卷”资源(支持挂载/卸载的块存储)。
    • 防火墙组新增 default_action,规则新增 note。
    • 服务器 labels 上限为 32 对(原为 16 对)。
  3. v1.2 2025-09-15
    • 新增“快照”资源及 /servers/{id}/restore。
    • 地区新增 ipv4_pool_remaining。
  4. v1.1 2025-06-04
    • 列表端点已改用游标分页。offset/limit 已弃用,将在 v2 中移除。
    • 所有 POST 请求新增对 Idempotency-Key 的支持。
    • 新增“审计日志”资源。
  5. v1.0 2024-09-12
    • 首个稳定版本。
    • 服务器、镜像、套餐、地区、SSH 密钥、API 令牌、账单、Webhook。