Overview
This page covers what the Integration API is, how it differs from the panel’s own API, and the ground rules that apply to every request: the base URL, the GET-only design, bearer authentication, and the response envelope.
What it is for
Section titled “What it is for”The Integration API is a read-only surface for programs. It exists so a Discord bot, a status page, or a script can read live and save-derived data from your server without a browser session. It is the API the Palhelm Discord bot uses, and the one you would point your own tooling at.
It is deliberately small and safe to expose to automation:
- Read-only. Every route is a
GET. There is no way to kick a player, run a console command, restore a backup, or change a setting through this API. - Redacted. Responses are a strict subset of what a signed-in viewer sees. Platform account IDs, live player positions, and moderation state never appear. See Keys and redaction.
- Token-authenticated. Access uses a bearer key, not a login. Keys are created and revoked from the panel.
How it differs from the panel API
Section titled “How it differs from the panel API”Palhelm has two separate HTTP surfaces. Keeping them apart is a deliberate design choice, not an accident of routing.
| Panel API | Integration API | |
|---|---|---|
| Base path | /api/v1 |
/api/integration/v1 |
| Auth | Session cookie from a password login | Bearer key (Authorization header) |
| Methods | GET and mutating (POST, PUT, DELETE) | GET only |
| Audience | The panel’s own web UI | Bots, dashboards, scripts |
| Data shape | Full viewer data | Redacted, viewer-minus |
The two never mix. A session cookie grants nothing on the Integration API, and a bearer key grants nothing on the panel API. A bearer request is a distinct kind of caller inside the server and can never be mistaken for a signed-in session.
Base URL and versioning
Section titled “Base URL and versioning”Every endpoint lives under a single versioned base path:
https://panel.example.com/api/integration/v1The v1 in the path is the contract version. A future release that needs to change response shapes in an incompatible way would add v2 beside it rather than change v1 under existing clients. Within v1, changes are additive: new fields may appear, but existing fields keep their meaning.
GET-only by construction
Section titled “GET-only by construction”The router registers only GET handlers. This is not a convention that a handler could forget. Any other method on any path in this group returns 405 method_not_allowed with an Allow: GET header, decided by the router itself before any handler runs.
POST /api/integration/v1/players HTTP/1.1Host: panel.example.comAuthorization: Bearer phk_a1b2c3d4_...HTTP/1.1 405 Method Not AllowedAllow: GETCache-Control: no-storeContent-Type: application/json
{"error": {"code": "method_not_allowed", "message": "Method not allowed."}}The response envelope
Section titled “The response envelope”Every successful response is a JSON object with a data member. Save-derived endpoints add freshness fields, and paginated endpoints add a cursor. There are three shapes:
Paginated, save-derived (/players, /pals):
{ "data": [], "lastParseAt": "2026-07-10T02:00:00Z", "formatDrift": false, "nextCursor": null}Save-derived, not paginated (/players/{uid}, /guilds):
{ "data": {}, "lastParseAt": "2026-07-10T02:00:00Z", "formatDrift": false}Live-only (/map, /server, /metrics/current, /events):
{ "data": {}}datais always present.lastParseAtis the time of the last completed save parse, ornullif none has finished. It is your staleness signal for anything read from the save file. It appears only on save-derived endpoints.formatDriftistruewhen the last parse hit an unrecognized save layout and had to skip some data. It also appears only on save-derived endpoints.nextCursorappears only on paginated endpoints. See Pagination and limits.
All timestamps are RFC 3339 in UTC. The eight endpoints and their full field lists are in Endpoints.
Transport and browser access
Section titled “Transport and browser access”There are no CORS headers on this surface, by design. A browser page on another origin cannot call the API directly. If you are building a browser dashboard, proxy the request through your own server so the bearer key never lives in browser-held JavaScript.
Every response also carries Cache-Control: no-store. Do not cache or persist a response body.
Where to go next
Section titled “Where to go next”- Keys and redaction: creating and revoking keys, the key format, and exactly what is hidden from token responses.
- Endpoints: all eight routes with example requests and responses.
- Pagination and limits: cursors, conditional requests, rate limits, and the uniform 401.
- OpenAPI spec: the machine-readable contract and how to generate a client.