PUBLIC API

PVZ: Voyage API Docs

Public interface notes for launchers, bots, mirrors, and data tools. Start with latest release detail, then fetch Field Guide, world, search, news, or RSS data as needed.

These endpoints are static-first public data surfaces. They do not contain user state and do not require authentication. API JSON itself is kept out of search results; this page is the human-facing index.

Three-step quick start

Most clients only need latest release detail, one download URL, and one checksum verification.

  1. Step 1

    Read latest release

    Request release detail and choose the platform key that matches the device.

    /api/v1/releases/latest.json
  2. Step 2

    Download and verify

    Download from builds.*.url and verify the finished file with builds.*.sha256.

    /download/0.17p/windows
  3. Step 3

    Show update notes

    Launchers can read news JSON; community announcement bots can read changelog or RSS.

    /api/v1/news/en.json

Endpoint catalog

Filter by use case. Every card exposes a copyable concrete example URL.

Release

Release and updates

Current version, platform builds, checksums, and changelog data.

Content

Field Guide and world data

Encyclopedia entries, world regions, DidYouKnow trivia, and localized prose.

Search/news

Search and news

Stable search corpus, announcement feed, and bot-friendly updates.

Downloads

Download routes

R2-backed binary downloads with HEAD and Range support.

RSS

RSS feeds

RSS 2.0 release feeds for feed readers.

GET · Release

Latest release detail

Recommended release detail for launchers, mirrors, and bots. Includes every platform build.

/api/v1/releases/latest.json

GET · Release

Auto-update manifest

Updater manifest with backward-compatible top-level Windows x64 fields and a full builds matrix.

/api/v1/updates/latest.json

GET · Release

Release index

Lists public releases with the current latest version and detail links.

/api/v1/releases.json

GET · Release

Structured changelog

Returns both localized changelogs in one payload for announcement bots and launcher news panes.

/api/v1/changelog/0.17p.json

GET · Content

Field Guide index

Localized Field Guide catalog with counts, entry links, portrait assets, and alternate locale links.

/api/v1/encyclopedia/en/index.json

GET · Content

World region index

Localized world codex. There is no separate region-detail JSON; full paragraphs are included in regions.

/api/v1/world/en/index.json

GET · Search/news

Stable search corpus

Public wrapper for site-search documents. Do not depend on the root search-index files.

/api/v1/search/en.json

GET · Search/news

News and announcements JSON

Localized news feed for launchers, bots, and aggregators.

/api/v1/news/en.json

GET · HEAD · Downloads

Binary downloads

Download Windows and Android builds. Supports HEAD and single byte ranges; filenames are returned through Content-Disposition.

/download/0.17p/windows

GET · RSS

RSS release feed

RSS 2.0 feed with one item per release, linking to the localized changelog.

/feed.xml

Endpoint details

Open a panel for field summaries, trimmed responses, and curl/server-side fetch examples with the standard User-Agent.

GET

Latest release detail

/api/v1/releases/latest.json
Best for
Launchers, mirrors, download bots
Cache
public, max-age=300, s-maxage=3600, must-revalidate
Schema
1
Field summary
FieldTypeDescription
version string Current release version.
platforms string[] Available platform keys.
builds object Build details keyed by platform.
builds.*.sha256 string SHA-256 digest for the binary.
feeds object English and Chinese RSS feed links.
urls.canonical Link Version-pinned detail URL.

Trimmed release detail

