Voyager 开放 API
VOYAGER · DARKSTAR · OPEN API

把 KARDS 卡牌数据库
接进你的项目

一套只读为主、用 API Key 认证的开放接口:卡牌数据与筛选、单卡详情、卡图与缩略图、 官方头像 / 卡背 / 总部资源,以及可以直接调用的 DarkStar AI 助手。 不需要网页登录态,不占用网页 Cookie。

1,646张卡牌
74个头像
485张卡背
25张总部
2,000点 / Key / 天
使用范围:卡牌数据、卡图、头像、卡背、总部与 AI;请勿把接口用于批量爬取、转售或任何违反 1939 Games 条款的用途。 本站是非官方粉丝站,卡图与官方素材版权归 1939 Games。

认证方式

所有 /api/v1/* 请求都需要一个 API Key。Key 在页面底部「我的 Key」里创建, 明文 只在创建时显示一次,服务端只保存它的 SHA-256。

推荐把 Key 放在请求头里。查询参数 ?key= 虽然能用,但会出现在访问日志、浏览器历史和 Referer 中, 只建议在临时调试时使用。
HTTP 请求头
Authorization: Bearer vy_你的APIKey
查询参数(不推荐)
GET /api/v1/cards?limit=3&key=vy_你的APIKey
情况HTTP 状态返回
没有带 Key401{ "ok": false, "error": "缺少 API Key…", "code": "NO_KEY" }
Key 格式不对 / 不存在401code: "BAD_KEY"
Key 已吊销401code: "REVOKED"

快速开始

拿到 Key 后,先拉 3 张卡验证一下:

curl
curl "https://voyager-kards.pages.dev/api/v1/cards?limit=3" \
  -H "Authorization: Bearer vy_你的APIKey"
JavaScript (fetch)
const KEY = 'vy_你的APIKey';

const res = await fetch('https://voyager-kards.pages.dev/api/v1/cards?limit=3', {
  headers: { Authorization: `Bearer ${KEY}` },
});
if (!res.ok) throw new Error((await res.json()).error);

const data = await res.json();
console.log(data.total, data.cards);

小提示:响应头里有 X-API-Points(本次消耗)、X-API-Points-Today(今天已用)、 X-API-Points-Limit(每日上限)和 X-API-Points-Remaining(今天还剩)。

接口列表

基础地址:https://voyager-kards.pages.dev(也可以换成你当前访问的域名)。所有响应都是 UTF-8 JSON,除非是图片。

GET /api/v1/cards 卡牌列表 / 筛选

分页拉取卡牌,支持按名称、阵营、类型、稀有度、费用筛选。返回精简字段,卡图与缩略图地址也在每条记录里。

参数类型默认说明
limitint20每页条数,1–100
offsetint0跳过条数,用于翻页
qstring—在 id / 中文名 / 英文名 / 卡牌代码 / 描述里模糊搜索
factionstring—阵营,如 Germany;可用逗号分隔多个:Germany,Soviet
typestring—infantry / tank / fighter / bomber / artillery / order / countermeasure
raritystring—Standard / Limited / Special / Elite
costint—费用,0–30
curl
curl "https://voyager-kards.pages.dev/api/v1/cards?faction=Germany&type=tank&limit=5" \
  -H "Authorization: Bearer vy_你的APIKey"
JavaScript (fetch)
const params = new URLSearchParams({
  faction: 'Germany', type: 'tank', limit: '5', offset: '0',
});

const res = await fetch(`/api/v1/cards?${params}`, {
  headers: { Authorization: 'Bearer vy_你的APIKey' },
});
const { total, count, cards } = await res.json();
console.log(`共 ${total} 张,本页 ${count} 张`, cards[0]);
响应示例(节选)
{
  "ok": true,
  "total": 139,
  "count": 5,
  "limit": 5,
  "offset": 0,
  "cards": [
    {
      "id": "panzer_iiil",
      "name": "三号坦克 L 型",
      "nameEn": "PANZER III L",
      "faction": "Germany",
      "type": "tank",
      "rarity": "Standard",
      "cost": 3,
      "atk": 2,
      "def": 3,
      "reserved": false,
      "set": "Base",
      "token": "…",
      "img": true,
      "desc": "…",
      "attrs": [],
      "attrZh": [],
      "imageUrl": "https://voyager-kards.pages.dev/api/v1/img/panzer_iiil",
      "thumbUrl": "https://voyager-kards.pages.dev/api/v1/thumb/panzer_iiil"
    }
  ]
}
GET /api/v1/cards/:id 单卡详情

按卡牌 id 取一张卡的完整字段(与列表结构一致,包含描述、属性与图片地址)。id 就是列表里的 id,例如 panzer_iiil。

curl
curl "https://voyager-kards.pages.dev/api/v1/cards/panzer_iiil" \
  -H "Authorization: Bearer vy_你的APIKey"
JavaScript (fetch)
const res = await fetch('/api/v1/cards/panzer_iiil', {
  headers: { Authorization: 'Bearer vy_你的APIKey' },
});
const { card } = await res.json();
console.log(card.name, card.cost, card.atk, card.def);

找不到时返回 404 { "ok": false, "error": "卡牌不存在" }。

GET /api/v1/avatars 官方头像

列出官方头像(含稀有度与解锁段位)。支持 limit(1–200,默认 50)、offset、q。每条记录带 imageUrl。

GET /api/v1/cardbacks 官方卡背

列出官方卡背,字段含 set / setLabel / group / variant / imageUrl。

GET /api/v1/hq 总部 / 战场背景

列出总部背景,字段含 intro / header / dim / kind / imageUrl。

curl(三个接口同一套参数)
curl "https://voyager-kards.pages.dev/api/v1/avatars?limit=10" \
  -H "Authorization: Bearer vy_你的APIKey"

curl "https://voyager-kards.pages.dev/api/v1/cardbacks?q=naval&limit=10" \
  -H "Authorization: Bearer vy_你的APIKey"

curl "https://voyager-kards.pages.dev/api/v1/hq?limit=10" \
  -H "Authorization: Bearer vy_你的APIKey"
响应示例(头像)
{
  "ok": true,
  "kind": "avatars",
  "kindZh": "头像",
  "total": 74,
  "count": 10,
  "limit": 10,
  "offset": 0,
  "items": [
    {
      "id": "avatar_91st_astrakhan",
      "name": "阿斯特拉罕第 91 团",
      "nameEn": "91st Astrakhan",
      "rarity": "Common",
      "tier": 1,
      "file": "avatars/T_Portrait_Standard_91st-Astrakhan.jpg",
      "size": 17251,
      "imageUrl": "https://voyager-kards.pages.dev/resources/avatars/T_Portrait_Standard_91st-Astrakhan.jpg"
    }
  ]
}
GET /api/v1/img/:id 卡图(PNG)
GET /api/v1/thumb/:id 缩略图(JPG)

直接返回图片二进制,Content-Type 为 image/png 或 image/jpeg。 图片按真实字节计费(每 1KB 一点),所以拉大图之前先看今天的剩余点数。

curl 保存到文件
curl -L "https://voyager-kards.pages.dev/api/v1/thumb/panzer_iiil" \
  -H "Authorization: Bearer vy_你的APIKey" \
  -o panzer_iiil.jpg

curl -L "https://voyager-kards.pages.dev/api/v1/img/panzer_iiil" \
  -H "Authorization: Bearer vy_你的APIKey" \
  -o panzer_iiil.png
JavaScript(转 blob / object URL)
const res = await fetch('/api/v1/thumb/panzer_iiil', {
  headers: { Authorization: 'Bearer vy_你的APIKey' },
});
if (!res.ok) throw new Error('图片获取失败: ' + res.status);

const blob = await res.blob();
document.querySelector('img').src = URL.createObjectURL(blob);

卡图不存在、或图床暂时没同步时会返回 404 JSON。

POST /api/v1/ai DarkStar AI 助手

把一句话问题交给 DarkStar。请求体是 JSON,只有一个必填字段 prompt(最长 2000 字), 返回一段中文回答。非流式、不带历史上下文。

字段类型必填说明
promptstring是你的问题,例如「日快卡组怎么留牌?」
AI 同时占用账号的站内 AI 额度。除 API 点数外,每次调用还会消耗账号当天的 1 次 AI 对话额度 (DAILY_CHAT_LIMIT,默认 40 次/天);额度用完会返回 429 和 code: "AI_QUOTA"。 被封禁的账号不能通过 API 绕过 AI 限制。
curl
curl -X POST "https://voyager-kards.pages.dev/api/v1/ai" \
  -H "Authorization: Bearer vy_你的APIKey" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"日快卡组起手怎么留牌?用三点说明。"}'
JavaScript (fetch)
const res = await fetch('/api/v1/ai', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer vy_你的APIKey',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ prompt: '日快卡组起手怎么留牌?用三点说明。' }),
});
const data = await res.json();
if (!data.ok) throw new Error(data.error);
console.log(data.reply);
响应示例
{
  "ok": true,
  "model": "deepseek-chat",
  "reply": "1. 优先找 1–2 费的单位……",
  "aiUsage": { "used": 12, "limit": 40 }
}
GET /api/keys Key 管理接口(网页登录态)

下面三个接口是给本页「我的 Key」用的,使用网页 Cookie(vy_s)登录态,不是 API Key。 普通调用数据接口不需要它们。

方法与路径作用说明
POST /api/keys创建 Keybody { "label": "备注" };返回一次性明文 plaintext;每人最多 5 个有效 Key
GET /api/keys列出我的 Key只返回前缀、备注、创建时间、最后使用、当天点数与次数
DELETE /api/keys?id=吊销 Key吊销后立即失效,不可恢复

限额与计费

2,000每个 Key 每天的点数上限
1 + ⌈字节/1024⌉每次调用消耗的点数

计费规则很简单:

  1. 每次调用先计 1 点。
  2. 再加上响应体积:返回字节数 ÷ 1024,向上取整。例如返回 3.2KB 记 4 点,本次共 5 点;几百字节的 JSON 也会记 1 点,所以一次调用最少 2 点。
  3. 图片接口按图片真实字节计费;拉一张 300KB 的卡图会消耗约 301 点。
  4. 同一账号的所有 Key 合计每天也只能用 2,000 点 —— 多建 Key 不能绕过。
  5. 点数按 UTC+8 自然日重置(每天 00:00)。
  6. 失败的请求也按同样规则计点(至少 2 点;429 超限响应不扣点),避免用错误请求免费扫接口。

每次响应都带这些头,方便你的程序自己控制节奏:

响应头含义
X-API-Points本次调用消耗的点数
X-API-Points-Today这个 Key 今天累计已用点数(含本次)
X-API-Points-Limit每日点数上限(默认 2000)
X-API-Points-Remaining这个 Key 今天剩余点数
X-API-Key-Prefix本次使用的 Key 前缀(便于排查)
Retry-After仅在 429 时出现:距离重置的秒数

超限时返回 429 Too Many Requests,不会返回数据、也不会扣点:

429 响应示例
{
  "ok": false,
  "error": "这个 Key 今日 API 用量已用完(2000 点),8 小时后重置",
  "code": "API_QUOTA",
  "scope": "key",
  "limit": 2000,
  "used": 1998,
  "keyPrefix": "vy_ab12",
  "resetInSeconds": 28800,
  "docs": "/api-docs#limits"
}
状态码什么时候出现
200成功
400参数不合法(例如 limit=999、cost=abc)
401Key 缺失 / 格式错误 / 已吊销
403账号被封禁(仅 AI 接口)
404卡牌 / 图片 / 接口不存在
405方法不对(例如对只读接口发 POST)
429点数超限,或账号 AI 额度用完(AI_QUOTA)

我的 Key

正在检查登录状态…

说明与边界

接口稳定吗?
这是粉丝站提供的免费接口,可能因为数据更新、上游额度或维护而短暂不可用;不承诺 SLA,请在自己的程序里做好超时与重试。
可以商用 / 大量抓取吗?
不建议。接口是给玩家工具、社区项目和个人学习用的;请遵守点数限制,不要用多个账号或多建 Key 绕过。卡牌数据与官方素材版权归 1939 Games。
为什么 AI 接口没有流式输出?
开放接口为了简单和可计量,只提供一次性返回;站内网页版仍然有完整的流式对话、历史与组牌能力。
图片能直接热链吗?
imageUrl 指向站内 /resources/ 的静态文件,可以直接用在网页里;但请控制请求量,不要把本站当图床。
发现 bug / 想加接口?
欢迎到主站论坛反馈。新增接口会优先考虑调用量大、通用性强的需求。