开放 API 开发文档

开放 API 让你的网站、业务系统或自动化脚本直接调用本平台的能力:查询产品与价格、下单、用余额支付、管理已开通的服务,并通过事件回调实时获知开通与状态变化。

  • 所有价格、库存、限购与实名要求和在控制台下单完全一致(按你所在客户组的折扣计算)。
  • 每个请求独立签名,无需先登录换取 token,也不需要保存会话。
  • 请求与响应均为 JSON。

如果你的网站使用 魔方财务,无需开发,直接在魔方财务后台添加接口即可,见「魔方财务对接」指南。

1. 开通与凭据

  1. 登录控制台,进入「账户设置 → API 对接」,点击开通。
  2. 记下 API 账号(你的登录邮箱或手机号)和 API 密码(只显示一次,可凭登录密码再次查看或重置)。
  3. API 密码就是签名密钥,只保存在你的服务器上,不要写进网页或 App。重置后旧密码立即失效。

接口地址:

https://<本站域名>/openapi/v1

2. 签名

每个请求带 4 个请求头:

请求头 说明
X-Api-Account API 账号(邮箱或手机号)
X-Api-Timestamp 当前 Unix 时间戳(秒),与服务器相差不能超过 5 分钟
X-Api-Nonce 随机串,8-64 位字母、数字、_ 或 -,10 分钟内不能重复
X-Api-Signature 签名,见下文

签名原文由 5 行组成,用换行符 \n 连接:

METHOD            请求方法, 大写, 如 GET / POST
PATH?QUERY        请求路径与查询串, 与实际发出的完全一致, 如 /openapi/v1/hosts?page=1
TIMESTAMP         与 X-Api-Timestamp 相同
NONCE             与 X-Api-Nonce 相同
BODY_SHA256       请求体的 SHA-256 (十六进制小写); 没有请求体时为空串的 SHA-256

签名 = hex(HMAC-SHA256(API 密码, 签名原文))(十六进制小写)。

空请求体的 SHA-256 为 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855。

示例(Python)

import hashlib, hmac, json, secrets, time, requests

BASE = "https://example.com"
ACCOUNT = "you@example.com"
SECRET = "你的 API 密码"

def call(method, path, body=None):
    raw = json.dumps(body, separators=(",", ":")).encode() if body is not None else b""
    ts = str(int(time.time()))
    nonce = secrets.token_hex(12)
    text = "\n".join([method, path, ts, nonce, hashlib.sha256(raw).hexdigest()])
    sig = hmac.new(SECRET.encode(), text.encode(), hashlib.sha256).hexdigest()
    headers = {"Content-Type": "application/json", "X-Api-Account": ACCOUNT,
               "X-Api-Timestamp": ts, "X-Api-Nonce": nonce, "X-Api-Signature": sig}
    return requests.request(method, BASE + path, data=raw or None, headers=headers).json()

print(call("GET", "/openapi/v1/account"))

示例(Node.js)

import crypto from 'node:crypto';

const BASE = 'https://example.com', ACCOUNT = 'you@example.com', SECRET = '你的 API 密码';

async function call(method, path, body) {
  const raw = body === undefined ? '' : JSON.stringify(body);
  const ts = String(Math.floor(Date.now() / 1000));
  const nonce = crypto.randomBytes(12).toString('hex');
  const hash = crypto.createHash('sha256').update(raw).digest('hex');
  const sig = crypto.createHmac('sha256', SECRET).update([method, path, ts, nonce, hash].join('\n')).digest('hex');
  const res = await fetch(BASE + path, {
    method, body: raw || undefined,
    headers: { 'Content-Type': 'application/json', 'X-Api-Account': ACCOUNT, 'X-Api-Timestamp': ts, 'X-Api-Nonce': nonce, 'X-Api-Signature': sig },
  });
  return res.json();
}

示例(PHP)

function call($method, $path, $body = null) {
    $base = 'https://example.com'; $account = 'you@example.com'; $secret = '你的 API 密码';
    $raw = $body === null ? '' : json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    $ts = (string) time();
    $nonce = bin2hex(random_bytes(12));
    $sig = hash_hmac('sha256', implode("\n", [$method, $path, $ts, $nonce, hash('sha256', $raw)]), $secret);
    $ch = curl_init($base . $path);
    curl_setopt_array($ch, [CURLOPT_CUSTOMREQUEST => $method, CURLOPT_RETURNTRANSFER => true, CURLOPT_POSTFIELDS => $raw ?: null,
        CURLOPT_HTTPHEADER => ['Content-Type: application/json', "X-Api-Account: $account", "X-Api-Timestamp: $ts",
            "X-Api-Nonce: $nonce", "X-Api-Signature: $sig"]]);
    $res = curl_exec($ch);
    curl_close($ch);
    return json_decode($res, true);
}

3. 响应格式与错误

所有接口返回:

{ "code": 200, "msg": "ok", "data": { } }

code 为 200 表示成功;失败时 HTTP 状态码与 code 的前三位一致(如 40140 对应 HTTP 401),msg 为可直接展示的中文说明。

code 说明
40140 签名校验失败(账号、密码或签名原文不对)
40141 时间戳与服务器相差超过 5 分钟
40142 nonce 重复(请求被重放)
40143 账户未开启 API 或已停用
42940 1 小时内签名错误 20 次,账户的 API 锁定 15 分钟
42901 调用过于频繁(每个账户每分钟最多 600 次)
42202 库存不足
42209 需要先完成实名认证
40919 账单已超过支付期限并自动取消

列表接口支持 page(从 1 开始)与 size(默认 20,最大 100),返回 { "items": [], "total": 0, "page": 1, "size": 20 }。

4. 接口

