Multi-Software Multilingual Release Center API

APay provides a unified core releases module (releases table across SQLite, PostgreSQL, and MySQL) to manage software releases, changelogs, and installable packages across multiple products (shoply, qingpu-ai, hoxi-desktop, codex, goray, gopanel, or any custom appKey).

Key capabilities:

  • Multi-Software & Release Channels: Isolated by (app_key, channel, version) with support for stable, beta, rc, and nightly channels.
  • 7-Locale Structured Release Notes: Native support for zh, en, zh-TW, zh-HK, ru, ja, and ko with automatic language fallback (zh-HK -> zh-TW -> zh -> en, other -> en -> zh). Each locale contains title, summary, body, and structured items (feat, fix, perf, ui, ops, security, breaking).
  • Multi-Platform Assets: Each release can attach multiple installable packages (macos, windows, linux, chrome, container, android, ios) with arch, package, size, sha256, and CDN mirrors.
  • Bad-Release Withdrawal & Rollback: Marking a release with withdrawn_at immediately hides it from public feeds and instructs clients currently running the withdrawn version (isRollbackTarget: true) to roll back to the latest healthy release.

Public Endpoints

1. List Releases (GET /api/releases)

Returns the localized release timeline and latest release for a given software application and channel.

Query Parameters

ParameterTypeDefaultDescription
app / appKeystringdefaultSoftware identifier (e.g., shoply, qingpu-ai, hoxi-desktop, codex, or all)
channelstringstableRelease channel (stable, beta, rc, nightly, or all)
lang / localestringzhOutput language (en, zh, zh-TW, zh-HK, ru, ja, ko)
platform / osstring-Optional target OS filter (macos/darwin, windows/win32, linux, chrome, container)
archstring-Optional CPU architecture filter (arm64, x64, universal)
packagestring-Optional package type filter (desktop, extension, container, cli, installer)
limitnumber30Maximum number of releases returned (1–100)

Response (200)

{
  "code": 0,
  "msg": "ok",
  "appKey": "shoply",
  "channel": "stable",
  "lang": "en",
  "latest": {
    "id": 1,
    "appKey": "shoply",
    "channel": "stable",
    "version": "1.8.0",
    "versionCode": 1008000,
    "tag_name": "v1.8.0",
    "title": "Shoply 1.8.0 Stable",
    "summary": "One-click migration and multilingual SEO routing",
    "body": "- Added one-click migration\n- Fixed multi-currency rounding",
    "items": [
      { "type": "feat", "text": "Added one-click migration" },
      { "type": "fix", "text": "Fixed multi-currency rounding" }
    ],
    "assets": [
      {
        "name": "ghcr.io/shoply/shoply:1.8.0",
        "platform": "container",
        "arch": "universal",
        "package": "container",
        "browser_download_url": "https://downloads.shoply.example/shoply-1.8.0.tar.gz",
        "size": 104857600,
        "sha256": "..."
      }
    ],
    "mandatory": false,
    "releasedAt": "2026-10-20T00:00:00.000Z"
  },
  "releases": []
}

2. Check Client Upgrade (GET /api/releases/check)

Evaluates whether a client running currentVersion on a specific (platform, arch, package) needs an update or rollback. Automatically skips releases that have been withdrawn or do not provide an asset for the client's platform.

Query Parameters

ParameterTypeRequiredDescription
app / appKeystringNo (default)Target software identifier
channelstringNo (stable)Release channel
currentVersion / versionstringNoClient's currently installed SemVer (e.g., 1.2.0)
platform / osstringNoClient OS (darwin/macos, win32/windows, linux, chrome, container)
archstringNoClient CPU architecture (arm64, x64, universal)
packagestringNoPackage format (desktop, extension, container, cli)
langstringNo (zh)Language code for localized release notes
formatstringNoOptional output format: tauri (Tauri Updater JSON manifest, returns 204 when no update is available) or appcast / xml (Sparkle 2.x RSS feed)

Response (200)