{
  "schemaVersion": 1,
  "kind": "release",
  "version": "0.17p",
  "releasedAt": "2026-05-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.17p.json",
      "url": "https://pvzvoyage.com/api/v1/releases/0.17p.json"
    }
  },
  "builds": {
    "windows": {
      "platformKey": "windows",
      "platform": {
        "zh": "Windows 64 位(自解压)",
        "en": "Windows x64 (self-extracting EXE)"
      },
      "path": "/download/0.17p/windows",
      "url": "https://pvzvoyage.com/download/0.17p/windows",
      "aliasPath": "/download/0.17p/windows.exe",
      "filename": "PVZ-Voyage-0.17p-Windows-x64.exe",
      "size": 147749281,
      "sizeMiB": 140.9,
      "sha256": "788532e0381dda16784f62d3bc2df6d6e7adaf7ad9674f76742efb21db5c4988",
      "digest": {
        "algorithm": "SHA-256",
        "hex": "788532e0381dda16784f62d3bc2df6d6e7adaf7ad9674f76742efb21db5c4988"
      },
      "mime": "application/vnd.microsoft.portable-executable",
      "extension": ".exe",
      "minOs": {
        "name": "Windows 7",
        "build": 7600,
        "label": "Windows 7+"
      },
      "note": "Example shows the Windows x64 build only; the real payload includes every platform."
    }
  }
}

curl

curl -fsSL \
  -A "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)" \
  https://pvzvoyage.com/api/v1/releases/latest.json

fetch

