Everything you can do in the panel you can do over the API — power actions, file operations, server management. It is the right tool for deploy scripts, uptime checks and anything that should not depend on someone being logged in.
Two kinds of key
Client key acts as your account. Use it for your own automation — CI, deploy scripts, monitoring.
Application key is scoped to specific services and permissions, and is what you hand to anything you do not fully control. An application key limited to read and power on one service cannot touch the rest of your account, so a leak from a third-party integration is contained.
Prefer application keys for integrations, and a client key only for your own automation. The blast radius of a leak is the entire difference.
Credentials and handling
Keys are created in your account settings. Treat them like any other secret: in environment variables, never in a committed file, never printed to a log.
export PANEL_URL="https://panel.sentinelx.me"
export PANEL_KEY="application-xxxxxxxx"
That second point is worth stating plainly: the panel URL is predictable, so a leaked key needs nothing else to be usable. If a key appears in a log or a repository, revoke and reissue it.
Attaching the key
Send the key in the Authorization header:
curl "$PANEL_URL/api/servers" \
-H "Authorization: Bearer $PANEL_KEY" \
-H "Accept: application/json"
export PANEL_KEY="application-xxxxxxxx"
export SSH_HOST="sentinelx.me"
export SSH_PORT="<your sftp port>"
rsync -az --delete \
--exclude node_modules --exclude .git \
-e "ssh -p $SSH_PORT" \
./dist/ "$PANEL_USER@$SSH_HOST:/home/container/"
curl -X POST "$PANEL_URL/api/servers/$SERVER_ID/power" \
-H "Authorization: Bearer $PANEL_KEY" \
-H "Content-Type: application/json" \
-d '{"signal":"restart"}'
Order matters: upload and verify first, restart last. Restarting before the upload completes serves the old code and then, on the next request, half-written files.
A deploy script that fails safely
Sequence the steps so a failure stops the deploy rather than proceeding with inconsistent state:
- Check the service is up; abort if it is not.
- Upload to a staging directory, not the live one.
- Install dependencies.
- Restart.
- Poll until the port answers.
- On failure, restore the backup taken before the deploy.
Steps 1 and 6 are what separate a script from a hope. Every other step can fail halfway; those two mean a failure costs you minutes rather than an evening.
Polling instead of assuming
A restart returns before the application is listening. Polling until the port answers — with a timeout — turns “started” into “actually serving”, which is the difference between a correct deploy script and one that reports success for a process that then crashes.
for i in $(seq 1 30); do
if curl -fsS "http://127.0.0.1:$PORT/healthz" >/dev/null 2>&1; then
echo "healthy after ${i}s"; exit 0
fi
sleep 1
done
echo "did not become healthy"; exit 1
Keep the health endpoint cheap — a single 200 that does not query the database on every call. A health check heavy enough to fail under load is a health check that reports outages that are not there.