Update: Compatible with game versioning changes in 2026!
We’ve made it easy to automatically update your Minecraft server to the latest Paper, Velocity, Waterfall or even Travertine version.
If you’ve ever been frustrated with having to download each individual Paper build, you can now use MineAcademy Endpoint to get the latest jar.
We also provide endpoints for both Spigot and Mojang mappings to Paper.
In this tutorial, I’ll show you what the new endpoint is capable of, and how to configure your Minecraft server using cURL to automatically update Paper.
About Our Endpoint
Endpoint Structure
The structure for our endpoint is as follows:
https://mineacademy.org/api/{software}/{version}
Supported Software
At this time, we support the following software:
- Paper (use “paper” for Spigot, and “paper-mojmap” for Mojang mappings, see below)
- Purpur
- Velocity
- Folia (please note that these builds appear outdated on Paper)
- Travertine
- Waterfall
Please note that the versions are compiled by team Paper, and their availability can be checked at “https://api.papermc.io/v2/projects/X” (replace X with the project name such as folia).
Obtaining The Latest Version
The top-most endpoint call will automatically retrieve the latest Paper jar for any Minecraft version.
It is inherently unsafe to use this without strong precaution, as this will serve any given major Minecraft version such as 26.x and 1.21 as soon as they are available.
We only recommend downloading the latest major version for testing purposes.
https://mineacademy.org/api/paper/latest
If you wish to obtain a jar using Mojang mappings, use “paper-mojmap” instead:
https://mineacademy.org/api/paper-mojmap/latest
https://mineacademy.org/api/purpur/latest
https://mineacademy.org/api/folia/latest
https://mineacademy.org/api/velocity/latest
https://mineacademy.org/api/waterfall/latest
https://mineacademy.org/api/travertine/latest
Obtaining The Latest Build For A Given Version
Our endpoint is capable of retrieving the latest Paper build for a given Minecraft version, such as 1.21.11, 26.1 etc.
For all available versions, visit Paper’s build explorer here and see the panel to the left. Then, simply replace the “.” with “_” with the version you would like to obtain the latest build of.
Examples:
Obtaining Minecraft 1.8.8: Please note that if you wish to 1.8.x, there is no such server build as 1.8.9 and older versions are no longer officially maintained.
https://mineacademy.org/api/paper/1_8_8
Example: To get 26.1.2, just type 26_1_2 directly:
https://mineacademy.org/api/paper/26_1_2
https://mineacademy.org/api/paper/1_21_11
https://mineacademy.org/api/paper/1_20_6
You can use the same logic for Purpur:
https://mineacademy.org/api/purpur/1_21_11
It is even possible to obtain a snapshot build of a software, here is an example from Velocity:
https://mineacademy.org/api/velocity/3_5_0-SNAPSHOT
Here is an example of getting Waterfall. Note that BungeeCord and Waterfall don’t have subversions:
https://mineacademy.org/api/waterfall/1_21
Auto-Download Latest Paper When Launching Your Server
You can use cURL to automatically download the latest software version directly from Paper using our endpoint.
Windows Script Example
Here is an example of a launching script for Windows. Save the content below to a file ending with “.bat” extensions such as “launch.bat”.
Please note to change the startup flags on line 7 according to your preferences.
@echo off
set "jar_url=https://mineacademy.org/api/paper/latest"
set "downloaded_file=paperclip.jar"
curl -fsSL -A "yourname/1.0 (https://yourserver.com)" -o "%downloaded_file%" "%jar_url%"
java -Xms4G -Xmx4G -jar "%downloaded_file%" nogui
pause
Linux And macOS Script Example
And here is an example of a launching script for Linux and macOS. Save the content below to a file ending with “.sh” extensions such as “launch.sh”.
Please note to change the startup flags on line 7 according to your preferences.
#!/bin/bash
cd "$(dirname "$0")"
jar_url="https://mineacademy.org/api/paper/latest"
downloaded_file="paperclip.jar"
curl -fsSL -A "yourname/1.0 (https://yourserver.com)" -o "$downloaded_file" "$jar_url"
java -Xms4G -Xmx4G -jar "$downloaded_file" nogui
New: Use Native Paper Fill Endpoint To Auto-Update
This script is built for the server layout from System Administrator course (minecraft user, server jar at /home/minecraft/server/paper.jar, a minecraft.service managed by systemd).
You must change:
minecraftto your actual username, plus the/home/minecraft/server/paper.jarandminecraft.servicepaths if yours differ.UA="yourname/1.0 (https://yourserver.com)": PaperMC rejects generic User-Agents.VERSION_GROUP="26.1"is the minor version you’re pinning to. The script auto-moves 26.1.2 to 26.1.3, but never to 26.2, so your plugins keep working. Set this to whatever line your server runs.JAR="/home/minecraft/server/paper.jar"must match the exact path and filename yourstart.shlaunches. If yours is namedserver.jar, change it here.
Leave alone:
API="https://fill.papermc.io/v3/projects/paper"— the current PaperMC endpoint. The oldapi.papermc.io/v2stopped getting builds on Dec 31, 2025.
#!/usr/bin/env bash
# Auto-update Paper on the 26.1.x minor line.
# Never crosses into 26.2 or any other version group.
# set -e exit immediately if any command fails (safety net)
# set -u error if we use an unset variable (catches typos)
# set -o pipefail in cmd1 | cmd2, fail if EITHER fails (not just the last)
set -euo pipefail
# === CONFIG ===
# Which version group to track.
VERSION_GROUP="26.1"
# PaperMC requires a User-Agent.
UA="yourname/1.0 (https://yourserver.com)"
# Where the jar lives. start.sh must reference this exact filename.
JAR="/home/minecraft/server/paper.jar"
# Base URL for the Fill API.
API="https://fill.papermc.io/v3/projects/paper"
# === 1. Get all versions inside our pinned group, newest first ===
# curl flags:
# -f fail on HTTP errors (404, 500) instead of writing the error page to disk
# -s silent (no progress bar)
# -S but still show actual errors. -sS = quiet on success, loud on failure
# -L follow redirects (PaperMC redirects to a CDN)
# -H add a header
#
# jq flags:
# -r raw output (no surrounding quotes on strings)
# --arg g … pass a shell variable INTO jq as $g, safely
#
# jq query: .versions[$g] // [] = "give me .versions[26.1], or empty array"
# | .[] = expand the array into separate lines
#
# sort -V -r: -V = version-aware sort (so 26.1.10 comes after 26.1.9, not before),
# -r = reverse, so newest first.
VERSIONS=$(curl -fsSL -H "User-Agent: $UA" "$API" \
| jq -r --arg g "$VERSION_GROUP" '.versions[$g] // [] | .[]' \
| sort -V -r)
# === 2. Walk newest → oldest, take the first one with a STABLE build ===
# We loop because the newest version might only have ALPHA builds out so far.
# We want STABLE only.
for V in $VERSIONS; do
RESP=$(curl -fsSL -H "User-Agent: $UA" "$API/versions/$V/builds")
# jq query, broken down:
# map(select(.channel=="STABLE")) keep only stable builds
# .[0] take the first (newest)
# .downloads."server:default".url drill into nested fields
# (the quotes are needed because "server:default" has a colon)
# // "null" if missing, give the string "null"
URL=$(echo "$RESP" | jq -r 'map(select(.channel=="STABLE"))|.[0].downloads."server:default".url // "null"')
SHA=$(echo "$RESP" | jq -r 'map(select(.channel=="STABLE"))|.[0].downloads."server:default".checksums.sha256 // "null"')
BUILD=$(echo "$RESP" | jq -r 'map(select(.channel=="STABLE"))|.[0].id // "null"')
# Found one? Remember the version and stop looping.
if [ "$URL" != "null" ]; then
FOUND="$V"
break
fi
done
# If we walked everything and found nothing, bail.
# ${FOUND:-} expands to "" if FOUND is unset — needed because of `set -u`.
if [ -z "${FOUND:-}" ]; then
echo "No stable build in $VERSION_GROUP"
exit 1
fi
echo "Latest stable: $FOUND build $BUILD"
# === 3. Already on this build? Skip — don't waste bandwidth ===
# sha256sum FILE prints:
# cut -d' ' -f1 splits on space, takes field 1 → just the hash.
if [ -f "$JAR" ] && [ "$(sha256sum "$JAR" | cut -d' ' -f1)" = "$SHA" ]; then
echo "Already up to date."
exit 0
fi
# === 4. Stage the download in a temp file, verify before swapping ===
# mktemp creates a uniquely-named temp file. XXXXXX gets replaced randomly.
# We put it INSIDE the server folder so the final `mv` is on the same
# filesystem — that makes it atomic (the rename either fully happens or
# doesn't, no half-written state).
TMP=$(mktemp /home/minecraft/server/.paper.XXXXXX.jar)
# trap: register a cleanup command that runs when the script exits,
# even if it crashes. Guarantees we don't leave half-downloaded files behind.
trap 'rm -f "$TMP"' EXIT
# Download.
curl -fsSL -H "User-Agent: $UA" -o "$TMP" "$URL"
# Verify checksum. If it doesn't match, the download was corrupted
# or tampered with — abort before we touch the live jar.
if [ "$(sha256sum "$TMP" | cut -d' ' -f1)" != "$SHA" ]; then
echo "Checksum mismatch — aborting."
exit 1
fi
# === 5. Swap atomically: stop, replace, start ===
# Paper docs are explicit: do NOT replace a running jar.
# systemctl stop blocks until the world is saved (our minecraft.service
# types "stop" in the console and waits), so the save is already guaranteed.
# We use full path /bin/systemctl because that's exactly what we
# whitelisted in sudoers. sudo matches paths character-for-character.
sudo /bin/systemctl stop minecraft.service
# Keep one rollback in case the new build is broken.
[ -f "$JAR" ] && cp -f "$JAR" "$JAR.bak"
# The atomic swap. After this line, the live jar IS the new build.
mv "$TMP" "$JAR"
# Cancel the cleanup trap — we don't want to delete the now-live jar.
trap - EXIT
sudo /bin/systemctl start minecraft.service
echo "Updated to $FOUND build $BUILD"
Now you need to make it executable and let the minecraft user own it:
sudo chown minecraft:minecraft /home/minecraft/server/update-paper.sh
sudo chmod 750 /home/minecraft/server/update-paper.sh
You can use the above script in systemd in two files, because the deamon splits scheduled jobs into:
- .service -what to run
- .timer – when to run it
Here’s a sample paper-update service:
sudo tee /etc/systemd/system/paper-update.service >/dev/null <<'EOF'
[Unit]
# What to run. A .service holds the command, never a schedule.
Description=Auto-update Paper on the pinned minor line
Wants=network-online.target
After=network-online.target
[Service]
# oneshot = run once and exit. Runs as the minecraft user, which is why
# the sudoers rule lets minecraft stop/start the server.
Type=oneshot
User=minecraft
Group=minecraft
ExecStart=/home/minecraft/server/update-paper.sh
EOF
Here’s a sample paper update timer running the script every 4am with a random 15-sec spread:
sudo tee /etc/systemd/system/paper-update.timer >/dev/null <<'EOF'
[Unit]
Description=Run Paper updater daily at 04:00
[Timer]
# Schedule format: YYYY-MM-DD HH:MM:SS, with * meaning "any".
# *-*-* 04:00:00 = daily at 4 AM.
#
# IMPORTANT: uses the SYSTEM timezone. If your VM is on UTC (Azure default),
# 04:00 UTC = 06:00 Central European summer time.
# Set the VM timezone: sudo timedatectl set-timezone Europe/Prague
# Or pin per-timer: OnCalendar=*-*-* 04:00:00 Europe/Prague
OnCalendar=*-*-* 04:00:00
# Wait a random 0–15 min after 04:00. Politeness to the CDN, and if you run
# many servers they don't all restart at the same instant.
RandomizedDelaySec=15min
# If the VM was OFF at 4 AM, run the missed job at next boot. cron loses these.
Persistent=true
# Which service this timer triggers.
Unit=paper-update.service
[Install]
# Hooks the timer into boot so `systemctl enable` makes it auto-start.
WantedBy=timers.target
EOF
To activate:
# systemd caches unit files in memory. Whenever you add or edit one in
# /etc/systemd/system/, you MUST tell it to re-read. Forgetting this is
# the #1 "why isn't my change taking effect" mistake.
sudo systemctl daemon-reload
# enable create the symlink so the timer auto-starts on boot
# --now AND start it right now without waiting for a reboot
sudo systemctl enable --now paper-update.timer
# Show all active timers, plus when each will next fire.
# Look at the NEXT column — that's your "yes scheduling worked" confirmation.
systemctl list-timers paper-update.timer --no-pager
Backups note: If a future build breaks your plugins, the script keeps one previous jar as paper.jar.bak. To go back:
sudo systemctl stop minecraft.service
# Swap the backup back into place.
sudo -u minecraft mv /home/minecraft/server/paper.jar.bak /home/minecraft/server/paper.jar
# Stop the timer so it doesn't immediately re-pull the bad build at 4 AM.
sudo systemctl disable --now paper-update.timer
sudo systemctl start minecraft.service
Security Advisory
Automatically updating between major game versions will break your plugins and can corrupt your worlds, especially given that the early builds of every new major Minecraft update are inherently unsafe.
Updating between subversions also comes with the same risk.
The only real recommended use case for this endpoint is to use it on a local test server.
Do NOT blindly update to the latest version because things will guaranteed break.
Take care,
-Matej