// 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-API-Client/1.0 (+https://pvzvoyage.com/)",
  },
});
if (!response.ok) {
  throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const release = await response.json();
  • Store urls.canonical when you need immutable release data.
  • Clients should choose a platform from builds instead of hardcoding download URLs.
GET

Auto-update manifest

/api/v1/updates/latest.json
Best for
Updaters and launchers
Cache
public, max-age=300, s-maxage=3600, must-revalidate
Schema
2
Field summary
FieldTypeDescription
url string Primary build download URL kept for v1 consumers.
sha256 string Primary build checksum.
builds object All platform builds.
minOs object Minimum OS requirement.
changelog object Human changelog pages and JSON changelog link.

Updater example

{
  "schemaVersion": 2,
  "version": "0.17p",
  "releasedAt": "2026-05-01",
  "url": "https://pvzvoyage.com/download/0.17p/windows",
  "sha256": "788532e0381dda16784f62d3bc2df6d6e7adaf7ad9674f76742efb21db5c4988",
  "size": 147749281,
  "filename": "PVZ-Voyage-0.17p-Windows-x64.exe",
  "minOs": {
    "name": "Windows 7",
    "build": 7600
  },
  "builds": {
    "windows": {
      "url": "https://pvzvoyage.com/download/0.17p/windows",
      "sha256": "788532e0381dda16784f62d3bc2df6d6e7adaf7ad9674f76742efb21db5c4988",
      "size": 147749281,
      "filename": "PVZ-Voyage-0.17p-Windows-x64.exe",
      "minOs": {
        "name": "Windows 7",
        "build": 7600
      }
    }
  }
}

curl

curl -fsSL \
  -A "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)" \
  https://pvzvoyage.com/api/v1/updates/latest.json

fetch

// 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-API-Client/1.0 (+https://pvzvoyage.com/)",
  },
});
if (!response.ok) {
  throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const manifest = await response.json();
  • If you control the client, prefer release detail; it is more complete than the updater manifest.
  • Top-level fields are a compatibility layer, not the only downloadable platform.
GET

Release index

/api/v1/releases.json
Best for
Release lists and historical navigation
Cache
public, max-age=300, s-maxage=3600, must-revalidate
Schema
1
Field summary
FieldTypeDescription
latest string Latest version.
releases array Published releases.
releases[].detail string Version-pinned detail API.
releases[].latestDetail string | null Latest detail alias for the current version.

Release index example

{
  "schemaVersion": 1,
  "latest": "0.17p",
  "releases": [
    {
      "version": "0.17p",
      "releasedAt": "2026-05-01",
      "url": "https://pvzvoyage.com/download/0.17p/windows",
      "sha256": "788532e0381dda16784f62d3bc2df6d6e7adaf7ad9674f76742efb21db5c4988",
      "detail": "https://pvzvoyage.com/api/v1/releases/0.17p.json",
      "latestDetail": "https://pvzvoyage.com/api/v1/releases/latest.json"
    }
  ]
}

curl

curl -fsSL \
  -A "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)" \
  https://pvzvoyage.com/api/v1/releases.json

fetch

// 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-API-Client/1.0 (+https://pvzvoyage.com/)",
  },
});
if (!response.ok) {
  throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const index = await response.json();
  • Use this when you only need a version list; follow detail for platform builds.
GET

Structured changelog

/api/v1/changelog/{version}.json
Best for
Announcement bots, update pages, community tools
Cache
public, max-age=300, s-maxage=3600, must-revalidate
Schema
1
Field summary
FieldTypeDescription
version string Version represented by the changelog.
locales.zh object Chinese changelog.
locales.en object English changelog.
sections array Headings, paragraphs, subsections, and items.

Changelog shape example

{
  "schemaVersion": 1,
  "version": "0.17p",
  "releasedAt": "2026-05-01",
  "locales": {
    "en": {
      "title": "PVZ: Voyage 0.17p Changelog",
      "sections": [
        {
          "title": "Highlights",
          "paragraphs": [
            "..."
          ],
          "sections": []
        }
      ]
    }
  }
}

curl

curl -fsSL \
  -A "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)" \
  https://pvzvoyage.com/api/v1/changelog/0.17p.json

fetch

// Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/changelog/0.17p.json", {
  headers: {
    "User-Agent": "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)",
  },
});
if (!response.ok) {
  throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const changelog = await response.json();
  • The site currently publishes structured JSON for the current version.
GET

Field Guide index

/api/v1/encyclopedia/{locale}/index.json
Best for
Field Guide browsers, wiki tools, search clients
Cache
public, max-age=300, s-maxage=3600, must-revalidate
Schema
1
Field summary
FieldTypeDescription
locale 'zh' | 'en' Current locale.
tabs array Plant, zombie, and boss categories with counts.
entries array Entry summaries, page URLs, API URLs, and portraits.
alternate object Other-locale page and API.

Field Guide index example

{
  "schemaVersion": 1,
  "kind": "encyclopediaIndex",
  "locale": "en",
  "title": "Field Guide",
  "counts": {
    "total": 48,
    "byKind": {
      "plant": 22,
      "zombie": 16,
      "boss": 10
    }
  },
  "entries": [
    {
      "slug": "peashooter",
      "name": "Peashooter",
      "kind": "plant",
      "path": "/en/encyclopedia/peashooter/",
      "api": {
        "path": "/api/v1/encyclopedia/en/peashooter.json",
        "url": "https://pvzvoyage.com/api/v1/encyclopedia/en/peashooter.json"
      },
      "portrait": {
        "avif": {
          "path": "/media/encyclopedia/peashooter.avif"
        },
        "width": 1200,
        "height": 1185
      }
    }
  ]
}

curl

curl -fsSL \
  -A "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)" \
  https://pvzvoyage.com/api/v1/encyclopedia/en/index.json

fetch

// Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/encyclopedia/en/index.json", {
  headers: {
    "User-Agent": "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)",
  },
});
if (!response.ok) {
  throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const fieldGuide = await response.json();
  • Slug lists come from content modules; do not hardcode them from documentation.
GET

Field Guide entry detail

/api/v1/encyclopedia/{locale}/{slug}.json
Best for
Databases, bots, Field Guide mirrors
Cache
public, max-age=300, s-maxage=3600, must-revalidate
Schema
1
Field summary
FieldTypeDescription
entry object Entry copy, role, abilities, and advanced mechanics.
portrait object AVIF/WebP/PNG portrait and dimensions.
navigation object Previous/next entry summaries.
alternate object | null Other-locale entry.

Entry detail example

{
  "schemaVersion": 1,
  "kind": "encyclopediaEntry",
  "locale": "en",
  "slug": "peashooter",
  "entry": {
    "slug": "peashooter",
    "kind": "plant",
    "name": "Peashooter",
    "mechanics": {
      "role": "Ranged attacker · Crossbreed base",
      "abilities": [
        "..."
      ]
    },
    "interactions": [
      {
        "target": "Wall-nut",
        "targetSlug": "wall-nut",
        "effect": "..."
      }
    ]
  },
  "portrait": {
    "png": {
      "path": "/media/encyclopedia/peashooter.png"
    },
    "width": 1200,
    "height": 1185
  }
}

curl

curl -fsSL \
  -A "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)" \
  https://pvzvoyage.com/api/v1/encyclopedia/en/peashooter.json

fetch

// Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/encyclopedia/en/peashooter.json", {
  headers: {
    "User-Agent": "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)",
  },
});
if (!response.ok) {
  throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const entry = await response.json();
  • Advanced mechanics appears only on entries that have that data.
GET

World region index

/api/v1/world/{locale}/index.json
Best for
Maps, databases, region browsers
Cache
public, max-age=300, s-maxage=3600, must-revalidate
Schema
1
Field summary
FieldTypeDescription
regions array Region slug, number, title, summary, paragraphs, and visuals.
visual object Card/hero images and accent colors.
alternate object Other-locale world index.

World index example

{
  "schemaVersion": 1,
  "kind": "worldIndex",
  "locale": "en",
  "count": 4,
  "regions": [
    {
      "slug": "maple-falls",
      "number": "I",
      "title": "Maple Falls",
      "summary": "...",
      "path": "/en/world/maple-falls/",
      "visual": {
        "accent": "#8da66b",
        "motif": "wind / lake / stairway"
      }
    }
  ]
}

curl

curl -fsSL \
  -A "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)" \
  https://pvzvoyage.com/api/v1/world/en/index.json

fetch

// Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/world/en/index.json", {
  headers: {
    "User-Agent": "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)",
  },
});
if (!response.ok) {
  throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const world = await response.json();
  • Region slugs are stable across locales; titles and prose are localized.
GET

DidYouKnow catalog

/api/v1/did-you-know/{locale}/index.json
Best for
Launchers, bots, data tools, local homepage selection
Cache
public, max-age=300, s-maxage=3600, must-revalidate
Schema
1
Field summary
FieldTypeDescription
counts object Total count and counts by trivia, tip, mechanic, and lore.
filters object Available contexts, kinds, spoiler levels, and tags.
selectionDefaults.homeHero object Default homepage selection rules.
items array Localized items with copy, source refs, tags, weight, and related Field Guide entries.
items[].sourceRefs array Local sources checked before publication.

DidYouKnow catalog example

{
  "schemaVersion": 1,
  "kind": "didYouKnowIndex",
  "locale": "en",
  "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": "Sunflower matching is no longer directional, and CocoBottle Shine can pass its large-sun charge into the kept plant.",
      "spoilerLevel": "mechanics",
      "contexts": [
        "homeHero",
        "encyclopedia",
        "api"
      ],
      "relatedEntries": [
        {
          "slug": "sunflower",
          "name": "Sunflower",
          "path": "/en/encyclopedia/sunflower/"
        }
      ]
    }
  ]
}