{
  "code": 0,
  "msg": "ok",
  "data": {
    "appKey": "qingpu-ai",
    "channel": "stable",
    "lang": "en",
    "currentVersion": "1.2.0",
    "currentVersionCode": 1002000,
    "needUpdate": true,
    "hasUpdate": true,
    "isRollbackTarget": false,
    "mandatory": false,
    "latestVersion": "1.3.0",
    "latestVersionCode": 1003000,
    "downloadUrl": "https://cdn.qingpu.example/Qingpu-1.3.0-arm64.dmg",
    "sha256": "...",
    "size": 94371840,
    "appcastUrl": "/api/releases/appcast.xml?app=qingpu-ai&channel=stable&lang=en",
    "asset": {
      "name": "Qingpu-1.3.0-arm64.dmg",
      "platform": "macos",
      "arch": "arm64",
      "package": "desktop",
      "browser_download_url": "https://cdn.qingpu.example/Qingpu-1.3.0-arm64.dmg",
      "size": 94371840
    },
    "release": {
      "version": "1.3.0",
      "title": "Qingpu 1.3.0",
      "summary": "macOS performance optimization"
    }
  }
}

3. Sparkle 2.x / WinSparkle Appcast Feed (GET /api/releases/appcast.xml)

Generates a standard RSS 2.0 XML feed with xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" for native macOS (Sparkle 2) and Windows (WinSparkle / NetSparkle) auto-updaters. Also accessible at /api/releases/appcast.

  • Supports ?app=<appKey>&channel=stable&lang=zh&platform=macos&arch=arm64&limit=20.
  • Renders localized summary and items into clean HTML inside <description><![CDATA[...]]></description>.
  • Maps versionCode to <sparkle:version>, SemVer version to <sparkle:shortVersionString>, mandatory / minUpgradeVersion to <sparkle:criticalUpdate />, and asset signature / edSignature to sparkle:edSignature="...".
  • Automatically excludes withdrawn (withdrawn_at) or draft releases.

4. Tauri v1 / v2 Auto-Updater Manifest (GET /api/releases/check?format=tauri)

Returns the standard Tauri dynamic updater JSON manifest ({ version, notes, pub_date, platforms }) with automatic mapping of APay (platform, arch) assets onto darwin-aarch64, darwin-x86_64, windows-x86_64, linux-x86_64, etc. When version (currentVersion) is supplied and already up to date, returns HTTP 204 No Content.


CI / AI Agent & Admin Endpoints

1. Publish / Upsert Release via APAY_RELEASE_KEY (POST /api/releases & POST /api/releases/publish)

Protected by the APAY_RELEASE_KEY environment variable via Authorization: Bearer <APAY_RELEASE_KEY> or x-release-key: <APAY_RELEASE_KEY>.

  • Publish / Upsert Release: Pass appKey, appName, channel, version, locales, assets, mandatory, minUpgradeVersion, isActive, releasedAt, or dryRun: true. Every published or updated release is recorded in the operation audit log (operation_logs).
  • Administrative actions (save_app, delete_app, withdraw, restore, seed_bundled) are unified under /api/admin/releases (which also accepts Authorization: Bearer <APAY_RELEASE_KEY>).

2. Admin Console Endpoints (/api/admin/releases)

All /api/admin/releases/** endpoints accept either an administrator session / token (releases permission module) or Authorization: Bearer <APAY_RELEASE_KEY>.

  • GET /api/admin/releases: Lists releases with filtering by appKey, channel, status (all / published / withdrawn / draft), and keyword, plus per-software summary cards (data.apps).
  • POST /api/admin/releases:
    • Publishes or upserts a release record (appKey, channel, version, locales, assets, mandatory, minUpgradeVersion, isActive, releasedAt).
    • Supports { "action": "seed_bundled", "appKey": "all" } to import bundled JSON release histories into the database idempotently.
  • PUT /api/admin/releases/:id: Updates an existing release's metadata, multilingual locales, or multi-platform assets.
  • PATCH /api/admin/releases/:id/status: Toggles release state (status: 'published' | 'withdrawn' | 'draft' or { isActive, withdrawn }).
  • DELETE /api/admin/releases/:id: Permanently deletes a release record.