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:

  • minecraft to your actual username, plus the /home/minecraft/server/paper.jar and minecraft.service paths 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 your start.sh launches. If yours is named server.jar, change it here.

Leave alone:

  • API="https://fill.papermc.io/v3/projects/paper" — the current PaperMC endpoint. The old api.papermc.io/v2 stopped 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:   <hash>  <filename>
# 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