curl

curl -fsSL \
  -A "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)" \
  https://pvzvoyage.com/api/v1/did-you-know/en/index.json

fetch

// Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/did-you-know/en/index.json", {
  headers: {
    "User-Agent": "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)",
  },
});
if (!response.ok) {
  throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const didYouKnow = await response.json();
  • Items are maintained in repository content files and validated at build time for IDs, locales, slugs, length, tags, and spoiler levels.
  • Use random.json for a single result; read the full catalog when you want to cache or filter locally.
GET · HEAD

Random DidYouKnow selection

/api/v1/did-you-know/{locale}/random.json
Best for
Launcher welcome panes, bots, lightweight tools
Cache
Explicit seed uses public, max-age=300, s-maxage=3600; no seed uses a UTC hour bucket and public, max-age=60, s-maxage=300
Schema
1
Field summary
FieldTypeDescription
context query homeHero, encyclopedia, api, or any.
kind query Comma-separated trivia, tip, mechanic, or lore.
entry query Related Field Guide slug; preferred by default and required with strictEntry=1.
spoilerMax query Maximum spoiler level; defaults to mechanics for homeHero and lateGame otherwise.
exclude query Comma-separated item IDs; the first 20 are honored.
selection object Seed, pool size, excluded count, and filters actually used.
item object Selected DidYouKnow item.

Random selection example

{
  "schemaVersion": 1,
  "kind": "didYouKnowSelection",
  "locale": "en",
  "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": "Sunflower matching is no longer directional, and CocoBottle Shine can pass its large-sun charge into the kept plant.",
    "cta": {
      "path": "/en/encyclopedia/sunflower/",
      "url": "https://pvzvoyage.com/en/encyclopedia/sunflower/"
    }
  }
}

