发现
接口发现
低成本入口,列出接口族、schema、版本、语言和文档链接。
大多数客户端可以先读取 API 索引,再跟随最新版本和下载入口。
步骤 1
读取 API 索引,确认接口族、schema、语言和缓存策略。
/api/v1/index.json步骤 2
请求版本详情,并选择与设备匹配的平台 key。
/api/v1/releases/latest.json步骤 3
使用 builds.*.url 下载文件,完成后用 builds.*.sha256 确认本地文件与发布构建一致。
/download/0.17q/windows按用途筛选。每个卡片都可复制真实示例 URL。
发现
低成本入口,列出接口族、schema、版本、语言和文档链接。
版本
当前版本、各平台构建、校验值和更新日志。
内容
图鉴条目、世界区域、你知道吗冷知识以及本地化正文。
DIY
公开关卡库、详情 JSON、GDF 下载与提交入口。
搜索/动态
稳定的搜索语料、公告流,以及适合机器人的订阅入口。
下载
由本站下载服务提供的二进制文件,支持 HEAD 和 Range 请求。
RSS
面向阅读器的 RSS 2.0 发布源。
GET · HEAD · DIY
返回依赖请求来源的上传配置。该响应不会进入公共缓存。
/api/v1/diy/runtime-config.jsonGET · 发现
面向启动器、Bot、镜像站和代理的机器可读发现入口,避免抓取页面或硬编码路径。
/api/v1/index.jsonGET · 版本
适用于启动器、镜像站和机器人的完整版本详情,包含所有平台的构建信息。
/api/v1/releases/latest.jsonGET · 版本
这份更新清单兼容旧客户端;顶层字段保留 Windows 64 位主构建,builds 则包含所有平台。
/api/v1/updates/latest.jsonGET · 版本
列出已公开版本,并提供当前 latest 字段和版本详情链接。
/api/v1/releases.jsonGET · 版本
一次返回中英两种更新日志内容,适合公告机器人和启动器更新页。
/api/v1/changelog/0.17q.jsonGET · 内容
本地化图鉴目录,包含分类计数、条目链接、肖像资源和跨语言 alternate 链接。
/api/v1/encyclopedia/zh/index.jsonGET · 内容
单个植物、僵尸或 Boss 的本地化详情,包含机制、联动、肖像与前后导航。
/api/v1/encyclopedia/zh/peashooter.jsonGET · 内容
本地化世界设定索引;目前没有单独的区域详情 JSON,区域完整段落直接放在 regions 中。
/api/v1/world/zh/index.jsonGET · 内容
本地化冷知识与玩法贴士目录;首页区块与外部工具都读取这套人工校验内容。
/api/v1/did-you-know/zh/index.jsonGET · HEAD · 内容
由服务端读取静态目录后进行确定性随机选择;适合只展示一条冷知识的启动器、机器人或工具。
/api/v1/did-you-know/zh/random.json?context=homeHero&entry=sunflower&seed=session-42GET · HEAD · DIY
列出已公开的 DIY 关卡,支持搜索、筛选、排序、分页和本地收藏批量回查。
/api/v1/diy/levels.json?sort=hot&tag=conveyor&limit=20GET · HEAD · DIY
返回单个公开 DIY 关卡的元数据、解析摘要、下载链接和可用于客户端展示的关卡概览。
/api/v1/diy/levels/sample-level-id.jsonGET · HEAD · DIY
下载已公开 DIY 关卡的 GDF 文件;HEAD 可用于读取文件名、大小和校验信息。
/api/v1/diy/levels/sample-level-id/download.gdfGET · HEAD · DIY
返回已公开 DIY 关卡的上传图标;HEAD 可用于读取类型、大小和尺寸元数据。
/api/v1/diy/levels/sample-level-id/iconPOST · DIY
提交 .gdf 文件与公开元数据;成功响应表示文件已接收并返回所有者凭证。
/api/v1/diy/levelsPOST · DIY
将上传响应中的 owner secret 换取网站 HttpOnly owner session。
/api/v1/diy/levels/sample-level-id/owner/sessionPOST · DIY
使用上传响应中的 owner secret 查询或管理自己的提交;网站也可通过 HttpOnly owner session 使用同一接口。
/api/v1/diy/levels/sample-level-id/owner/statusPOST · DIY
使用上传响应中的 owner secret 查询或管理自己的提交;网站也可通过 HttpOnly owner session 使用同一接口。
/api/v1/diy/levels/sample-level-id/owner/editPOST · DIY
使用上传响应中的 owner secret 查询或管理自己的提交;网站也可通过 HttpOnly owner session 使用同一接口。
/api/v1/diy/levels/sample-level-id/owner/removePOST · DIY
使用上传响应中的 owner secret 查询或管理自己的提交;网站也可通过 HttpOnly owner session 使用同一接口。
/api/v1/diy/levels/sample-level-id/owner/updateGET · 搜索/动态
这是面向外部工具的站内搜索文档封装;不要依赖根目录的 search-index 文件。
/api/v1/search/zh.jsonGET · 搜索/动态
面向启动器、机器人和聚合器的本地化新闻流。
/api/v1/news/zh.jsonGET · HEAD · 下载
用于下载 Windows 和 Android 构建;支持 HEAD 预检和单段 Range 请求,文件名会通过 Content-Disposition 返回。
/download/0.17q/windowsGET · RSS
RSS 2.0 发布源;每个版本对应一个 item,并链接到本地化更新日志。
/zh/feed.xml展开后可查看字段摘要、精简响应示例,以及带标准 User-Agent 的 curl 和服务端 fetch 示例。
/api/v1/diy/runtime-config.json| 字段 | 类型 | 说明 |
|---|---|---|
| mode | string | disabled、local 或 production。 |
| turnstileSiteKey | string | null | 公开 Turnstile site key。 |
| turnstileRequired | boolean | 当前请求是否必须提供 Turnstile token。 |
{
"schemaVersion": 1,
"kind": "diyRuntimeConfig",
"mode": "production",
"turnstileSiteKey": "0x4AAAAAADr9j5Z_Is8qzs20",
"turnstileRequired": true
} const response = await fetch("https://pvzvoyage.com/api/v1/diy/runtime-config.json");
if (!response.ok) {
throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const config = await response.json(); /api/v1/index.json| 字段 | 类型 | 说明 |
|---|---|---|
| apiVersion | string | 当前公开 API 主版本。 |
| latestRelease | object | 最新公开版本、发布时间和 release/update/changelog 链接。 |
| locales | object | 默认语言、支持语言,以及各语言页面和本地化 API。 |
| cache | object | API、下载和错误响应的缓存策略摘要。 |
| families | array | 接口族、schemaVersion、示例路径和文档锚点。 |
| documentation | object | 中英文 API 文档和 llms.txt 链接。 |
{
"schemaVersion": 1,
"kind": "apiIndex",
"apiVersion": "v1",
"latestRelease": {
"version": "0.17q",
"releasedAt": "2026-07-01",
"detail": {
"path": "/api/v1/releases/latest.json",
"url": "https://pvzvoyage.com/api/v1/releases/latest.json"
}
},
"locales": {
"default": "zh",
"supported": [
"zh",
"en"
]
},
"documentation": {
"en": {
"path": "/en/api-docs/",
"url": "https://pvzvoyage.com/en/api-docs/"
},
"zh": {
"path": "/zh/api-docs/",
"url": "https://pvzvoyage.com/zh/api-docs/"
},
"openapi": {
"path": "/api/openapi.json",
"url": "https://pvzvoyage.com/api/openapi.json"
}
},
"families": [
{
"key": "release",
"schemaVersions": [
1,
2
],
"endpoints": [
{
"id": "releases-latest",
"method": "GET",
"pathTemplate": "/api/v1/releases/latest.json",
"schemaVersion": 1
},
{
"id": "updates-latest",
"method": "GET",
"pathTemplate": "/api/v1/updates/latest.json",
"schemaVersion": 2
}
]
},
{
"key": "diy",
"schemaVersions": [
1
],
"endpoints": [
{
"id": "diy-levels-list",
"method": "GET · HEAD",
"pathTemplate": "/api/v1/diy/levels.json",
"schemaVersion": 1
},
{
"id": "diy-level-detail",
"method": "GET · HEAD",
"pathTemplate": "/api/v1/diy/levels/{public_id}.json",
"schemaVersion": 1
},
{
"id": "diy-level-icon",
"method": "GET · HEAD",
"pathTemplate": "/api/v1/diy/levels/{public_id}/icon",
"schemaVersion": 1
},
{
"id": "diy-runtime-config",
"method": "GET · HEAD",
"pathTemplate": "/api/v1/diy/runtime-config.json",
"schemaVersion": 1
},
{
"id": "diy-level-upload",
"method": "POST",
"pathTemplate": "/api/v1/diy/levels",
"schemaVersion": 1
},
{
"id": "diy-owner-session",
"method": "POST",
"pathTemplate": "/api/v1/diy/levels/{public_id}/owner/session",
"schemaVersion": 1
},
{
"id": "diy-owner-status",
"method": "POST",
"pathTemplate": "/api/v1/diy/levels/{public_id}/owner/status",
"schemaVersion": 1
},
{
"id": "diy-owner-edit",
"method": "POST",
"pathTemplate": "/api/v1/diy/levels/{public_id}/owner/edit",
"schemaVersion": 1
},
{
"id": "diy-owner-remove",
"method": "POST",
"pathTemplate": "/api/v1/diy/levels/{public_id}/owner/remove",
"schemaVersion": 1
},
{
"id": "diy-owner-update",
"method": "POST",
"pathTemplate": "/api/v1/diy/levels/{public_id}/owner/update",
"schemaVersion": 1
}
]
}
]
} curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
https://pvzvoyage.com/api/v1/index.json // Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/index.json", {
headers: {
"User-Agent": "PVZVoyage/0.17q (+https://pvzvoyage.com/)",
},
});
if (!response.ok) {
throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const apiIndex = await response.json(); /api/v1/releases/latest.json| 字段 | 类型 | 说明 |
|---|---|---|
| version | string | 当前版本号。 |
| platforms | string[] | 可用的平台 key 列表。 |
| builds | object | 按平台 key 索引的构建详情。 |
| builds.*.sha256 | string | 二进制文件的 SHA-256 校验值。 |
| feeds | object | 中英文 RSS 订阅链接。 |
| urls.canonical | Link | 固定版本详情 URL。 |
{
"schemaVersion": 1,
"kind": "release",
"version": "0.17q",
"releasedAt": "2026-07-01",
"latest": true,
"primaryPlatform": "windows",
"platforms": [
"windows",
"windows-zip",
"windows-x86",
"windows-x86-zip",
"android"
],
"urls": {
"self": {
"path": "/api/v1/releases/latest.json",
"url": "https://pvzvoyage.com/api/v1/releases/latest.json"
},
"canonical": {
"path": "/api/v1/releases/0.17q.json",
"url": "https://pvzvoyage.com/api/v1/releases/0.17q.json"
}
},
"builds": {
"windows": {
"platformKey": "windows",
"platform": {
"zh": "Windows 64 位(自解压)",
"en": "Windows x64 (self-extracting EXE)"
},
"path": "/download/0.17q/windows",
"url": "https://pvzvoyage.com/download/0.17q/windows",
"aliasPath": "/download/0.17q/windows.exe",
"filename": "PVZ-Voyage-0.17q-Windows-x64.exe",
"size": 151519712,
"sizeMiB": 144.5,
"sha256": "126f641200dba871499c929f20fe2bd92ddbc8f8b051a5f9809764d7a493af57",
"digest": {
"algorithm": "SHA-256",
"hex": "126f641200dba871499c929f20fe2bd92ddbc8f8b051a5f9809764d7a493af57"
},
"mime": "application/vnd.microsoft.portable-executable",
"extension": ".exe",
"minOs": {
"name": "Windows 7",
"build": 7600,
"label": "Windows 7+"
},
"note": "示例只展示 Windows 64 位构建;真实响应会包含所有平台。"
}
}
} curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
https://pvzvoyage.com/api/v1/releases/latest.json // Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/releases/latest.json", {
headers: {
"User-Agent": "PVZVoyage/0.17q (+https://pvzvoyage.com/)",
},
});
if (!response.ok) {
throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const release = await response.json(); /api/v1/updates/latest.json| 字段 | 类型 | 说明 |
|---|---|---|
| url | string | 主构建下载 URL,保留给 v1 客户端使用。 |
| sha256 | string | 主构建的校验值。 |
| builds | object | 所有平台的构建信息。 |
| minOs | object | 最低系统要求。 |
| changelog | object | 更新日志页面和 JSON changelog 链接。 |
{
"schemaVersion": 2,
"version": "0.17q",
"releasedAt": "2026-07-01",
"url": "https://pvzvoyage.com/download/0.17q/windows",
"sha256": "126f641200dba871499c929f20fe2bd92ddbc8f8b051a5f9809764d7a493af57",
"size": 151519712,
"filename": "PVZ-Voyage-0.17q-Windows-x64.exe",
"minOs": {
"name": "Windows 7",
"build": 7600
},
"builds": {
"windows": {
"url": "https://pvzvoyage.com/download/0.17q/windows",
"sha256": "126f641200dba871499c929f20fe2bd92ddbc8f8b051a5f9809764d7a493af57",
"size": 151519712,
"filename": "PVZ-Voyage-0.17q-Windows-x64.exe",
"minOs": {
"name": "Windows 7",
"build": 7600
}
}
}
} curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
https://pvzvoyage.com/api/v1/updates/latest.json // Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/updates/latest.json", {
headers: {
"User-Agent": "PVZVoyage/0.17q (+https://pvzvoyage.com/)",
},
});
if (!response.ok) {
throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const manifest = await response.json(); /api/v1/releases.json| 字段 | 类型 | 说明 |
|---|---|---|
| latest | string | 最新版本号。 |
| releases | array | 已公开版本列表。 |
| releases[].detail | string | 固定版本详情 API。 |
| releases[].latestDetail | string | null | 当前版本的 latest 详情别名。 |
{
"schemaVersion": 1,
"latest": "0.17q",
"releases": [
{
"version": "0.17q",
"releasedAt": "2026-07-01",
"url": "https://pvzvoyage.com/download/0.17q/windows",
"sha256": "126f641200dba871499c929f20fe2bd92ddbc8f8b051a5f9809764d7a493af57",
"detail": "https://pvzvoyage.com/api/v1/releases/0.17q.json",
"latestDetail": "https://pvzvoyage.com/api/v1/releases/latest.json"
}
]
} curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
https://pvzvoyage.com/api/v1/releases.json // Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/releases.json", {
headers: {
"User-Agent": "PVZVoyage/0.17q (+https://pvzvoyage.com/)",
},
});
if (!response.ok) {
throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const index = await response.json(); /api/v1/changelog/{version}.json| 字段 | 类型 | 说明 |
|---|---|---|
| version | string | 这份更新日志对应的版本。 |
| locales.zh | object | 中文更新日志。 |
| locales.en | object | 英文更新日志。 |
| sections | array | 标题、段落、小节和条目。 |
{
"schemaVersion": 1,
"version": "0.17q",
"releasedAt": "2026-07-01",
"locales": {
"zh": {
"title": "远征 0.17q 更新日志",
"sections": [
{
"title": "版本亮点",
"paragraphs": [
"..."
],
"sections": []
}
]
}
}
} curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
https://pvzvoyage.com/api/v1/changelog/0.17q.json // Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/changelog/0.17q.json", {
headers: {
"User-Agent": "PVZVoyage/0.17q (+https://pvzvoyage.com/)",
},
});
if (!response.ok) {
throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const changelog = await response.json(); /api/v1/encyclopedia/{locale}/index.json| 字段 | 类型 | 说明 |
|---|---|---|
| locale | 'zh' | 'en' | 当前语言。 |
| tabs | array | 植物、僵尸、Boss 分类与计数。 |
| entries | array | 条目摘要、页面 URL、API URL 和肖像。 |
| alternate | object | 另一语言的页面与 API。 |
{
"schemaVersion": 1,
"kind": "encyclopediaIndex",
"locale": "zh",
"title": "远征图鉴",
"counts": {
"total": 48,
"byKind": {
"plant": 22,
"zombie": 16,
"boss": 10
}
},
"entries": [
{
"slug": "peashooter",
"name": "豌豆射手",
"kind": "plant",
"path": "/zh/encyclopedia/peashooter/",
"api": {
"path": "/api/v1/encyclopedia/zh/peashooter.json",
"url": "https://pvzvoyage.com/api/v1/encyclopedia/zh/peashooter.json"
},
"portrait": {
"avif": {
"path": "/media/encyclopedia/peashooter.avif"
},
"width": 1200,
"height": 1185
}
}
]
} curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
https://pvzvoyage.com/api/v1/encyclopedia/zh/index.json // Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/encyclopedia/zh/index.json", {
headers: {
"User-Agent": "PVZVoyage/0.17q (+https://pvzvoyage.com/)",
},
});
if (!response.ok) {
throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const fieldGuide = await response.json(); /api/v1/encyclopedia/{locale}/{slug}.json| 字段 | 类型 | 说明 |
|---|---|---|
| entry | object | 条目正文、定位、能力与高级机制。 |
| portrait | object | AVIF/WebP/PNG 肖像与尺寸。 |
| navigation | object | 上一个/下一个条目摘要。 |
| alternate | object | null | 另一语言的条目。 |
{
"schemaVersion": 1,
"kind": "encyclopediaEntry",
"locale": "zh",
"slug": "peashooter",
"entry": {
"slug": "peashooter",
"kind": "plant",
"name": "豌豆射手",
"mechanics": {
"role": "远程攻击 · 杂交基础",
"abilities": [
"..."
]
},
"interactions": [
{
"target": "坚果墙",
"targetSlug": "wall-nut",
"effect": "..."
}
]
},
"portrait": {
"png": {
"path": "/media/encyclopedia/peashooter.png"
},
"width": 1200,
"height": 1185
}
} curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
https://pvzvoyage.com/api/v1/encyclopedia/zh/peashooter.json // Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/encyclopedia/zh/peashooter.json", {
headers: {
"User-Agent": "PVZVoyage/0.17q (+https://pvzvoyage.com/)",
},
});
if (!response.ok) {
throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const entry = await response.json(); /api/v1/world/{locale}/index.json| 字段 | 类型 | 说明 |
|---|---|---|
| regions | array | 区域 slug、编号、标题、简介、段落与视觉资源。 |
| visual | object | 卡片/首屏图片与主题色。 |
| alternate | object | 另一语言的世界索引。 |
{
"schemaVersion": 1,
"kind": "worldIndex",
"locale": "zh",
"count": 4,
"regions": [
{
"slug": "maple-falls",
"number": "I",
"title": "枫威瀑布",
"summary": "...",
"path": "/zh/world/maple-falls/",
"visual": {
"accent": "#8da66b",
"motif": "wind / lake / stairway"
}
}
]
} curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
https://pvzvoyage.com/api/v1/world/zh/index.json // Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/world/zh/index.json", {
headers: {
"User-Agent": "PVZVoyage/0.17q (+https://pvzvoyage.com/)",
},
});
if (!response.ok) {
throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const world = await response.json(); /api/v1/did-you-know/{locale}/index.json| 字段 | 类型 | 说明 |
|---|---|---|
| counts | object | 总数以及按 trivia、tip、mechanic、lore 分组的计数。 |
| filters | object | 可用 contexts、kinds、spoilerLevels 与 tags。 |
| selectionDefaults.homeHero | object | 首页默认选择规则。 |
| items | array | 本地化条目数组,含正文、来源、标签、权重和关联图鉴。 |
| items[].sourceRefs | array | 发布前校验过的本地来源。 |
{
"schemaVersion": 1,
"kind": "didYouKnowIndex",
"locale": "zh",
"counts": {
"total": 36,
"byKind": {
"trivia": 2,
"tip": 22,
"mechanic": 11,
"lore": 1
}
},
"selectionDefaults": {
"homeHero": {
"allowedSpoilerLevels": [
"none",
"mild",
"mechanics"
],
"preferredRelatedSlugs": [
"sunflower",
"peashooter"
],
"maxRecentIds": 12
}
},
"items": [
{
"id": "sunflower-match-inheritance",
"kind": "mechanic",
"text": "向日葵连线不再区分方向;搭配阳光椰瓶时,还能继承大阳光充能。",
"spoilerLevel": "mechanics",
"contexts": [
"homeHero",
"encyclopedia",
"api"
],
"relatedEntries": [
{
"slug": "sunflower",
"name": "向日葵",
"path": "/zh/encyclopedia/sunflower/"
}
]
}
]
} curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
https://pvzvoyage.com/api/v1/did-you-know/zh/index.json // Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/did-you-know/zh/index.json", {
headers: {
"User-Agent": "PVZVoyage/0.17q (+https://pvzvoyage.com/)",
},
});
if (!response.ok) {
throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const didYouKnow = await response.json(); /api/v1/did-you-know/{locale}/random.json| 字段 | 类型 | 说明 |
|---|---|---|
| context | query | homeHero、encyclopedia、api 或 any。 |
| kind | query | 逗号分隔的 trivia、tip、mechanic、lore。 |
| entry | query | 关联图鉴 slug;默认作为偏好,strictEntry=1 时变为必需。 |
| strictEntry | query | 0 或 1;设为 1 时必须提供 entry,并且只从关联该条目的内容中选择。 |
| tags | query | 逗号分隔的 URL-safe 标签,最多 12 个;匹配任意一个标签。 |
| spoilerMax | query | 允许的最高剧透等级;homeHero 默认 mechanics,其他场景默认 lateGame。 |
| exclude | query | 逗号分隔的条目 ID,最多 20 个。 |
| seed | query | 最长 128 个字符;不提供时使用当前 UTC 小时桶。 |
| X-PVZV-DidYouKnow-Cache | response header | HIT 或 MISS,用于验证随机选择缓存是否命中。 |
| selection | object | 实际使用的 seed、池大小、排除数量与过滤器。 |
| item | object | 被选中的 DidYouKnow 条目。 |
{
"schemaVersion": 1,
"kind": "didYouKnowSelection",
"locale": "zh",
"selection": {
"strategy": "weighted-stable-random",
"seed": "session-42",
"context": "homeHero",
"poolSize": 31,
"excludedCount": 0,
"filters": {
"entry": "sunflower",
"strictEntry": false,
"spoilerMax": "mechanics"
}
},
"item": {
"id": "sunflower-match-inheritance",
"kind": "mechanic",
"text": "向日葵连线不再区分方向;搭配阳光椰瓶时,还能继承大阳光充能。",
"cta": {
"path": "/zh/encyclopedia/sunflower/",
"url": "https://pvzvoyage.com/zh/encyclopedia/sunflower/"
}
}
} curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
"https://pvzvoyage.com/api/v1/did-you-know/zh/random.json?context=homeHero&entry=sunflower&seed=session-42" // Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/did-you-know/zh/random.json?context=homeHero&entry=sunflower&seed=session-42", {
headers: {
"User-Agent": "PVZVoyage/0.17q (+https://pvzvoyage.com/)",
},
});
if (!response.ok) {
throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const selection = await response.json(); /api/v1/diy/levels.json| 字段 | 类型 | 说明 |
|---|---|---|
| q · 可选 | query | 搜索公开标题、作者或简介;最长 60 个字符。 |
| ids · 可选 | query | 逗号分隔的公开关卡 ID,最多 50 个;适合本地收藏回查。 |
| version · 可选 | query | 精确匹配游戏版本,例如 0.17q。 |
| difficulty · 可选 | query | 外显/设计难度整数 0..9;这是独立显示刻度,不对应游戏内环境难度。 |
| difficultyMin / difficultyMax · 可选 | query | 外显/设计难度范围,整数 0..9。 |
| background · 可选 | query | 背景 ID。 |
| wavesMin / wavesMax · 可选 | query | 最大波数范围,1..100。 |
| subLevelsMin / subLevelsMax · 可选 | query | 子关卡数量范围,1..8。 |
| downloadsMin / downloadsMax · 可选 | query | 近似下载量范围,使用非负整数。 |
| tag · 可选 | query | 可重复,也可用逗号分隔;多个标签按同时匹配处理。 |
| sort · 可选 | query | latest、hot、name、downloads 或 difficulty;默认 latest。 |
| cursor · 可选 | query | 上一页返回的不透明分页游标。 |
| limit · 可选 | query | 1..50,默认 20。 |
| mode | string | 接口启用状态的公开标识。 |
| levels | array | 公开关卡摘要数组。 |
| levels[].titleZh | string | 中文公开标题。 |
| levels[].titleEn | string | 英文公开标题。 |
| levels[].descriptionZh | string | 中文公开简介。 |
| levels[].descriptionEn | string | 英文公开简介。 |
| levels[].icon | object | null | 可公开展示的关卡图标链接和图片元数据;未上传时为空。 |
| levels[].download | Link | GDF 下载入口。 |
| pagination.nextCursor | string | null | 下一页游标;为空表示没有下一页。 |
| pagination.total | number | null | 当前筛选条件下的总数,无法计算时为空。 |
{
"schemaVersion": 1,
"kind": "diyLevelList",
"mode": "production",
"levels": [
{
"schemaVersion": 1,
"id": "sample-level-id",
"title": "Sample Conveyor Trial",
"description": "Short public description shown in the library.",
"titleZh": "传送带试炼",
"titleEn": "Sample Conveyor Trial",
"descriptionZh": "在关卡库中展示的中文简介。",
"descriptionEn": "Short public description shown in the library.",
"author": "Example Creator",
"gameVersion": "0.17q",
"difficulty": 3,
"way": 0,
"waves": 10,
"background": 1,
"subLevelCount": 1,
"modeTags": [
"conveyor"
],
"sizeBytes": 20480,
"sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"icon": {
"path": "/api/v1/diy/levels/sample-level-id/icon",
"url": "https://pvzvoyage.com/api/v1/diy/levels/sample-level-id/icon",
"contentType": "image/png",
"width": 96,
"height": 96,
"sizeBytes": 8192,
"sha256": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
},
"downloadCountApprox": 42,
"approvedAt": "2026-06-27T01:00:00.000Z",
"detail": {
"path": "/api/v1/diy/levels/sample-level-id.json",
"url": "https://pvzvoyage.com/api/v1/diy/levels/sample-level-id.json"
},
"download": {
"path": "/api/v1/diy/levels/sample-level-id/download.gdf",
"url": "https://pvzvoyage.com/api/v1/diy/levels/sample-level-id/download.gdf"
}
}
],
"pagination": {
"nextCursor": "opaque-cursor",
"total": 128
}
} curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
"https://pvzvoyage.com/api/v1/diy/levels.json?sort=hot&tag=conveyor&limit=20" // Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/diy/levels.json?sort=hot&tag=conveyor&limit=20", {
headers: {
"User-Agent": "PVZVoyage/0.17q (+https://pvzvoyage.com/)",
},
});
if (!response.ok) {
throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const levels = await response.json(); /api/v1/diy/levels/{public_id}.json| 字段 | 类型 | 说明 |
|---|---|---|
| public_id | path | 公开关卡 ID。 |
| level.id | string | 公开关卡 ID。 |
| level.title | string | 兼容旧客户端的公开标题投影;本地化客户端应使用 titleZh/titleEn。 |
| level.description | string | 兼容旧客户端的公开简介投影;本地化客户端应使用 descriptionZh/descriptionEn。 |
| level.titleZh | string | 中文公开标题。 |
| level.titleEn | string | 英文公开标题。 |
| level.descriptionZh | string | 中文公开简介。 |
| level.descriptionEn | string | 英文公开简介。 |
| level.author | string | 从 GDF 中读取的作者。 |
| level.gameVersion | string | null | GDF 声明的游戏版本。 |
| level.difficulty | number | null | 关卡外显/设计难度值;默认取自 GDF 解析,也可在上传或管理时手动标注。 |
| level.environmentDifficulty | number | null | 游戏内环境难度值,通常为 0..4,也识别 5..7。 |
| level.waves | number | null | 最大波数。 |
| level.background | number | null | 首个子关卡背景 ID。 |
| level.subLevelCount | number | 子关卡数量。 |
| level.modeTags | string[] | 公开模式标签。 |
| level.sizeBytes | number | GDF 文件大小。 |
| level.sha256 | string | GDF 文件 SHA-256。 |
| level.icon | object | null | 关卡图标链接和 PNG/JPEG/WebP 图片元数据;未上传时为空。 |
| level.downloadCountApprox | number | 近似下载量,用于展示趋势。 |
| level.gdfName · 可选 | string | null | GDF 内部名称。 |
| level.gdfDescription · 可选 | string | null | GDF 内部简介。 |
| level.seed · 可选 | number | null | GDF 随机种子。 |
| level.crcValid | boolean | GDF CRC 校验结果。 |
| level.subLevels · 可选 | array | null | 多子关卡摘要。 |
| level.subLevels[].difficulty · 可选 | number | null | 该子关卡的外显/设计难度。 |
| level.summaryJson | object | GDF 信息摘要对象:由 GDF 原始 JSON 提取并归一化得到,保留关卡名、作者、版本、难度、波数、背景、子关卡和出怪概要;不是可直接重新打包为 .gdf 的原始关卡 JSON。 |
{
"schemaVersion": 1,
"kind": "diyLevelDetail",
"mode": "production",
"level": {
"schemaVersion": 1,
"id": "sample-level-id",
"title": "Sample Conveyor Trial",
"description": "Short public description shown in the library.",
"titleZh": "传送带试炼",
"titleEn": "Sample Conveyor Trial",
"descriptionZh": "在关卡库中展示的中文简介。",
"descriptionEn": "Short public description shown in the library.",
"author": "Example Creator",
"gameVersion": "0.17q",
"difficulty": 3,
"environmentDifficulty": 2,
"way": 0,
"waves": 10,
"background": 1,
"subLevelCount": 2,
"modeTags": [
"conveyor"
],
"sizeBytes": 20480,
"sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"icon": {
"path": "/api/v1/diy/levels/sample-level-id/icon",
"url": "https://pvzvoyage.com/api/v1/diy/levels/sample-level-id/icon",
"contentType": "image/png",
"width": 96,
"height": 96,
"sizeBytes": 8192,
"sha256": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
},
"downloadCountApprox": 42,
"approvedAt": "2026-06-27T01:00:00.000Z",
"detail": {
"path": "/api/v1/diy/levels/sample-level-id.json",
"url": "https://pvzvoyage.com/api/v1/diy/levels/sample-level-id.json"
},
"download": {
"path": "/api/v1/diy/levels/sample-level-id/download.gdf",
"url": "https://pvzvoyage.com/api/v1/diy/levels/sample-level-id/download.gdf"
},
"gdfName": "Sample Conveyor Trial",
"gdfDescription": "GDF-authored description if present.",
"seed": 123,
"crcValid": true,
"subLevels": [
{
"index": 0,
"difficulty": 2,
"waves": 8,
"background": 1,
"zombieSummary": [
"Zombie",
"ConeheadZombie"
]
},
{
"index": 1,
"difficulty": 3,
"waves": 10,
"background": 3,
"zombieSummary": [
"BucketheadZombie",
"FlagZombie"
]
}
],
"summaryJson": {
"gdf_name": "Sample Conveyor Trial",
"extracted_author": "Example Creator",
"gdf_description": "GDF-authored description if present.",
"game_version": "0.17q",
"difficulty": 3,
"environment_difficulty": 2,
"way": 0,
"waves": 10,
"waves_range": "8-10",
"background": 1,
"sub_level_count": 2,
"sub_levels": [
{
"index": 0,
"waves": 8,
"background": 1,
"difficulty": 2,
"zombie_summary": [
"Zombie",
"ConeheadZombie"
]
},
{
"index": 1,
"waves": 10,
"background": 3,
"difficulty": 3,
"zombie_summary": [
"BucketheadZombie",
"FlagZombie"
]
}
]
}
}
} curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
https://pvzvoyage.com/api/v1/diy/levels/sample-level-id.json // Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/diy/levels/sample-level-id.json", {
headers: {
"User-Agent": "PVZVoyage/0.17q (+https://pvzvoyage.com/)",
},
});
if (!response.ok) {
throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const level = await response.json(); /api/v1/diy/levels/{public_id}/download.gdf| 字段 | 类型 | 说明 |
|---|---|---|
| public_id | path | 公开关卡 ID。 |
| Content-Type | header | application/octet-stream。 |
| Content-Disposition | header | 附件文件名,通常来自公开标题。 |
| Content-Length | header | GDF 文件大小。 |
| ETag | header | 与详情中的 sha256 对应的文件标识。 |
| Cache-Control | header | 版本化公开文件缓存策略。 |
HTTP/2 200
content-type: application/octet-stream
content-disposition: attachment; filename="Sample Conveyor Trial.gdf"
content-length: 20480
etag: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
cache-control: public, max-age=300, stale-while-revalidate=300 curl -I \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
https://pvzvoyage.com/api/v1/diy/levels/sample-level-id/download.gdf curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
-o "Sample Conveyor Trial.gdf" \
https://pvzvoyage.com/api/v1/diy/levels/sample-level-id/download.gdf /api/v1/diy/levels/{public_id}/icon| 字段 | 类型 | 说明 |
|---|---|---|
| public_id | path | 公开关卡 ID。 |
| Content-Type | header | image/png、image/jpeg 或 image/webp。 |
| Content-Disposition | header | inline。 |
| Content-Length | header | 图标文件大小。 |
| ETag | header | 图标 SHA-256 文件标识。 |
| X-PVZV-DIY-Icon-Width | header | 图标宽度,单位像素。 |
| X-PVZV-DIY-Icon-Height | header | 图标高度,单位像素。 |
| Cache-Control | header | 公开图标缓存策略。 |
HTTP/2 200
content-type: image/png
content-disposition: inline
content-length: 8192
etag: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
x-pvzv-diy-icon-width: 96
x-pvzv-diy-icon-height: 96
cache-control: public, max-age=300 curl -I \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
https://pvzvoyage.com/api/v1/diy/levels/sample-level-id/icon curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
-o "sample-level-icon.png" \
https://pvzvoyage.com/api/v1/diy/levels/sample-level-id/icon /api/v1/diy/levels| 字段 | 类型 | 说明 |
|---|---|---|
| file | multipart field | 必填 .gdf 文件,最大 256 KiB。 |
| icon · 可选 | multipart field | 可选关卡图标。只接受 PNG、JPEG 或 WebP,最大 96 KiB,宽高 32..512 像素;完整 multipart 请求必须小于 480 KiB。 |
| titleZh · 可选 | multipart field | 中文公开标题,填写时为 2..80 个字符。 |
| titleEn · 可选 | multipart field | 英文公开标题,填写时为 2..80 个字符。 |
| descriptionZh · 可选 | multipart field | 中文公开简介,最多 1500 个字符。 |
| descriptionEn · 可选 | multipart field | 英文公开简介,最多 1500 个字符。 |
| modeTags · 可选 | multipart field | 逗号分隔或重复字段,最多 5 个受控标签。 |
| turnstileToken · 可选 | multipart field | 浏览器上传控件在需要时提供的验证 token。 |
| status | string | 成功提交后为 pending。 |
| level | object | 新关卡的 ID、标题、作者、sha256 与提交时间。 |
| ownerCredential | object | 所有者凭证文件名、文本和 secret;只返回一次,请妥善保存。 |
{
"schemaVersion": 1,
"status": "pending",
"level": {
"id": "sample-level-id",
"title": "Sample Conveyor Trial",
"author": "Example Creator",
"sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"createdAt": "2026-06-27T01:00:00.000Z"
},
"ownerCredential": {
"filename": "pvzvoyage-diy-sample-level-id-owner.txt",
"text": "PVZ: Voyage DIY owner credential\nLevel ID: sample-level-id\nSecret: example_owner_secret",
"secret": "example_owner_secret"
}
} curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
-F "file=@level.gdf;type=application/octet-stream" \
-F "icon=@icon.png;type=image/png" \
-F "titleZh=传送带试炼" \
-F "titleEn=Sample Conveyor Trial" \
-F "descriptionZh=中文公开简介。" \
-F "descriptionEn=Short public description." \
-F "modeTags=conveyor,puzzle" \
https://pvzvoyage.com/api/v1/diy/levels const formData = new FormData();
formData.set("file", file, file.name);
if (iconFile) formData.set("icon", iconFile, iconFile.name);
formData.set("titleZh", "传送带试炼");
formData.set("titleEn", "Sample Conveyor Trial");
formData.set("descriptionZh", "中文公开简介。");
formData.set("descriptionEn", "Short public description.");
formData.set("modeTags", "conveyor,puzzle");
if (turnstileToken) formData.set("turnstileToken", turnstileToken);
const response = await fetch("https://pvzvoyage.com/api/v1/diy/levels", {
method: "POST",
body: formData,
});
const result = await response.json();
if (!response.ok) {
throw new Error(result?.error?.message ?? "DIY upload failed");
} /api/v1/diy/levels/{public_id}/owner/session| 字段 | 类型 | 说明 |
|---|---|---|
| secret | string | 上传时只返回一次的 owner secret。 |
{
"schemaVersion": 1,
"ok": true,
"expiresAt": "2026-06-27T02:00:00.000Z"
} const response = await fetch("https://pvzvoyage.com/api/v1/diy/levels/sample-level-id/owner/session", {
method: "POST",
headers: { "Content-Type": "application/json", "X-PVZV-CSRF": "1" },
body: JSON.stringify({ secret: "<owner-secret>" }),
});
const result = await response.json(); /api/v1/diy/levels/{public_id}/owner/status| 字段 | 类型 | 说明 |
|---|---|---|
| Authorization · 可选 | header | Bearer owner secret;也可使用网站 owner session。 |
| X-PVZV-CSRF · 可选 | header | 仅 Cookie 浏览器流程需要;Bearer 客户端不需要。 |
| body · 可选 | application/json | 编辑字段或空对象。 |
{
"schemaVersion": 1,
"level": {
"id": "sample-level-id",
"status": "pending"
}
} const response = await fetch("https://pvzvoyage.com/api/v1/diy/levels/sample-level-id/owner/status", {
method: "POST",
headers: { Authorization: "Bearer <owner-secret>", "Content-Type": "application/json" },
body: JSON.stringify({}),
});
const result = await response.json(); /api/v1/diy/levels/{public_id}/owner/edit| 字段 | 类型 | 说明 |
|---|---|---|
| Authorization · 可选 | header | Bearer owner secret;也可使用网站 owner session。 |
| X-PVZV-CSRF · 可选 | header | 仅 Cookie 浏览器流程需要;Bearer 客户端不需要。 |
| body | application/json | 编辑字段或空对象。 |
{
"schemaVersion": 1,
"ok": true,
"status": "updated"
} const response = await fetch("https://pvzvoyage.com/api/v1/diy/levels/sample-level-id/owner/edit", {
method: "POST",
headers: { Authorization: "Bearer <owner-secret>", "Content-Type": "application/json" },
body: JSON.stringify({}),
});
const result = await response.json(); /api/v1/diy/levels/{public_id}/owner/remove| 字段 | 类型 | 说明 |
|---|---|---|
| Authorization · 可选 | header | Bearer owner secret;也可使用网站 owner session。 |
| X-PVZV-CSRF · 可选 | header | 仅 Cookie 浏览器流程需要;Bearer 客户端不需要。 |
| body · 可选 | application/json | 编辑字段或空对象。 |
{
"schemaVersion": 1,
"ok": true,
"status": "removed"
} const response = await fetch("https://pvzvoyage.com/api/v1/diy/levels/sample-level-id/owner/remove", {
method: "POST",
headers: { Authorization: "Bearer <owner-secret>", "Content-Type": "application/json" },
body: JSON.stringify({}),
});
const result = await response.json(); /api/v1/diy/levels/{public_id}/owner/update| 字段 | 类型 | 说明 |
|---|---|---|
| Authorization · 可选 | header | Bearer owner secret;也可使用网站 owner session。 |
| X-PVZV-CSRF · 可选 | header | 仅 Cookie 浏览器流程需要;Bearer 客户端不需要。 |
| body | multipart/form-data | 完整 .gdf 与可选元数据。 |
{
"schemaVersion": 1,
"ok": true,
"status": "pending_update"
} const response = await fetch("https://pvzvoyage.com/api/v1/diy/levels/sample-level-id/owner/update", {
method: "POST",
headers: { Authorization: "Bearer <owner-secret>", "Content-Type": "application/json" },
body: JSON.stringify({}),
});
const result = await response.json(); /api/v1/search/{locale}.json| 字段 | 类型 | 说明 |
|---|---|---|
| documentCount | number | 文档数量。 |
| source | object | 站内搜索源文件说明。 |
| documents | array | 标准化文档数组。 |
| documents[].kind | string | nav、changelog、world、encyclopedia、mechanics、channel、faq 等。 |
{
"schemaVersion": 1,
"kind": "searchIndex",
"locale": "zh",
"documentCount": 100,
"documents": [
{
"id": "encyclopedia:zh:peashooter",
"kind": "encyclopedia",
"title": "豌豆射手",
"subtitle": "植物档案 · 初始拥有",
"path": "/zh/encyclopedia/peashooter/",
"url": "https://pvzvoyage.com/zh/encyclopedia/peashooter/",
"aliases": [
"peashooter",
"豌豆射手",
"plant"
]
}
]
} curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
https://pvzvoyage.com/api/v1/search/zh.json // Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/search/zh.json", {
headers: {
"User-Agent": "PVZVoyage/0.17q (+https://pvzvoyage.com/)",
},
});
if (!response.ok) {
throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const searchIndex = await response.json(); /api/v1/news/{locale}.json| 字段 | 类型 | 说明 |
|---|---|---|
| latestVersion | string | 最新版本。 |
| links | object | 首页、下载、更新日志、RSS 与 release API。 |
| items | array | 公告条目。 |
| items[].highlights | array | 结构化亮点。 |
{
"schemaVersion": 1,
"kind": "newsFeed",
"locale": "zh",
"latestVersion": "0.17q",
"items": [
{
"id": "release-0.17q",
"kind": "release",
"version": "0.17q",
"title": "PVZ: Voyage 0.17q 已发布",
"publishedAt": "2026-07-01",
"api": {
"path": "/api/v1/releases/0.17q.json",
"url": "https://pvzvoyage.com/api/v1/releases/0.17q.json"
}
}
]
} curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
https://pvzvoyage.com/api/v1/news/zh.json // Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/news/zh.json", {
headers: {
"User-Agent": "PVZVoyage/0.17q (+https://pvzvoyage.com/)",
},
});
if (!response.ok) {
throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const news = await response.json(); /download/{version}/{platform}| 字段 | 类型 | 说明 |
|---|---|---|
| Content-Type | header | 构建的 MIME 类型,例如 application/zip 或 Android APK 的 MIME 类型。 |
| Content-Disposition | header | 附件文件名。 |
| Content-Length | header | 完整文件或单段 Range 响应的字节数。 |
| Accept-Ranges | header | 表示支持 bytes 范围请求。 |
| Range | request header | 请求单个字节范围。 |
| Retry-After | header | 响应为 429 时返回。 |
HTTP/2 200
content-type: application/vnd.microsoft.portable-executable
content-length: 151519712
content-disposition: attachment; filename="PVZ-Voyage-0.17q-Windows-x64.exe"
accept-ranges: bytes
cache-control: public, max-age=3600, s-maxage=86400, immutable curl -I \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
https://pvzvoyage.com/download/0.17q/windows curl -L \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
-H "Range: bytes=0-1048575" \
-o pvzvoyage.part \
https://pvzvoyage.com/download/0.17q/windows // Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const head = await fetch("https://pvzvoyage.com/download/0.17q/windows", {
method: "HEAD",
headers: {
"User-Agent": "PVZVoyage/0.17q (+https://pvzvoyage.com/)",
},
});
const size = Number(head.headers.get("content-length") ?? 0);
const filename = head.headers.get("content-disposition"); /zh/feed.xml| 字段 | 类型 | 说明 |
|---|---|---|
| channel | RSS | 站点发布源。 |
| item | RSS | 版本条目。 |
| link | RSS | 本地化更新日志链接。 |
| pubDate | RSS | 发布日期。 |
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>PVZ: Voyage</title>
<item>
<title>PVZ: Voyage 0.17q 已发布</title>
<link>https://pvzvoyage.com/zh/version/0.17q/</link>
</item>
</channel>
</rss> curl -fsSL \
-A "PVZVoyage/0.17q (+https://pvzvoyage.com/)" \
https://pvzvoyage.com/zh/feed.xml // Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/zh/feed.xml", {
headers: {
"User-Agent": "PVZVoyage/0.17q (+https://pvzvoyage.com/)",
},
});
const xml = await response.text(); 不要在客户端中硬编码二进制文件的下载路径。客户端应先获取最新版本详情,再根据目标平台从 builds 中选择对应构建。下载路由支持 HEAD 预检、GET 下载和单段 Range 断点续传;非法范围会返回 416,限流会返回 429 和 Retry-After。下载完成后,使用 SHA-256 校验本地文件是否与本站发布的构建一致;该校验不代表运行环境、杀毒判断或游戏行为一定正常。
两者都来自同一套静态构建流程,但适用对象不同。
使用 News JSON
News JSON 包含结构化字段、CTA、图片、tag 和 release API 链接,更适合程序读取。
使用 RSS
RSS 2.0 更适合阅读器和通用订阅服务。
命令行工具、脚本、官方游戏客户端和服务端客户端应发送能够标识集成来源的 User-Agent,例如:PVZVoyage/0.17q (+https://pvzvoyage.com/)。如果您维护自己的客户端,可以替换 product/version 和支持 URL。公开读取 API 支持这种格式,并继续受速率限制和反滥用规则约束;浏览器 fetch 会自动携带浏览器 UA;使用默认工具 UA 的请求可能收到普通 404,而不是 JSON 格式错误。
JSON API 响应允许跨源读取:Access-Control-Allow-Origin: *。该设置只表示浏览器可以读取响应,不表示第三方页面获得本站背书。
API JSON 使用 Cache-Control 表达较短的浏览器缓存,并用 CDN-Cache-Control 表达较长的共享缓存意图;固定版本 release/changelog JSON 比 latest/update JSON 更适合长时间缓存。DidYouKnow random 会按规范化后的有效查询进入共享缓存。DIY 公共 GDF/icon 的 GET 响应使用短 TTL 缓存,HEAD 请求不用于填充边缘缓存;下载文件使用带版本路径的 immutable 缓存。客户端应尊重这些响应头,避免用高频轮询代替缓存。收到 429 时,请读取 Retry-After 后再重试。
未知 .json 路径通常返回 JSON 404,参数错误可能返回 JSON 400。下载路由的非法 Range 返回 416;请求过于频繁时返回 429。少数不符合公开接口调用约定的请求可能收到普通 404,这类响应不保证采用 JSON 错误格式。
builds.*.sha256 用于确认下载完成后的本地文件与本站发布的构建产物一致。它不能证明文件会在所有系统上运行,也不能替代系统权限、杀毒软件和用户自己的来源判断。
/api/v1 是破坏性变化的兼容边界。v1 内的 schemaVersion 只表示向后兼容的 payload 演进;新增字段可以提升 schemaVersion,但客户端必须忽略未知字段。任何不兼容变化都进入 /api/v2。