开放 API 开发文档
开放 API 让你的网站、业务系统或自动化脚本直接调用本平台的能力:查询产品与价格、下单、用余额支付、管理已开通的服务,并通过事件回调实时获知开通与状态变化。
- 所有价格、库存、限购与实名要求和在控制台下单完全一致(按你所在客户组的折扣计算)。
- 每个请求独立签名,无需先登录换取 token,也不需要保存会话。
- 请求与响应均为 JSON。
如果你的网站使用 魔方财务,无需开发,直接在魔方财务后台添加接口即可,见「魔方财务对接」指南。
1. 开通与凭据
- 登录控制台,进入「账户设置 → API 对接」,点击开通。
- 记下 API 账号(你的登录邮箱或手机号)和 API 密码(只显示一次,可凭登录密码再次查看或重置)。
- 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:hourlydailymonthlyquarterlysemiannuallyannuallybienniallytrienniallyonetime,以产品启用的周期为准。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. 推荐流程
- 定时(如每小时)拉取
/catalog同步产品与价格,用户选购时调用/quote报价。 - 用户下单:
POST /orders(带Idempotency-Key)→POST /invoices/{id}/pay。 - 等待
host.status_changed回调中status变为active,或轮询/hosts/{id},取得 IP 与登录信息交付给用户。 - 到期前调用
/hosts/{id}/renew,或开启自动续费并保证余额充足。
7. 限制
- 每个账户每分钟最多 600 次调用;1 小时内签名错误 20 次锁定 15 分钟。
- 请求体最大 2 MB。
- 远程控制台需要在浏览器中打开,暂不通过 API 提供。