curl

curl -fsSL \
  -A "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)" \
  "https://pvzvoyage.com/api/v1/did-you-know/en/random.json?context=homeHero&entry=sunflower&seed=session-42"

fetch

// Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/did-you-know/en/random.json?context=homeHero&entry=sunflower&seed=session-42", {
  headers: {
    "User-Agent": "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)",
  },
});
if (!response.ok) {
  throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const selection = await response.json();
  • The same catalog, query, and seed produce a stable result; catalog changes may select a different item.
  • Bad parameters return JSON 400; no matching item returns JSON 404 with code no_matching_item.
GET

Stable search corpus

/api/v1/search/{locale}.json
Best for
Bots, external search, lightweight mirrors
Cache
public, max-age=300, s-maxage=3600, must-revalidate
Schema
1
Field summary
FieldTypeDescription
documentCount number Number of documents.
source object Source file note for the internal search index.
documents array Normalized documents.
documents[].kind string nav, changelog, world, encyclopedia, mechanics, channel, faq, and more.

Search document example

{
  "schemaVersion": 1,
  "kind": "searchIndex",
  "locale": "en",
  "documentCount": 100,
  "documents": [
    {
      "id": "encyclopedia:en:peashooter",
      "kind": "encyclopedia",
      "title": "Peashooter",
      "subtitle": "Plant file · Owned by default",
      "path": "/en/encyclopedia/peashooter/",
      "url": "https://pvzvoyage.com/en/encyclopedia/peashooter/",
      "aliases": [
        "peashooter",
        "Peashooter",
        "plant"
      ]
    }
  ]
}

curl

curl -fsSL \
  -A "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)" \
  https://pvzvoyage.com/api/v1/search/en.json

fetch

// Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/search/en.json", {
  headers: {
    "User-Agent": "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)",
  },
});
if (!response.ok) {
  throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const searchIndex = await response.json();
  • Root search-index-*.json files are for the site UI and are not the stable API.
GET

News and announcements JSON

/api/v1/news/{locale}.json
Best for
Launcher news panes, Discord/QQ bots, aggregators
Cache
public, max-age=300, s-maxage=3600, must-revalidate
Schema
1
Field summary
FieldTypeDescription
latestVersion string Latest version.
links object Home, download, changelog, RSS, and release API links.
items array Announcement items.
items[].highlights array Structured highlights.

News feed example

{
  "schemaVersion": 1,
  "kind": "newsFeed",
  "locale": "en",
  "latestVersion": "0.17p",
  "items": [
    {
      "id": "release-0.17p",
      "kind": "release",
      "version": "0.17p",
      "title": "PVZ: Voyage 0.17p released",
      "publishedAt": "2026-05-01",
      "api": {
        "path": "/api/v1/releases/0.17p.json",
        "url": "https://pvzvoyage.com/api/v1/releases/0.17p.json"
      }
    }
  ]
}

curl

curl -fsSL \
  -A "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)" \
  https://pvzvoyage.com/api/v1/news/en.json

fetch

// Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/api/v1/news/en.json", {
  headers: {
    "User-Agent": "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)",
  },
});
if (!response.ok) {
  throw new Error(`PVZ: Voyage API failed: ${response.status}`);
}
const news = await response.json();
  • Use RSS for feed readers; use this JSON for software clients.
GET · HEAD