账户

方法 路径 说明
GET /account 账户信息:余额 credit、信用额度 credit_limit、结算币种 currency、实名状态等
GET /credit/ledger 余额流水,可按 type 筛选

产品与报价

方法 路径 说明
GET /catalog 在售产品:分类 categories、分组 groups(含各产品的周期价、库存、是否售罄)
GET /catalog/products/{id} 产品详情:周期价与全部配置项(options,含各选项 id 与加价)
POST /quote 报价(不下单),参数同下单,返回明细与合计

订单与账单

方法 路径 说明
POST /orders 下单,返回订单 order 与待支付账单 invoice
GET /orders 订单列表,可按 status 筛选
GET /orders/{id} 订单详情
POST /orders/{id}/cancel 取消未支付的订单
GET /invoices 账单列表
GET /invoices/{id} 账单详情
POST /invoices/{id}/pay 用余额支付,{"method": "credit"};有信用额度时可用 credit_limit

下单参数:

{
  "product_id": 12,
  "cycle": "monthly",
  "qty": 1,
  "config": { "34": 201, "35": 20 },
  "password": "Abcd1234",
  "hostname": "web01",
  "auto_renew": true,
  "promo_code": ""
}
  • cycle:hourly daily monthly quarterly semiannually annually biennially triennially onetime,以产品启用的周期为准。
  • config:配置项 id → 选项 id(选择类)或数量(数量类),未传的必选项取默认值;可选项 id 见产品详情。
  • password:可选,8-32 位,需同时含大写字母、小写字母和数字;不传则自动生成。
  • 请求头 Idempotency-Key(建议传,如你系统中的订单号):同一个键重复提交只会创建一个订单,网络超时后可放心重试。
  • 订单金额为 0 时直接完成;否则请在支付期限内调用 /invoices/{id}/pay,超时自动取消并释放库存。

服务

方法 路径 说明
GET /hosts 服务列表,status 可选 pending provisioning active suspended terminated expiring
GET /hosts/{id} 服务详情:IP、登录信息、配置、到期时间、续费价
GET /hosts/{id}/events 服务操作记录
POST /hosts/{id}/renew 续费一个周期(用余额支付),返回续费账单
PUT /hosts/{id}/auto-renew 自动续费开关,{"on": true}
PUT /hosts/{id}/remark 备注名与分组,{"remark": "", "tag": ""}
GET /hosts/{id}/power 实时电源状态:on off busy unknown
POST /hosts/{id}/power 电源操作,{"action": "on"},可选 on off reboot hard_off hard_reboot
GET /hosts/{id}/os 可重装的系统列表
POST /hosts/{id}/reinstall 重装系统,{"value_id": 系统选项 id}
POST /hosts/{id}/password 重置密码,{"password": "新密码"}
GET /hosts/{id}/tasks/{task_id} 异步操作进度:status、done、error
GET /hosts/{id}/charts 可用的监控指标
GET /hosts/{id}/chart 监控数据,参数 type、select、start、end(毫秒时间戳)
GET /hosts/{id}/upgrade 可调整的配置与价格
POST /hosts/{id}/upgrade/quote 升降配报价
POST /hosts/{id}/upgrade 提交升降配,补差价生成账单(余额支付后生效),降配差价退回余额
POST /hosts/{id}/cancel 申请取消,{"type": "end" 或 "immediate", "reason": "原因"}

电源、重装、重置密码为异步操作,返回 {"task_id": 123, "status": "queued"},可轮询任务进度或等待事件回调;这些接口同样支持 Idempotency-Key。

5. 事件回调(Webhook)

在「API 对接」页填写回调地址(http/https 公网地址,端口 80 / 443 / 8080 / 8443 / 8888),发生以下事件时平台会 POST 到该地址:

事件 触发时机 data 主要字段
order.paid 订单支付成功 order_id invoice_id amount currency host_ids
host.status_changed 服务状态变化(开通中、运行中、暂停、恢复、终止) host_id status from reason main_ip next_due_at
host.renewed 续费成功 host_id next_due_at previous_due_at invoice_id
ping 在 API 对接页点击「发送测试」 message

请求体:

{
  "id": "host.status_changed:event1024",
  "event": "host.status_changed",
  "created": 1767225600,
  "data": { "host_id": 88, "status": "active", "from": "provisioning", "reason": "provision", "main_ip": "203.0.113.10" }
}

请求头:X-Api-Event(事件名)、X-Api-Event-Id(事件 id)、X-Api-Timestamp、X-Api-Signature。

验签:X-Api-Signature = hex(HMAC-SHA256(API 密码, X-Api-Timestamp + "\n" + 原始请求体))。请先验签再处理。

  • 返回任意 2xx 视为送达;超时(15 秒)或非 2xx 会按 30 秒、2 分钟、10 分钟、30 分钟、2 小时逐步重试。
  • 同一事件重试时 id 不变,请按 id 去重;事件可能乱序到达,以 /hosts/{id} 查询到的当前状态为准。

6. 推荐流程

  1. 定时(如每小时)拉取 /catalog 同步产品与价格,用户选购时调用 /quote 报价。
  2. 用户下单:POST /orders(带 Idempotency-Key)→ POST /invoices/{id}/pay。
  3. 等待 host.status_changed 回调中 status 变为 active,或轮询 /hosts/{id},取得 IP 与登录信息交付给用户。
  4. 到期前调用 /hosts/{id}/renew,或开启自动续费并保证余额充足。

7. 限制

  • 每个账户每分钟最多 600 次调用;1 小时内签名错误 20 次锁定 15 分钟。
  • 请求体最大 2 MB。
  • 远程控制台需要在浏览器中打开,暂不通过 API 提供。