SimTX API/Account service
The SimTX account service is the HTTPS JSON API at https://auth.simtx.net. It signs users in, issues credentials, manages persistent stations and satellites, lists the game servers that are online, and exchanges a credential for the single-use game ticket that a game server accepts in the hello. It also serves a small set of public, unauthenticated endpoints.
A client that only receives at an ad-hoc site does not need the account service at all, apart from discovering a server address. A client that transmits, receives through a station, manages stations or publishes to the extension catalog does.
Endpoint summary
| Method | Path | Authentication | Purpose |
|---|---|---|---|
POST |
/api/v1/device/authorizations |
None | Start a device login |
POST |
/api/v1/device/token |
None | Poll for credentials |
POST |
/api/v1/device/refresh |
None | Rotate the credential pair |
GET |
/api/v1/servers |
Bearer | List online game servers |
POST |
/api/v1/game-tickets |
Bearer | Obtain a game ticket |
GET, POST |
/api/v1/stations |
Bearer | List your stations, create a ground station |
GET, PATCH, DELETE |
/api/v1/stations/{id} |
Bearer | Read, edit or delete a station |
POST, PATCH, DELETE |
/api/v1/stations/{id}/antennas... |
Bearer | Manage antennas |
POST, PATCH, DELETE |
/api/v1/stations/{id}/rigs... |
Bearer | Manage rigs |
POST |
/api/v1/satellites |
Bearer | Launch a satellite |
POST |
/api/v1/stations/{id}/deorbit/preview |
Bearer | Preview a deorbit burn |
POST |
/api/v1/stations/{id}/deorbit |
Bearer | Deorbit a satellite |
GET |
/api/v1/satellites |
None | Public satellites |
GET |
/api/v1/status |
None | Service status |
GET |
/api/v1/profiles |
None | Search public profiles |
GET |
/api/v1/profiles/{handle} |
None | Read one public profile |
GET |
/api/v1/releases |
None | Published client releases |
GET |
/downloads/transmitter-update.properties |
None | Update manifest |
GET |
/downloads/{filename} |
None | Release download |
GET |
/api/v1/network-test/ping |
None | Latency probe |
POST |
/api/v1/network-test/upload |
None | Upload probe |
Endpoints under /api/v1/me/, /api/v1/auth/ and the device approval endpoints (/api/v1/device/verify, /api/v1/device/deny, GET /api/v1/device/authorizations/{userCode}) belong to the account website. They require a browser session cookie and a CSRF token and do not accept bearer credentials; the website's station pages use /api/v1/me/stations and /api/v1/me/satellites with the same bodies as the bearer endpoints. Administrative and internal endpoints are not part of the public API and are not documented here.
Conventions
- Transport. HTTPS only. Request and response bodies are
application/json(UTF-8) unless stated otherwise. Timestamps are ISO-8601 strings in UTC, for example2026-10-24T12:00:00Z. - Field names are camelCase. Null fields are omitted. Unknown response fields may be added in future and must be ignored by clients.
- Caching. Every
/api/response carriesCache-Control: no-store, except the public satellite list, which supportsETagrevalidation. - Timeouts. The official clients use a 5 second connect timeout and a 10 second request timeout. Those values are a sensible default.
- Request IDs. A client may send an
X-Request-IDheader matching[A-Za-z0-9._-]{8,64}. The service echoes it in the response header and in error bodies. Without one, the service generates a UUID. Quote it when reporting a problem. - Body size. Station, antenna, rig and launch bodies are limited to 2 MiB (
413 request_too_large).
Authentication
Authenticated endpoints read a bearer credential from the Authorization header. The header must begin with exactly Bearer (capital B, one space).
GET /api/v1/servers HTTP/1.1
Host: auth.simtx.net
Authorization: Bearer stx_at1_0f3c...
Two kinds of credential are accepted as a bearer:
- an access credential obtained through device login, or
- a personal credential created by the user on the account website. It is intended for bots, scripts and other headless software. The user chooses its scopes and expiry, and the secret is displayed once.
What a credential may do is the intersection of its scope and the account's permissions. Station writes, launches and deorbit burns need the scope station.manage; reading stations, previewing a deorbit and minting station-bound tickets need only an account credential.
Credential formats
All SimTX credentials are opaque strings: a fixed prefix followed by 64 lowercase hexadecimal characters (32 random bytes). They are not JWTs and contain no readable data. A client must store them as given and must never parse them.
| Prefix | Credential | Lifetime | Used for |
|---|---|---|---|
stx_dc1_ |
Device code | 10 minutes | Polling /api/v1/device/token
|
stx_at1_ |
Access credential | 10 minutes | Bearer for authenticated endpoints |
stx_rt1_ |
Refresh credential | 30 days idle, 180 days absolute; rotates on every use | /api/v1/device/refresh
|
stx_pc1_ |
Personal credential | Chosen by the user, at most 1 year | Bearer for authenticated endpoints |
stx_gt1_ |
Game ticket | 60 seconds, single use | The game server hello |
A user code (shown to the person signing in) has the form ABCD-EF23: eight characters from the alphabet ABCDEFGHJKLMNPQRSTUVWXYZ23456789, with a hyphen after the fourth. The alphabet omits I, O, 0 and 1, so nobody has to wonder which one they are looking at.
Storing credentials
- Keep the access credential in memory only. It expires after ten minutes in any case.
- Persist the refresh credential (or a personal credential) in the operating system's credential store, such as Keychain, Windows Credential Manager or Secret Service.
- There is no client-side logout endpoint. Signing out means deleting the stored refresh credential. Users revoke devices and personal credentials on the account website.
- Never send an access, refresh or personal credential to a game server. Game servers only ever see game tickets.
Errors
Every error response has the same JSON body:
{
"code": "credential_invalid",
"message": "The access credential is invalid or expired",
"fieldErrors": {},
"requestId": "3d7f0c1e-5b2a-4a8e-9a77-1f0f6f5d2b10"
}
| Field | Type | Description |
|---|---|---|
code |
string | Stable, machine-readable error code. Branch on this. |
message |
string | Human-readable English text. May change; do not parse. |
fieldErrors |
object | Additional string values keyed by name. For example, device polling reports the required poll interval as fieldErrors.interval, and a missing scope as fieldErrors.scope.
|
requestId |
string | The request ID. See Conventions. |
Common error codes
| HTTP | code |
Meaning |
|---|---|---|
| 401 | credential_missing |
No Authorization header, or it does not start with Bearer .
|
| 401 | credential_invalid |
The bearer credential is unknown, expired, revoked, or belongs to an account that is not active. Refresh once and retry; if that fails, sign in again. |
| 400 | scope_invalid |
A requested scope is not a known permission. |
| 403 | scope_required |
The credential's scope lacks a permission the endpoint needs; fieldErrors.scope names it. Sign the user in again with the wider scope.
|
| 400 | ticket_request_invalid |
See Game tickets. |
| 400, 403, 404, 409 | station_invalid, station_not_found, station_sealed and others |
See Station endpoints. |
| 400 | authorization_pending, slow_down, expired_token, access_denied, invalid_grant |
Device polling states. See Device login. |
| 401 | invalid_grant, refresh_reuse_detected |
Refresh failures. See Device login. |
| 404 | profile_not_found, release_artifact_not_found, release_manifest_unavailable |
The requested public resource does not exist. |
| 413 | request_too_large |
The request body is over the limit. |
| 429 | rate_limited |
A rate-limit bucket is exhausted. See below. |
| 500 | internal_error |
Unexpected server failure. Retry later with backoff. |
Rate limits
Rate limits are counted per client IP address, per bucket, in fixed one-minute windows aligned to the UTC minute. A request over the limit receives 429 with code rate_limited. No Retry-After header is sent, so wait for the next minute boundary.
| Bucket | Endpoint(s) | Requests per minute |
|---|---|---|
device-create |
POST /api/v1/device/authorizations |
20 |
device-poll |
POST /api/v1/device/token |
120 |
device-refresh |
POST /api/v1/device/refresh |
120 |
server-directory |
GET /api/v1/servers |
120 |
game-ticket |
POST /api/v1/game-tickets |
120 |
station-read |
GET /api/v1/stations, GET /api/v1/stations/{id}, POST .../deorbit/preview |
240 |
station-write |
Every station, antenna, rig, launch and deorbit write | 120 |
public-satellites |
GET /api/v1/satellites |
120 |
public-directory |
GET /api/v1/profiles |
60 |
public-profile |
GET /api/v1/profiles/{handle} |
120 |
public-releases |
GET /api/v1/releases |
120 |
release-manifest |
GET /downloads/transmitter-update.properties |
240 |
release-download |
GET /downloads/{filename} |
240 |
network-test-ping |
GET /api/v1/network-test/ping |
60 |
network-test-upload |
POST /api/v1/network-test/upload |
144 |
GET /api/v1/status is not rate limited.
See also
- SimTX API/Device login: the sign-in flow for desktop and command-line software.
- SimTX API/Station endpoints: stations, satellites and deorbiting.
- SimTX API/Game tickets: how a credential becomes a game server connection.
- SimTX API/Permissions: scopes and numeric capabilities.