面板开放 API:用脚本管理站点
面板提供一组 REST 接口,可以把站点与服务器信息接到自己的脚本、CI/CD、监控或计费系统里,也可以批量创建、删除站点。接口与面板共用同一个服务端口,使用 API Key 鉴权。
接入信息
| 项目 | 值 |
| 接口地址 | http://<面板地址>:8888/api/v1 |
| 鉴权 | X-API-Key: <你的密钥> |
| 请求格式 | GET 用查询参数;POST 用 application/x-www-form-urlencoded(不是 JSON) |
| 响应格式 | application/json;成功直接返回数据对象,失败返回 {"error":"...","code":403} |
| 前置条件 | 面板已绑定账号,且当前授权在有效期内 |
创建 API 密钥
- 进入面板「API 密钥」→「新建密钥」;
- 勾选权限范围(scope),按最小权限原则只给需要的;
- 可设置有效期与备注。密钥只在创建时完整显示一次,请立即保存到密码管理器。
密钥以哈希形式存储,面板不保存明文;可选范围还会受当前套餐约束,套餐未开放的能力不会出现在勾选项里。怀疑泄露时停用或删除密钥即可立即失效。
权限范围(scope)
| scope | 对应接口 | 用途 |
system:read | GET /api/v1/system | 主机名、面板版本、CPU / 内存 / 磁盘占用、站点数 |
sites:read | GET /api/v1/sites、GET /api/v1/site/get | 站点列表与单个站点详情(含已绑定域名) |
sites:create | POST /api/v1/site/create | 新建站点 |
sites:delete | POST /api/v1/site/delete | 删除站点及其域名、文件目录(不可恢复) |
plan:read | GET /api/v1/plan | 当前套餐的配额与可用功能,用于按版本适配脚本 |
接口说明
| 方法 | 路径 | 参数 | 返回 |
| GET | /api/v1/sites | — | {"sites":[...],"count":N} |
| GET | /api/v1/site/get | name 站点名 | {"site":{...},"domains":["..."]} |
| GET | /api/v1/system | — | 主机名、版本、CPU / 内存 / 磁盘、站点数 |
| GET | /api/v1/plan | — | plan、quotas、features、api_scopes、vhost_count 等 |
| POST | /api/v1/site/create | name、passwd,可选 type / runtime / web_quota / db_quota / max_connect / speed_limit / max_subdir / cron_count | 创建结果 |
| POST | /api/v1/site/delete | name 站点名 | 删除结果 |
创建站点时 name 为 3–32 位小写字母、数字、- 或 _,passwd 为 6–64 位。资源额度超过套餐上限会自动收口到上限;站点级功能开关不允许通过 API 覆盖;系统站点不允许删除。
curl 示例
# 站点列表
curl -s http://82.157.137.169:8888/api/v1/sites \
-H "X-API-Key: $NC_API_KEY"
# 服务器信息
curl -s http://82.157.137.169:8888/api/v1/system \
-H "X-API-Key: $NC_API_KEY"
# 单个站点
curl -s "http://82.157.137.169:8888/api/v1/site/get?name=demo01" \
-H "X-API-Key: $NC_API_KEY"
# 新建站点(表单编码,不是 JSON)
curl -s -X POST http://82.157.137.169:8888/api/v1/site/create \
-H "X-API-Key: $NC_API_KEY" \
-d "name=demo01" \
-d "passwd=StrongPass123" \
-d "runtime=php"
# 删除站点(不可恢复)
curl -s -X POST http://82.157.137.169:8888/api/v1/site/delete \
-H "X-API-Key: $NC_API_KEY" \
-d "name=demo01"
PHP 示例
<?php
$base = 'http://82.157.137.169:8888';
$key = getenv('NC_API_KEY');
function ncApi($base, $key, $method, $path, array $data = []) {
$url = $base . $path;
$ch = curl_init();
if ($method === 'GET' && $data) {
$url .= '?' . http_build_query($data);
}
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: ' . $key],
CURLOPT_CUSTOMREQUEST => $method,
]);
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
}
$body = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return [$code, json_decode($body, true)];
}
[$code, $res] = ncApi($base, $key, 'GET', '/api/v1/sites');
if ($code !== 200) {
fwrite(STDERR, ($res['error'] ?? 'request failed') . "\n");
exit(1);
}
foreach ($res['sites'] as $site) {
echo $site['name'], "\t", $site['domain'], "\n";
}
Node.js 示例
const base = 'http://82.157.137.169:8888';
const key = process.env.NC_API_KEY;
async function ncApi(method, path, data = null) {
const url = new URL(base + path);
const opt = { method, headers: { 'X-API-Key': key } };
if (method === 'POST') {
opt.body = new URLSearchParams(data);
} else if (data) {
for (const [k, v] of Object.entries(data)) url.searchParams.set(k, v);
}
const resp = await fetch(url, opt);
const body = await resp.json();
if (!resp.ok) throw new Error(`${resp.status} ${body.error}`);
return body;
}
const { count, sites } = await ncApi('GET', '/api/v1/sites');
console.log(count, sites.map((s) => s.name));
错误码
| 状态码 | 含义 |
| 401 | API Key 无效、已停用或已过期 |
| 403 | 密钥缺少对应 scope;面板未绑定账号;授权已过期;系统站点不可删除 |
| 404 | 接口或站点不存在 |
| 400 | 缺少必填参数,或参数格式不合法 |
安全建议
- 密钥只放在环境变量或密钥管理服务里,不要写进前端代码、公开仓库或截图;
- 按最小权限创建多个密钥,按用途区分,便于单独吊销;
- 接口尽量走 HTTPS 或只在内网调用,避免明文密钥在公网传输;
- 删除类接口请先在测试站点验证,删除后文件和数据库不会进入回收站。