Under the Hood
REST API
A FastAPI application running in the bot's own process, serving versioned routes under /api/v1. Authentication is a signed session token, and no secret is ever sent to a client.
Base URL
The server listens on port 5022 by default. The add-on builds its base URL from its protocol, host and port settings, which are stored as three separate keys for reasons covered on the settings page.
{protocol}://{host}:{port}/api/v1Three surfaces, one auth model
/api/v1/...the game client | Everything the KSP add-on needs: linking, profile, missions, contracts, submissions, craft transfer, notifications and marketplace listing. |
/api/v1/web/...this website | The browsing and buying half of the marketplace, contract management, and the profile. Called from the site's own server-side routes, never from page JavaScript. |
/api/v1/web/admin/...the owner console | Listing moderation, user accounts, announcements, publishing add-on versions and runtime controls. Restricted to a single owner account, and it answers 404 rather than 403 to everyone else, so the surface is invisible rather than merely locked. |
Authentication
Every route except the linking pair requires a session token in the standard authorization header. Requests from the game additionally carry the install’s device id in its own header, which is checked against the account’s trusted devices.
GET /api/v1/user/profile
Authorization: Bearer <session-token>
X-Device-Id: <random-per-install>Tokens are HMAC-SHA256 signed and carry a version number that is checked against the account’s current version on each request, which is how logging out everywhere invalidates them all at once without storing the tokens themselves.
Suspension is a gate, not a revocation
A suspended account gets a structured 403 that the client renders as a notice, rather than having its token revoked. A revoked token would drop the add-on to a link screen whose only offer, linking again, would work and explain nothing.
Representative endpoints
The real surface is around a hundred routes. What follows is enough to show the conventions; the definitive contract is the server source.
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /api/v1/auth/linkExchange a 6-digit code for a pending approval. | Exchange a 6-digit code for a pending approval. | Public |
| POST | /api/v1/auth/link/pollPoll that approval until it is answered; returns the signed token. | Poll that approval until it is answered; returns the signed token. | Public |
| GET | /api/v1/auth/verifyValidate a token and return the profile behind it. | Validate a token and return the profile behind it. | Token |
| GET | /api/v1/version/checkReport the client's version and hash; also returns the required policy version. | Report the client's version and hash; also returns the required policy version. | Token |
| GET | /api/v1/user/profileBalance, XP, level and unlocked levels. | Balance, XP, level and unlocked levels. | Token |
| GET | /api/v1/missions/weeklyThe current week's missions and their classifications. | The current week's missions and their classifications. | Token |
| GET | /api/v1/contracts/activeContracts currently on the player's plate. | Contracts currently on the player's plate. | Token |
| POST | /api/v1/contracts/createWrite a new contract from inside the game. | Write a new contract from inside the game. | Token |
| POST | /api/v1/contracts/create_rescueCreate a rescue, snapshotting and removing the issuer's vessel. | Create a rescue, snapshotting and removing the issuer's vessel. | Token |
| POST | /api/v1/auctions/createOpen a reverse auction, escrowing the starting price. | Open a reverse auction, escrowing the starting price. | Token |
| POST | /api/v1/contracts/{id}/submitSubmit work: telemetry, screenshots and the craft file where one is asked for. | Submit work: telemetry, screenshots and the craft file where one is asked for. | Token |
| POST | /api/v1/parts/catalogUpload the install's part catalogue, which the compatibility check reads. | Upload the install's part catalogue, which the compatibility check reads. | Token |
| POST | /api/v1/marketplace/listList the craft currently in the editor for sale. | List the craft currently in the editor for sale. | Token |
| GET | /api/v1/web/marketplace/listingsThe paged, filtered, sorted listing feed. | The paged, filtered, sorted listing feed. | Public |
| GET | /api/v1/web/marketplace/{id}/compatibilityCheck one listing's parts against the caller's uploaded catalogue. | Check one listing's parts against the caller's uploaded catalogue. | Token |
| POST | /api/v1/web/marketplace/{id}/buyPurchase a listing and receive the craft file. | Purchase a listing and receive the craft file. | Token |
| POST | /api/v1/bugreportFile a bug report, optionally with a trimmed KSP.log, as a ticket. | File a bug report, optionally with a trimmed KSP.log, as a ticket. | Token |
| GET | /api/v1/healthLiveness check. | Liveness check. | Public |
Things worth knowing before you write a client
- Interactive API documentation is available but off by default, so the endpoint list is not public on a production server.
- Rate limiting is applied per client address, which behind a reverse proxy means the proxy has to be listed as trusted or every request will look like it came from one machine.
- There is flood detection on the authenticated endpoints that cost money or pay rewards, set far above any human play rate.
- Craft and image downloads are served from signed storage URLs rather than proxied through the API.
- The notification stream uses a short-lived ticket rather than the session token, because the game’s HTTP client cannot set an authorization header on a websocket handshake.