代码示例

五种语言的最小可用封装。共同点:统一处理 Bearer 头,并且先判 ok 再判状态码

cURL

export HSCDN_KEY="你的API密钥"
BASE="https://cdn.treeidc.cn"

# 读: 站点列表
curl -s -H "Authorization: Bearer $HSCDN_KEY" "$BASE/api/me/sites"

# 写: 修改回源地址(把 123 换成你自己的站点 ID, 否则 404)
curl -s -X POST "$BASE/api/sites/123/update" \
  -H "Authorization: Bearer $HSCDN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"origins":[{"addr":"203.0.113.10","weight":1,"status":true}]}'

# 写: 刷新缓存
curl -s -X POST "$BASE/api/cache/refresh" \
  -H "Authorization: Bearer $HSCDN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"urls":"https://www.example.com/index.html"}'

Python

下面这段可以直接跑(只读),把密钥放进环境变量 HSCDN_KEY 即可:

import os
import requests

BASE = "https://cdn.treeidc.cn"
S = requests.Session()
S.headers.update({"Authorization": "Bearer " + os.environ["HSCDN_KEY"]})

def call(method, path, **kw):
    r = S.request(method, BASE + path, timeout=20, **kw)
    d = r.json()
    if not d.get("ok"):                       # 先看 ok, 再看状态码
        raise RuntimeError(f"{path} 失败: {d.get('message')} (HTTP {r.status_code})")
    return d

# 列出站点
for s in call("GET", "/api/me/sites")["sites"]:
    print(s["id"], s["domain"], "启用" if s["enabled"] else "停用")

写操作 —— SITE_ID 换成上面列出来的、你自己的站点 ID:

SITE_ID = 123          # ← 换成你自己的站点 ID, 否则会得到 404「网站不存在」

# 改回源
d = call("POST", f"/api/sites/{SITE_ID}/update",
         json={"origins": [{"addr": "203.0.113.10", "weight": 1, "status": True}]})

# 字段名写错时请求照样返回 ok:true —— 只有这里能看出来
if d.get("ignored_fields"):
    raise RuntimeError(f"这些字段名写错了, 没有生效: {d['ignored_fields']}")

# 刷新缓存(注意 urls 是**字符串**, 多条用换行分隔)
call("POST", "/api/cache/refresh",
     json={"urls": "\n".join(["https://www.example.com/index.html"])})

Node.js

只读部分,可以直接跑(需要 Node 18+ 的原生 fetch):

const BASE = 'https://cdn.treeidc.cn'

async function call (method, path, body) {
  const res = await fetch(BASE + path, {
    method,
    headers: {
      Authorization: `Bearer ${process.env.HSCDN_KEY}`,
      ...(body ? { 'Content-Type': 'application/json' } : {})
    },
    body: body ? JSON.stringify(body) : undefined
  })
  const data = await res.json()
  if (!data.ok) throw new Error(`${path} 失败: ${data.message} (HTTP ${res.status})`)
  return data
}

const { sites } = await call('GET', '/api/me/sites')
console.log(sites.map(s => s.domain))

写操作 —— SITE_ID 换成上面列出来的、你自己的站点 ID:

const SITE_ID = 123   // ← 换成你自己的站点 ID, 否则会抛「网站不存在 (HTTP 404)」

const d = await call('POST', `/api/sites/${SITE_ID}/update`, {
  origins: [{ addr: '203.0.113.10', weight: 1, status: true }]
})
if (d.ignored_fields?.length) throw new Error(`字段名写错了: ${d.ignored_fields}`)

await call('POST', '/api/cache/refresh', {
  urls: 'https://www.example.com/index.html'   // 字符串, 多条用 \n 分隔
})

PHP

<?php
function hscdn($method, $path, $body = null) {
    $ch = curl_init('https://cdn.treeidc.cn' . $path);
    $headers = ['Authorization: Bearer ' . getenv('HSCDN_KEY')];
    if ($body !== null) {
        $headers[] = 'Content-Type: application/json';
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
    }
    curl_setopt_array($ch, [
        CURLOPT_CUSTOMREQUEST  => $method,
        CURLOPT_HTTPHEADER     => $headers,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 20,
    ]);
    $raw = curl_exec($ch);
    curl_close($ch);

    $data = json_decode($raw, true);
    if (empty($data['ok'])) {
        throw new Exception($path . ' 失败: ' . ($data['message'] ?? '未知错误'));
    }
    return $data;
}

$sites = hscdn('GET', '/api/me/sites')['sites'];
hscdn('POST', '/api/cache/refresh', ['urls' => 'https://www.example.com/index.html']);

Go

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
    "os"
    "time"
)

const base = "https://cdn.treeidc.cn"

func call(method, path string, body any) (map[string]any, error) {
    buf := bytes.NewBuffer(nil)
    if body != nil {
        b, _ := json.Marshal(body)
        buf = bytes.NewBuffer(b)
    }
    req, _ := http.NewRequest(method, base+path, buf)
    req.Header.Set("Authorization", "Bearer "+os.Getenv("HSCDN_KEY"))
    if body != nil {
        req.Header.Set("Content-Type", "application/json")
    }

    res, err := (&http.Client{Timeout: 20 * time.Second}).Do(req)
    if err != nil {
        return nil, err
    }
    defer res.Body.Close()

    var d map[string]any
    if err := json.NewDecoder(res.Body).Decode(&d); err != nil {
        return nil, err
    }
    if ok, _ := d["ok"].(bool); !ok {
        return nil, fmt.Errorf("%s 失败: %v (HTTP %d)", path, d["message"], res.StatusCode)
    }
    return d, nil
}

文档没写到的情况,或某个字段的行为与描述不符 —— 请在控制台提交工单,附上请求路径、请求体与完整响应,能最快定位。