Binary downloads

/download/{version}/{platform}
Best for
Launchers, mirrors, download pages
Cache
public, max-age=3600, s-maxage=86400, immutable
Schema
binary
Field summary
FieldTypeDescription
Content-Type header Build MIME type, such as application/zip or the APK MIME type.
Content-Disposition header Attachment filename.
Accept-Ranges header Supports bytes.
Range request header Request a single byte range.
Retry-After header Returned on 429 responses.

HEAD probe example

HTTP/2 200
content-type: application/vnd.microsoft.portable-executable
content-disposition: attachment; filename="PVZ-Voyage-0.17p-Windows-x64.exe"
accept-ranges: bytes
cache-control: public, max-age=3600, s-maxage=86400, immutable

HEAD

curl -I \
  -A "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)" \
  https://pvzvoyage.com/download/0.17p/windows

Range

curl -L \
  -A "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)" \
  -H "Range: bytes=0-1048575" \
  -o pvzvoyage.part \
  https://pvzvoyage.com/download/0.17p/windows

fetch

// Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const head = await fetch("https://pvzvoyage.com/download/0.17p/windows", {
  method: "HEAD",
  headers: {
    "User-Agent": "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)",
  },
});
const size = Number(head.headers.get("content-length") ?? 0);
const filename = head.headers.get("content-disposition");
  • Read release detail first, then use builds.*.url.
  • Verify the completed file with builds.*.sha256.
  • Only single byte ranges are supported; multi-ranges or invalid ranges return 416.
GET

RSS release feed

/feed.xml
Best for
RSS readers and subscription services
Cache
static asset cache through Worker headers
Schema
feed
Field summary
FieldTypeDescription
channel RSS Release channel.
item RSS Release item.
link RSS Localized changelog link.
pubDate RSS Release date.

RSS fragment

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>PVZ: Voyage</title>
    <item>
      <title>PVZ: Voyage 0.17p released</title>
      <link>https://pvzvoyage.com/en/version/0.17p/</link>
    </item>
  </channel>
</rss>

curl

curl -fsSL \
  -A "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)" \
  https://pvzvoyage.com/feed.xml

fetch

// Server-side fetch example. Browser fetch sends a browser User-Agent automatically.
const response = await fetch("https://pvzvoyage.com/feed.xml", {
  headers: {
    "User-Agent": "PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/)",
  },
});
const xml = await response.text();
  • RSS is for readers; software clients should prefer /api/v1/news/{locale}.json.

Download client guidance

Do not hardcode binary paths in clients. Read latest release detail first, then choose a platform from builds. Download routes support HEAD probes, GET downloads, and single-range resumes; verify the result with SHA-256.

JSON or RSS?

Both are generated by the same static build pipeline, but they serve different consumers.

Use News JSON

Structured fields, CTAs, images, tags, and release API links are better for software.

  • Launcher news panes
  • Bot announcements
  • External aggregators
/api/v1/news/en.json

Use RSS

RSS 2.0 is better for feed readers and generic subscription services.

  • RSS readers
  • Personal subscriptions
  • Low-maintenance notifications
/feed.xml

Headers, errors, and versioning

User-Agent

Command-line, script, and server-side clients should send a User-Agent that identifies the integration, for example: PVZVoyage-API-Client/1.0 (+https://pvzvoyage.com/). If you maintain your own client, you may replace the product/version and support URL. Browser fetch uses the browser UA automatically.

CORS

JSON API responses are readable cross-origin with Access-Control-Allow-Origin: *.

Caching

API JSON uses short browser cache and longer edge cache; binary downloads use immutable versioned-path caching.

404

Unknown .json API paths return a JSON error object instead of an HTML 404 page. Requests that do not follow the public interface conventions may receive a plain 404 before API handling, and that response is not guaranteed to use the JSON error shape.

Compatibility

/api/v1 is intended to remain stable; additive fields may appear without a schemaVersion bump, while breaking shape changes should use a new schemaVersion or a future /api/v2 path.