BASIC

Release API

Publish a new version of a Download with one HTTP request, without opening WP Admin. Use it from CI, from a deploy script, or after you upload a zip over FTP.

POST https://your-site.com/wp-json/hoster/v1/downloads/<slug>/release

<slug> is the Download's slug. An old slug of a renamed Download works too.

Authentication

The API uses WordPress Application Passwords.

  1. Log in as a user who can edit the Download (an administrator or editor).
  2. Go to Users → Profile → Application Passwords, enter a name such as "CI" and click Add New Application Password.
  3. Copy the password and keep it in your CI secrets or deploy script, never in the repository.

WordPress offers Application Passwords on sites served over HTTPS. Hoster's own licence must be active on the site, otherwise the API answers with HTTP 403.

Parameters

Send the request as multipart/form-data.

  • version (required) — The new version, for example 1.2.0. A leading v is removed. Letters, digits, dots, -, + and _, up to 64 characters.
  • package (optional) — The zip file upload.
  • download_url (optional) — An http(s) URL of the zip, instead of package.
  • changelog (optional) — HTML added at the top of the Download's Changelog tab.
  • publish (optional) — 1 publishes a draft Download. Default: the status stays as it is.

Send either package or download_url, not both. Send neither to keep the current package, for example when you replaced the file on the server yourself. A Download without any package yet needs one of the two.

Examples

The Updater tab on Downloads → Resources shows this command for the chosen Download:

curl -u "USER:APPLICATION_PASSWORD" \
  -F version=1.2.0 \
  -F package=@my-plugin.zip \
  "https://your-site.com/wp-json/hoster/v1/downloads/my-plugin/release"

With a changelog entry, publishing a draft:

curl -u "USER:APPLICATION_PASSWORD" \
  -F version=1.2.0 \
  -F package=@my-plugin.zip \
  --form-string 'changelog=<h4>1.2.0</h4><ul><li>New: export settings</li></ul>' \
  -F publish=1 \
  "https://your-site.com/wp-json/hoster/v1/downloads/my-plugin/release"
Tip
Pass text values such as changelog with --form-string. With -F, curl reads a value that starts with < or @ as a file name.

With a zip hosted somewhere else:

curl -u "USER:APPLICATION_PASSWORD" \
  -F version=1.2.0 \
  --form-string download_url=https://downloads.example.com/my-plugin-1.2.0.zip \
  "https://your-site.com/wp-json/hoster/v1/downloads/my-plugin/release"

Typical uses

Release from CI

Build the zip in your pipeline, then call the API with the version from your tag and the credentials from the CI's secret store:

curl -u "$HOSTER_USER:$HOSTER_APP_PASSWORD" \
  -F "version=$VERSION" \
  -F "package=@dist/my-plugin.zip" \
  "https://your-site.com/wp-json/hoster/v1/downloads/my-plugin/release"

Downloads linked to GitHub don't accept the API: they get their version from GitHub releases, see GitHub.

Release from a deploy script

Add the same curl call at the end of the script that builds your zip, so building and publishing are one step.

Release after an FTP upload

When the Download URL points to a zip in your site's uploads folder, replace that file over FTP (same path and name) and send only the version:

curl -u "USER:APPLICATION_PASSWORD" \
  -F version=1.2.0 \
  "https://your-site.com/wp-json/hoster/v1/downloads/my-plugin/release"

Hoster notices the changed file and copies it into private storage again. If you uploaded the zip to a new path in your uploads folder, send its URL as download_url instead.

What Hoster does

  1. Stores an uploaded zip straight in private storage, never in the Media Library. A download_url in this site's uploads is copied there as well.
  2. Saves the version and adds the changelog entry.
  3. Updates the Download, so client sites see the new version on their next update check. A Check for updates click on a client site asks right away.

The answer is JSON:

{
  "id": 123,
  "slug": "my-plugin",
  "status": "publish",
  "version": "1.2.0",
  "package": true,
  "last_updated": "2026-09-29 10:15:00"
}

When the uploaded zip's Version: header differs from the version you sent, the version you sent is saved and the answer adds a warning.

Errors

  • 400 — Missing or invalid version or download_url, both package and download_url sent, the file is not a zip, no package at all, or the Download is linked to GitHub.
  • 401 / 403 — Wrong credentials, a user who can't edit this Download, publish=1 from a user who can't publish Downloads, or Hoster's licence is not active.
  • 404 — No Download with this slug.

The zip must fit the server's upload limits (upload_max_filesize and post_max_size in PHP). A zip over upload_max_filesize is refused with HTTP 400 and PHP's upload error. A request over post_max_size loses all its fields, so the error says the version parameter is missing.