API Keys and REST API
Generate and revoke API keys, connect the editor and MCP server with them, and call the platform REST API for games, builds and live status.
10 min read
What an API key is for#
An API key is a long-lived secret that identifies you to the Vastopia platform. The dashboard signs you in with your browser session; everything that runs outside the browser uses a key instead:
- The Vastopia Editor, when you sign in by pasting a key rather than through the browser flow. Pushing builds, registering a game, syncing project sources and authoring store items all go through that key.
- The Vastopia MCP server, so an AI assistant can publish builds on your behalf.
- Your own scripts and tools that call the REST API directly: listing builds, checking whether a game is live, automating a deploy.
A key carries your whole account. Anyone who holds it can do anything you can do through the API, so treat it like a password.
Manage keys on the dashboard#
API Keys lives in the dashboard sidebar under Account (/settings/api-keys) and is also reachable from the profile dropdown in the header. The page reads "Manage API keys for the Vastopia Editor. Paste a key into the editor to connect your account."
Generate a key#
- In the Generate New Key card, type a name in the field labeled "Key name (e.g. My Editor Key)". Name it after where it will live, such as
Laptop editororCI deploy script, so you can revoke the right one later. - Click Generate.
- A green card appears: "Key created! Copy it now — you won't see it again." Use the copy button next to the key and store it somewhere safe.
The full key is shown exactly once. The platform stores only a hash, so it cannot be retrieved later; if you lose it, generate a new one and revoke the old one.
| Property | Value |
|---|---|
| Format | vst_ followed by 40 hexadecimal characters (44 characters in total) |
| Shown in the list | The first 8 characters (for example vst_a1b2...), creation date and last-used date |
| Expiry | Keys created on this page never expire |
| Limit per account | None is enforced |
Review and revoke#
Each key card lists the name, prefix, Created date and, once it has been used, a Last used date (updated on each authenticated request, best effort). An empty page says "No API keys yet. Generate one to connect the editor."
To revoke a key:
- Click Revoke on its card.
- The Revoke API Key dialog warns: "This will immediately revoke this key. Any editor sessions using it will be disconnected."
- Click Revoke Key.
Revocation is immediate and permanent. An editor signed in with that key gets a 401 on its next request and must sign in again.
Session keys#
The editor can mint a short-lived session key for processes it launches, such as its MCP server: POST /api/users/me/api-keys/session returns a user-scoped vst_ key that expires after 12 hours and is named "MCP session key" unless you pass a name. These show in your list until they expire; you can revoke them like any other key.
Connect the editor with a key#
The editor prefers the browser sign-in (Sign in opens the platform's hosted login), and a pasted key is the alternative when that flow is unavailable. Three places accept one:
| Where | Controls |
|---|---|
| Project wizard login screen (before a project opens) | Field "Paste API key" and Sign in with API Key; Continue Offline skips sign-in for local work |
| Account Info dialog (profile button in the top bar) | Field "…or paste an API key" and Use Key; also shows the active key masked as its first and last four characters, or "OAuth session (temporary)" |
| Upload popover | "Generate an API key on the website and paste it here", with a Get API Key button that opens the dashboard |
Pasting a key makes the editor call GET /api/users/me with it; on success the key is saved to the editor's user data folder as vastopia_platform.cfg ([platform] api_key) and the editor is signed in as that account. A key that the platform rejects shows "Invalid API key". Sign Out in the Account Info dialog clears it.
Connect the MCP server with a key#
The Vastopia MCP server needs a key only for publishing tools (register_game, create_build, upload_build_artifacts, finalize_build, deploy_test_build, promote_build, rollback_build, update_game_listing and friends). Authoring tools work without one.
| Environment variable | Effect |
|---|---|
VASTOPIA_API_KEY | The key to send as x-api-key. Always wins over any other source. |
VASTOPIA_API_URL | Platform API base URL. Only localhost / 127.0.0.1, the production Heroku host, and vastopia.com and its subdomains over HTTPS are accepted; anything else is ignored with a warning so the key is never sent to an untrusted host. |
VASTOPIA_PUBLISHING | Set to off to withhold credentials entirely, even if the editor would have supplied them. |
When VASTOPIA_API_KEY is unset, the MCP server falls back to the key the editor saved in vastopia_platform.cfg, so signing in to the editor once is enough. Without any credential the publishing tools are still listed but fail with a message telling you to set VASTOPIA_API_KEY. See MCP setup.
Call the REST API yourself#
The production base URL is https://vastopia-api-8a231eb9cc69.herokuapp.com/api. Every authenticated request carries the key in an x-api-key header:
curl -H "x-api-key: vst_your_key_here" \
https://vastopia-api-8a231eb9cc69.herokuapp.com/api/users/me
The API also accepts the key as an Authorization: ApiKey <key> header, an apiKey query parameter or an apiKey field in a JSON body, but the header is the recommended form because it stays out of logs and URLs. Authorization: Bearer is reserved for browser and OAuth tokens; do not put an API key there.
Responses are JSON. Successful calls generally include "success": true; failures return an HTTP status with a message or error field:
| Status | Typical body | Meaning |
|---|---|---|
| 401 | {"error":"Invalid API key"} | Missing, revoked or mistyped key |
| 403 | {"message":"Not the game owner"} | The key is valid but the game belongs to someone else |
| 404 | {"message":"Game not found"} | Unknown game, or a private game you do not own |
| 429 | {"error":"Too many build mutations from this user (60/hr cap)"} | Build creation is rate-limited per user |
| 503 | {"error":"Auth lookup unavailable, please retry"} | Transient auth outage; retry |
Check who you are#
curl -H "x-api-key: $VASTOPIA_API_KEY" "$API/users/me"
Returns your profile (username, email and related fields). This is the same call the editor makes to validate a pasted key, so it is the quickest way to test one.
List your games and builds#
# Your games (newest first; supports ?page=, ?limit=, ?q=, ?tag=)
curl -H "x-api-key: $VASTOPIA_API_KEY" "$API/games/me"
# Builds for one game, newest first (add ?includeDeleted=true to see deleted ones)
curl -H "x-api-key: $VASTOPIA_API_KEY" "$API/games/$GAME_ID/builds"
Each build row includes buildId, buildNumber, buildName, status, pckSize, totalSize, versionLabel, promotedAs, patchNote, testServerHost/testServerPort while a test server is up, createdAt, promotedAt and failureReason. Statuses are uploading, ready, live, staged, superseded, beta, archived, deleted and failed; see Builds and versions.
Check live status (no key needed)#
curl "$API/games/$GAME_ID/live"
This endpoint is public. It returns the build players currently get: buildId, versionLabel, buildName, serverHost, serverPort, serverStatus, a one-hour presigned pckDownloadUrl, file sizes and SHA-256 hashes, deployedAt, isStaged, updateInProgress and the signature fields clients verify before mounting a pack. If a staged build exists it is preferred for new sessions; add ?prefer=live to ask for the live build instead. A game with nothing deployed answers 404 {"success":false,"error":"No deployed version"}.
Promote a build#
curl -X POST -H "x-api-key: $VASTOPIA_API_KEY" -H "Content-Type: application/json" \
"$API/games/$GAME_ID/builds/$BUILD_ID/promote" \
-d '{"type":"update","updatePost":{"title":"Combat Update","body":"Reworked melee hitboxes."}}'
type must be update or patch. An update may carry an updatePost (both title, up to 120 characters, and body, up to 20,000, or neither) or an updatePostId pointing at a draft; a patch may carry a patchNote. timing defaults to now. When deployment jobs are enabled the call returns 202 with a jobId, which you can follow with GET /games/{gameId}/deploy-status. The dashboard's Update tab is the same call with a form in front of it; see Updates, patches and rollback.
Endpoint reference#
All paths are relative to the base URL. "Owner" means the key's account must own the game; most game-scoped routes check ownership rather than team role.
Account and keys#
| Method | Path | Auth | Purpose |
|---|---|---|---|
| GET | /meta | none | Service name, API version and supported feature flags |
| GET | /users/me | key | Your profile |
| GET | /users/me/api-keys | key | List your keys (prefix, name, dates) |
| POST | /users/me/api-keys | key | Create a key; body {"name": "..."}; returns the full key once (201) |
| POST | /users/me/api-keys/session | key | Mint a 12-hour session key |
| DELETE | /users/me/api-keys/{keyId} | key | Revoke a key |
Games#
| Method | Path | Auth | Purpose |
|---|---|---|---|
| GET | /games/me | key | Games you own |
| GET | /games/{gameId} | optional | Game details; non-owners only see published, non-private games |
| POST | /games/register | key | Link a gameId and name to your account (the editor and register_game use this) |
| PATCH | /games/{gameId} | owner | Update listing fields such as name, description, excerpt, tags, visibility, contentRating, image URLs |
| DELETE | /games/{gameId} | owner | Delete the game, its builds, update posts and branding, and release its server |
| POST | /games/{gameId}/upload-url | owner | Presigned upload for branding images (type of icon, cover, cover_logo, screenshot, loading_screen or update_image) |
Builds and deployment#
| Method | Path | Auth | Purpose |
|---|---|---|---|
| GET | /games/{gameId}/builds | owner | List builds |
| POST | /games/{gameId}/builds | owner | Create a build; body {"build_name": "...", "game_name": "..."}; auto-creates the game on first push; returns presigned uploadUrls for pck, serverPackage and gameConfig |
| PATCH | /games/{gameId}/builds/{buildId}/finalize | owner | Mark the upload complete with sizes and SHA-256 hashes |
| POST | /games/{gameId}/builds/{buildId}/deploy-test | owner | Start a test server for the build |
| POST | /games/{gameId}/builds/{buildId}/stop-test | owner | Stop the test server |
| POST | /games/{gameId}/builds/{buildId}/deploy-beta | owner | Start a beta server |
| GET | /games/{gameId}/beta/status | owner | Beta server status and code |
| POST | /games/{gameId}/beta/stop | owner | Stop the beta server |
| POST | /games/{gameId}/builds/{buildId}/promote | owner | Deploy as an update or patch |
| POST | /games/{gameId}/rollback/{buildId} | owner | Re-deploy a previously live or archived build |
| POST | /games/{gameId}/builds/{buildId}/redeploy | owner | Redeploy a ready, archived or live build |
| DELETE | /games/{gameId}/builds/{buildId} | owner | Soft-delete a build (restore with POST .../restore) |
| GET | /games/{gameId}/deploy-status | owner | Active or latest deploy job plus queued jobs |
| GET | /games/{gameId}/schedule | owner | Scheduled deployment, cancel with POST .../schedule/cancel |
| GET | /games/{gameId}/live | none | Currently deployed build and server address |
| GET | /games/{gameId}/updates | key | Update posts; POST creates a draft, PATCH/DELETE .../{updateId} edit or remove one |
| GET | /hosting/tiers, /hosting/regions | none | Hosting tiers and regions for the launch wizard |
Shop, creator economy and revenue#
| Method | Path | Auth | Purpose |
|---|---|---|---|
| GET / POST | /games/{gameId}/shop/items | owner | List or create store items (see Shop, revenue and payouts) |
| PATCH / DELETE | /games/{gameId}/shop/items/{itemId} | owner | Update (priceCoins, isActive, stock, ...) or delete an item |
| POST | /games/{gameId}/shop/icon-upload-url | owner | Presigned upload for a store icon (512 KiB cap) |
| GET | /games/{gameId}/shop/purchases?limit= | owner | Recent purchases |
| GET | /games/{gameId}/shop/stats/daily?days= | owner | Daily shop statistics and summary |
| GET | /creator/connect, /creator/balance, /creator/earnings | key | Stripe Connect status, balance buckets and earnings ledger (?limit=, ?kind=, ?state=) |
| GET | /games/{gameId}/revenue/summary, /timeseries, /by-sku, /by-country, /refunds | Owner or Finance | Stripe revenue reports (?from=, ?to= ISO dates; `?interval=day |
| POST | /games/{gameId}/revenue/refunds/{purchaseId} | Owner or Finance | Issue a Stripe refund; body {"reason": "..."} |
Keep keys safe#
- Never commit a key to a repository or paste it into a shared chat. If one leaks, revoke it on the dashboard immediately and generate a replacement.
- Use one key per machine or tool and name it accordingly; revoking a single key then disconnects only that device.
- Prefer the browser sign-in in the editor and the editor-credential fallback in the MCP server, so the secret exists in one place on disk.
- The platform keys automatically provisioned for your game servers (
srv_) cannot act as you, but revoking them affects your running server, so leave them alone. - Account deletion under Privacy & Account removes every key with the account.
With AI (MCP)#
There is no MCP tool for managing keys; generate one on the dashboard or let the MCP server reuse the editor's sign-in. The publishing tools that consume the key are register_game, create_build, upload_build_artifacts, upload_pck_multipart, finalize_build, deploy_test_build, stop_test_server, get_deploy_status, wait_for_deploy, list_builds, promote_build, rollback_build, get_live_status and update_game_listing. See the MCP tools reference.
