Resource hub.
Whether you're just installing the plugin, troubleshooting a quirk, or building something custom on top of the API — everything lives here.
Top destinations
Get the latest PulseConnect.jar. Free, MIT-licensed companion plugin for Paper, Spigot, and Purpur.
Step-by-step walkthrough: install the plugin, configure the secret, forward your port, sign in. ~5 minutes.
Build a Discord bot, web dashboard, or custom client. Full REST + WebSocket reference, JWT auth, worked examples.
Every key in config.yml explained — defaults, valid values, security implications.
Quick answers to the most common questions about hosting, security, and supported server software.
Bug reports, feature requests, anything else — every message reaches the developer directly.
PulseConnect plugin.
The free, server-side companion to PulsePanel. Drop it in your plugins/ folder, configure once, and the iOS app can talk to your server.
Where the plugin lives
PulseConnect is hosted on GitHub as an open-source project under the MIT license.
- Latest JAR — the Download button above always grabs the newest release.
- All versions — see the Releases page for version history.
- Source code — inspect, fork, or contribute on GitHub.
- Issues & feature requests — file them on GitHub Issues, or email support@pulsepanelapp.com.
config.yml, and connecting the app — about 5 minutes.What you'll need.
PulsePanel runs on most modern Minecraft servers and any iPhone or iPad on iOS 17+. Here's the full compatibility matrix.
Server
Network
7070 TCP (configurable)iOS app
Managed Minecraft hosts
Many managed hosts (BisectHosting, Apex, Shockbyte, PebbleHost) lock down their network and only expose the Minecraft port. Before signing up, confirm the host supports opening additional TCP ports for plugins — without it, PulsePanel can't reach your server remotely.
Self-hosted servers and most VPS providers (DigitalOcean, Linode, Hetzner, etc.) work without restrictions.
Configuration reference.
Every key in plugins/PulseConnect/config.yml, what it does, and what to watch out for. The plugin generates this file with sensible defaults on first start — you only need to touch a few keys.
api:
How the plugin exposes its HTTP + WebSocket interface to the app.7070
The TCP port the plugin listens on. The app connects to this port. Forward this port on your router for remote access.
Change it if 7070 is already in use, or if your hosting provider only allows specific ports.
A server-internal secret the plugin uses to sign session tokens. Treat it like a password.
This is not something you enter in the app — it stays on the server. Use 32+ random characters; openssl rand -hex 32 works well.
24
How long an app sign-in stays valid before the user has to sign in again.
Lower values are slightly more secure but more annoying. Higher values are convenient but extend the lifetime of a leaked token. The default of 24 hours is a reasonable trade-off.
admin:
Used only on first launch to create the initial owner account.admin
The username for the owner account. This is what you'll sign in with on the app.
password123
change before launch
The password for the owner account. Stored hashed (BCrypt) in the database after first launch.
password123 as the placeholder. Change this in config.yml before you start the server, or change it via the app's account settings immediately after first sign-in.
The admin: block is read only on first plugin startup, when the database is empty. Once the owner account exists, this block is ignored — changing the values here won't affect the existing account.
To change credentials after first launch, use the app's account settings (or do a clean reset; see troubleshooting).
You can blank these fields out after first launch — the plugin doesn't need them anymore.
security:
Built-in protections for the sign-in flow and API rate limiting.5
How many failed sign-in attempts allowed before the (username, IP) pair is locked out.
Lower values are stricter against brute-force attacks but more punishing if you fat-finger your password.
15
How long the lockout lasts after hitting max-login-attempts.
Restarting the server clears the in-memory lockout state regardless of this value.
60
Maximum API requests per minute, per authenticated user. Prevents a misbehaving client from hammering the server.
The default is generous for normal app usage. Custom integrations doing heavy polling may need a higher value — or better, switch to the WebSocket for real-time data.
logging:
What the plugin writes to the server console.true
Log every API request to the server console. Useful for debugging client integrations and verifying the plugin is reachable.
Set to false on busy servers to reduce log noise. Privileged actions are still recorded in the audit log regardless.
true
Log every command executed via POST /command to the server console.
Recommended to leave on — commands run via the API have the same authority as console commands. The audit log captures these regardless, but console visibility is useful in real time.
// commands
In-game commands the plugin registers./pulseconnect
/pcAdmin command for inspecting and managing the plugin from in-game or the server console.
/pulseconnect help— list available subcommands/pulseconnect status— show plugin status (port, connected sessions, uptime)/pulseconnect reload— reloadconfig.ymlwithout restarting the server
/ticket
Player command for the in-game support ticket system. Players use this to ask staff for help; tickets show up in the app for the owner to respond to.
/ticket create <message>— open a new ticket/ticket reply <message>— reply to your active ticket/ticket close— close your active ticket/ticket list— view your ticket history
pulseconnect.admin
Bukkit permission required to run /pulseconnect subcommands. Granted to operators by default; reassign via your permission plugin (LuckPerms, etc.) if you want it to behave differently.
config.yml influences but doesn't fully document on its own.When things break.
Most issues fall into one of a dozen patterns. Start with the diagnostic flowchart if the app won't connect, otherwise jump to the relevant category below.
App won't connect — diagnose in 4 steps
// the most common failure path
[PulseConnect] API listening on :7070 after startup?Connection & network
5 issuesConnection refused or timeout
The plugin isn't running, or it isn't reachable on the address/port you gave the app.
Diagnose- Check the server console for
[PulseConnect] API listening on :7070after startup. If it's missing, the plugin didn't load — see Plugin doesn't load. - Confirm the address in the app matches your server's public IP or hostname. If you self-host, your public IP (not
192.168.x.x). - Confirm the port matches
api.portinconfig.yml(default7070). - Test the port from outside your network using canyouseeme.org or your phone on cellular data. If the port is closed, your forward isn't working.
- If you're behind a managed Minecraft host, confirm they've opened that port for you. Many hosts only expose the Minecraft port by default.
Port forwarding & CGNAT
Either the router rule isn't applying, or your ISP is using Carrier-Grade NAT (CGNAT) — common on mobile, rural, and cellular ISPs — which makes inbound connections impossible without a workaround.
Diagnose- In your router, confirm the rule: external port
7070→ internal IP of your server, internal port7070, protocol TCP. - Make sure you're forwarding to the server's current internal IP — DHCP can change it. Set a static lease for the server in your router.
- Compare your public IP at whatismyipaddress.com with the IP your router shows on its WAN interface. If they differ, you're behind CGNAT and standard port forwarding won't work.
- Ask your ISP for a public IPv4 address (sometimes free, sometimes a small monthly fee).
- Use a tunneling service: Tailscale Funnel, Cloudflare Tunnel, or a small VPS reverse proxy.
- Move the Minecraft server to a VPS provider that gives you a real public IP (DigitalOcean, Linode, Hetzner, etc.).
Connects on Wi-Fi but fails on cellular (or vice versa)
Almost always a network-side restriction, not the app. Some Wi-Fi networks (corporate, school, public guest) block non-standard ports outbound. Some cellular carriers throttle or block similarly. Or, if it works on Wi-Fi but not cellular, you might be using a local IP that only resolves on your home network.
Diagnose- If you used a
192.168.x.xaddress in the app, that only works on your home Wi-Fi. Use your public IP or hostname instead. - Test from cellular by toggling Wi-Fi off. If it fails, the Wi-Fi network is blocking outbound traffic to your port.
- Try a non-default port like
8443inapi.port— many networks allow that range while blocking unusual ones.
"Local Network" permission prompt didn't appear
iOS only prompts once. If you dismissed it or denied it, the app can't reach servers on your local Wi-Fi (only over the internet).
FixThe app's connection-error screen has an Open Settings button that deep-links to the right place. Or manually: iOS Settings → PulsePanel → Local Network → On.
This only matters when connecting to a server on the same Wi-Fi network as your phone. Connecting to a remote server over the internet doesn't need Local Network permission.
Worked yesterday, broken today
Something on either side changed. The usual suspects, in order of likelihood:
- Dynamic IP changed (most common for self-hosters) — your home IP rotates, and the address saved in the app no longer points to your server. Check your current public IP and update the app.
- Router restarted — port-forward rules sometimes don't survive firmware updates or reboots. Verify the rule is still active.
- Plugin or server updated — check the server console for
[PulseConnect]errors after startup. - iOS or app updated — try fully quitting and relaunching the app. If still broken, sign out and sign back in.
- Token expired — by default JWTs expire after 24 hours. Sign in again.
If your IP rotates often, set up a dynamic DNS hostname (DuckDNS, No-IP, Cloudflare with a script) and point the app at the hostname instead of the raw IP.
The plugin itself
3 issuesPlugin doesn't load on server start
The JAR is missing, in the wrong folder, incompatible with the server software, or has a corrupted config.yml.
- Confirm
PulseConnect.jaris inplugins/, not a subfolder. - Check the full server console output during startup. Look for any line containing
PulseConnect— if the JAR is being seen, you'll get either a success line or an explicit error. - If you see a YAML parse error, your
config.ymlhas bad indentation or unquoted special characters. Restore the default by deletingplugins/PulseConnect/config.ymland restarting the server — it'll regenerate. - Confirm Java version: PulseConnect requires Java 17 or newer. Run
java -versionon the server. - Confirm server software: Paper, Spigot, or Purpur on Minecraft 1.21+. Forge and Fabric aren't supported.
Port already in use / BindException
Something else is already listening on port 7070 (or whatever you set in api.port). Common culprits: another instance of the same plugin, a different admin plugin (ServerTap, AdminAPI, etc.), or a leftover process from a previous server crash.
- Stop the server cleanly. If a plugin from a previous run is still holding the port, give it 30 seconds to release.
- On Linux:
sudo lsof -i :7070shows what's using the port. Kill that process if it's stale. - If two plugins genuinely need different ports, change
api.portinconfig.ymlto something unused (e.g.7080) and update your port forward + the app.
Database errors — SQLITE_BUSY or Hikari pool exhausted
The plugin's SQLite database is being hit by multiple writers at once and locking up. This is rare in normal use but can happen on very busy servers, after a crash, or if another tool is reading plugins/PulseConnect/pulseconnect.db while the plugin is running.
- Close any external SQLite browser, sqlite3 CLI session, or backup tool that's accessing the plugin's database.
- Stop the server. Wait 10 seconds. Start it again.
- If errors persist, the database may be partially corrupt. Stop the server, copy
pulseconnect.dbsomewhere safe as a backup, then delete it. The plugin will recreate a fresh database on next startup. (You'll lose audit log history, ticket history, and accounts — re-add the admin account viaconfig.yml.)
Authentication
3 issuesAuth failed with correct password
Username or password doesn't match what the plugin's database stored. Common reasons: trailing spaces from copy-paste, caps lock, or the credentials in config.yml were changed after first launch (those fields only matter on first launch — the database is the source of truth after that).
- Type the username and password manually instead of pasting. Watch for caps lock and trailing spaces.
- If you changed
admin.usernameoradmin.passwordinconfig.ymlafter the plugin's first run, those changes had no effect. Use whatever credentials existed at first launch. - If you've truly forgotten, see Forgot admin credentials below.
Locked out — "too many attempts"
5 failed login attempts within 15 minutes triggers an automatic lockout (configurable). The lockout is keyed by username + IP, and resets on its own.
Fix- Wait 15 minutes (or whatever
security.lockout-minutesis inconfig.yml) and try once more — this time with the correct credentials. - If you need to bypass it immediately, restarting the server clears the in-memory lockout state.
POST /auth/login — your custom client will get a 429 Too Many Requests. Implement an exponential backoff after a 401 to avoid tripping the lockout during testing.
Forgot admin credentials
The owner password is BCrypt-hashed in the plugin's database and isn't recoverable. The clean reset path is to wipe the database and let the plugin recreate the account from config.yml.
- Stop the server.
- Edit
plugins/PulseConnect/config.ymland setadmin.usernameandadmin.passwordto fresh values. - Delete (or move aside as backup)
plugins/PulseConnect/pulseconnect.db. - Start the server. The plugin will create a new database and a new owner account from the values in
config.yml. - Sign in with the new credentials in the app.
What you lose: audit log history, closed tickets, any flagged players, ban/mute history that's stored in the plugin (server-side bans in the vanilla banlist are unaffected).
Push notifications
2 issuesNotifications not arriving
Push delivery has several layers — any one of them can be off. Work through them in order.
Diagnose- iOS-level permission — Settings → PulsePanel → Notifications → confirm Allow Notifications is on.
- App-level toggles — in the app, Settings → Notifications → confirm the categories you care about (tickets, server lag, etc.) are enabled.
- Server has internet access — the plugin needs outbound HTTPS to deliver pushes. If your server is firewalled to local-only, push won't work. A quick
curl https://www.google.comfrom the server confirms outbound is open. - Device is registered — open the app once on the device you want notifications on. The app registers its APNs token on each launch.
- Trigger a test event — join the server yourself (player_join is an easy one to verify), or open and reply to a ticket in-game.
If all of the above check out and notifications still aren't arriving, send the symptom + your iOS version to support@pulsepanelapp.com.
Notifications arrive delayed (minutes late)
Almost always iOS-side, not server-side. Apple intentionally batches and throttles pushes when the device is in low-power mode, on a constrained network, or has been idle for a while. The relay forwards within milliseconds — Apple's queue is what introduces delay.
Things that help- Disable Low Power Mode on the device.
- Open the PulsePanel app at least once a day — apps that haven't been opened in a while get more aggressively throttled.
- For tickets specifically, raising priority (
tickets.manage+ Set priority → high) marks the push as time-sensitive on iOS, which bypasses some throttling.
For genuinely real-time monitoring, the in-app live console and dashboard are sub-second; push is for awareness when you're not in the app.
App behavior
2 issuesDashboard is empty after connecting
The app authenticated but no data is flowing. Most often this means the server is still mid-startup, or there's a plugin error suppressing the data streams.
Fix- Wait 20-30 seconds, then pull-to-refresh the dashboard.
- Check the server console for any
[PulseConnect]error lines around the time you signed in. - Force quit the app (swipe up from app switcher) and reopen it.
- If the dashboard fills in but specific tabs (Console, Players, etc.) are empty, that points to a permission issue — sign out and back in to refresh your token.
File manager won't save — "file changed" conflict
The plugin uses optimistic locking on file writes. If the file changed on disk between when you opened it in the app and when you tried to save, the plugin returns a conflict instead of overwriting blindly.
Fix- Tap the file again to reload the latest version.
- Re-apply your edits to the fresh content.
- Save again.
This usually happens when something else (a plugin auto-rewrite, a separate SSH session, or another admin) modified the same file. The conflict is protecting your edits — the file would have lost data otherwise.
POST /files/write — if your expected_hash doesn't match, you'll get 409 Conflict with the current hash in the response. Re-read with GET /files/read and retry. Full details in the API reference.
Hosting-specific gotchas
1 issueReverse proxy (nginx / Caddy / Cloudflare) breaks WebSocket
HTTP requests work but the live console / chat / events don't stream. Reverse proxies often need explicit WebSocket upgrade headers, and Cloudflare's free tier will sometimes interfere with long-lived WebSocket connections.
Fix — nginxlocation /api/v1/ws {
proxy_pass http://localhost:7070;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
Fix — Caddy
Caddy handles WebSocket upgrades automatically. A simple reverse_proxy localhost:7070 works for both REST and WebSocket — no extra config needed.
Cloudflare's free plan supports WebSockets, but you may need to enable it explicitly under Network → WebSockets. If you're seeing intermittent disconnects, also check your Page Rules aren't caching the API path.
What's changing.
Release history for both the iOS app and the PulseConnect plugin. Newest first.
First release pending
The full changelog will start populating with the App Store launch. Subsequent updates to the iOS app and plugin will all land here with version numbers, dates, and notes.
Frequently asked.
Quick answers to the questions that come up most often. If yours isn't here, get in touch.
Compatibility & hosting
What server software is supported?
Paper, Spigot, and Purpur on Minecraft 1.21 or newer. Anything that runs Bukkit-API plugins on Java 17+. Forge and Fabric are not currently supported.
Will it work on a managed Minecraft host?
Only if the host allows you to open an additional TCP port beyond the Minecraft port. Some managed hosts lock the network down and only expose Minecraft itself — PulsePanel can't reach the server in that case.
Before paying for a host, ask whether they support opening custom TCP ports for plugins. Many do, some on request, some not at all.
Do I need to open ports on my server?
Yes — one TCP port for the plugin (7070 by default, configurable). Forward it on your router for remote access. Setup takes about a minute on most routers, and the setup guide walks through the common cases.
Security & privacy
Is it safe to expose my server like this?
Yes, with the standard caveats that apply to any service exposed to the internet. The plugin authenticates every request, file access is sandboxed to plugin folders, every privileged action is logged, and login attempts are rate-limited with lockouts.
The app authenticates over TLS using the credentials you create on the server. Your data flows directly between the app and your server — never through anyone else's infrastructure.
Where do my credentials live?
On your server (hashed with BCrypt in the plugin's database) and on your iPhone (in the iOS Keychain). Nothing is stored on PulsePanel infrastructure — there are no PulsePanel accounts.
What does PulseRelay see?
The relay is a pass-through for push notifications. It forwards to Apple's Push Notification service and discards the data. No database, no logs of notification contents, no IP retention. Full details in the privacy policy.
Pricing & licensing
Is the plugin free?
Yes. PulseConnect is free and stays free. You only pay once for the iOS app — no subscription, no per-server fee.
Is there a free trial?
The plugin is free, so you can run it on your server with no commitment. The iOS app is a one-time purchase — Apple's standard refund policy applies if it doesn't work for you.
Features & roadmap
Can multiple staff use the app?
Not yet. The current release is owner-only — one admin account, one device. Multi-staff support with per-user permissions is on the roadmap.
The plugin's API does support multi-user accounts and granular permissions if you're building a custom client. See the API reference.
Can I manage multiple servers from one app?
Not in the current release — single server only. Multi-server is on the roadmap.
Can I integrate with Discord / a web dashboard / a CLI?
Yes. The plugin's REST + WebSocket API is fully documented. See the API reference for endpoint specs and worked examples in Python, Node, and curl.
Get in touch.
PulsePanel is built and maintained by one developer. Every email reaches me directly.
For bug reports, feature requests, billing questions, security disclosures, or anything else:
Typical response: within a couple of days.
Bug reports — what to include
The more of the following you can include, the faster I can help:
- What happened vs. what you expected
- Steps to reproduce, if you can find them
- Server software and version (e.g. Paper 1.21.4)
- Plugin version from
config.ymlor the plugin list - iOS version and device
- Server console excerpt with any
[PulseConnect]lines around the time of the issue
A screenshot of the app's error message also helps a lot.
Security disclosures
If you've found a security vulnerability, please email support@pulsepanelapp.com with details. Don't open a public issue or post about it publicly until it's been addressed.
I take this seriously and will respond as soon as possible — typically same day for anything that affects user security.