MoonAPI 接口文档
自建存储(Cloudflare R2 + KV)驱动的 API 服务。当前提供「每日知识卡片」对外接口,以及配套的后台管理接口。
Base URL 与认证
| 项 | 值 |
|---|---|
| Base URL | https://api.lunor.top |
| 认证方式 | 请求头 Authorization: Bearer <API_KEY>(或 X-API-Key: <API_KEY>) |
| 密钥获取 | 登录 管理后台 → 「API 密钥」页创建(形如 mk_live_…) |
| 数据格式 | JSON(UTF-8),全部接口允许跨域(CORS) |
| 日期口径 | 「每日」按北京时间(UTC+8)自然日计算 |
每日知识卡片对外 · 需密钥
GET/api/v1/daily-card
返回当日知识卡片。同一天内多次请求返回同一张卡片;日期到达后自动轮换。
查询参数
| 参数 | 必填 | 说明 |
|---|---|---|
| date | 否 | 指定日期,格式 YYYY-MM-DD;缺省为今天 |
成功响应 200
{
"code": 0,
"message": "success",
"requestId": "8f2c…",
"data": {
"date": "2026-09-01",
"source": "auto", // pinned=后台排期 | auto=自动轮换 | builtin=内置兜底
"card": {
"id": "6f9c…",
"title": "月亮正以每年约 3.8 厘米的速度远离地球",
"category": "科学",
"content": "由于潮汐相互作用……",
"source": "NASA 月球测距计划",
"tags": ["天文", "月球"],
"createdAt": "2026-09-01T05:00:00.000Z",
"updatedAt": "2026-09-01T05:00:00.000Z"
}
}
}
管理后台可为指定日期「排期」固定卡片;未排期的日期按日期哈希在卡片库中自动轮换;卡片库为空时返回内置卡片,接口永不为空。
健康检查公开
GET/api/health
无需认证。返回服务状态及 KV / R2 绑定自检结果(bindings.kv、bindings.r2 均为 true 表示后端存储配置正常)。
管理接口管理员令牌
认证与端点清单
管理接口供后台页面使用,需请求头 Authorization: Bearer <管理员令牌>。令牌在首次访问 /admin 时初始化(仅存哈希)。/api/admin/setup 只能成功调用一次。
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/admin/setup | 初始化管理员令牌,请求体 {"token":"…"}(≥8 位) |
| POST | /api/admin/login | 校验管理员令牌 |
| GET | /api/admin/cards | 卡片列表(索引) |
| POST | /api/admin/cards | 新增卡片(单个对象或 {"cards":[…]} 批量,≤500 条) |
| GET PUT DELETE | /api/admin/cards/{id} | 读取 / 更新 / 删除单张卡片 |
| POST | /api/admin/cards/batch-delete | 批量删除,请求体 {"ids":[…]} |
| GET | /api/admin/daily | 排期列表 |
| POST | /api/admin/daily | 设置排期 {"date":"YYYY-MM-DD","cardId":"…"};cardId 为 null 表示清除 |
| GET | /api/admin/keys | API 密钥列表 |
| POST | /api/admin/keys | 创建密钥 {"name":"备注"};吊销 {"action":"revoke","key":"…"} |
卡片字段
| 字段 | 必填 | 说明 |
|---|---|---|
| title | 是 | 标题,≤120 字 |
| content | 是 | 正文,≤5000 字 |
| category | 否 | 分类,缺省「未分类」 |
| source | 否 | 内容来源 |
| tags | 否 | 字符串数组,≤10 个 |
响应信封
所有接口返回统一结构:{code, message, data, requestId}。code=0 表示成功,非 0 时 HTTP 状态码同步为非 2xx,message 为可直接展示的错误说明。
错误码表
| code | HTTP | 含义 |
|---|---|---|
| 40000 | 400 | 请求体不是合法 JSON |
| 40001 | 400 | date 参数格式错误 |
| 40002 | 400 | 管理员令牌长度不足 |
| 40003 / 40005 | 400 | 批量数量超出 1-500 限制 |
| 40004 / 40006 | 400 | 更新内容无效 / 缺少待吊销密钥 |
| 40101 / 40102 | 401 | 缺少管理员令牌 / 令牌错误 |
| 40103 / 40104 | 401 | 缺少 API Key / Key 无效 |
| 40302 | 403 | API Key 已被吊销 |
| 40401 | 404 | 卡片不存在 |
| 40901 | 409 | 管理员已初始化,禁止重复 setup |
| 50301 | 503 | 管理员未初始化,需先调用 setup |
调用示例
cURL
curl -s https://api.lunor.top/api/v1/daily-card \ -H "Authorization: Bearer mk_live_xxxxxxxx"
JavaScript(fetch)
const res = await fetch('https://api.lunor.top/api/v1/daily-card', {
headers: { Authorization: `Bearer ${API_KEY}` },
});
const { code, data } = await res.json();
if (code === 0) {
console.log(data.date, data.card.title, data.card.content);
}
Python(requests)
import requests
r = requests.get(
"https://api.lunor.top/api/v1/daily-card",
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=10,
)
r.raise_for_status()
card = r.json()["data"]["card"]
print(card["title"], card["content"], sep="\n")