SimTX API/Station endpoints
The station endpoints of the account service create, read, edit and delete an account's persistent stations, launch satellites and deorbit them. A station belongs to the account, not to a game server; game sessions attach to it with a station-bound game ticket.
All endpoints take a bearer credential (an access credential or a personal credential) on https://auth.simtx.net. Service credentials are refused with 403 account_credential_required.
Endpoints
| Method and path | Scope | Result |
|---|---|---|
GET /api/v1/stations |
Any | 200 {"stations": [Station]}: your stations
|
POST /api/v1/stations |
station.manage |
201 Station: create a ground station
|
GET /api/v1/stations/{id} |
Any | 200 Station
|
PATCH /api/v1/stations/{id} |
station.manage |
200 Station
|
DELETE /api/v1/stations/{id} |
station.manage |
204
|
POST /api/v1/stations/{id}/antennas |
station.manage |
201 Station (ground stations only)
|
PATCH, DELETE /api/v1/stations/{id}/antennas/{antennaId} |
station.manage |
200 Station
|
POST /api/v1/stations/{id}/rigs |
station.manage |
201 Station (ground stations only)
|
PATCH, DELETE /api/v1/stations/{id}/rigs/{rigId} |
station.manage |
200 Station
|
POST /api/v1/satellites |
station.manage |
201 Station: launch a satellite
|
POST /api/v1/stations/{id}/deorbit/preview |
Any | 200 Deorbit: what a burn now would do
|
POST /api/v1/stations/{id}/deorbit |
station.manage |
200 Station: fire the deorbit burn
|
GET /api/v1/satellites |
None (public) | 200 {"satellites": [SatelliteCatalogEntry]}; see Public endpoints
|
"Any" means any account credential, without a particular scope. A write with a credential whose scope lacks station.manage is refused with 403 scope_required and fieldErrors.scope = "station.manage"; sign the user in again with the wider scope. An account without the permission gets 403 permission_denied. Rate limits: 240 reads and 120 writes per minute per IP address.
The Station object
{
"stationId": "3f2504e0-4f89-41d3-9a0c-0305e82c3301",
"ownerAccountId": "0f8e2c4a-1b3d-4e5f-8a9b-0c1d2e3f4a5b",
"ownerHandle": "n0call",
"kind": "GROUND",
"state": "ACTIVE",
"name": "Home",
"callsign": "N0CALL",
"visibility": "UNLISTED",
"revision": 3,
"limits": { "maxSessions": 16, "maxTransmitters": 4, "maxReceivers": 16 },
"location": { "latitudeDeg": 47.4979, "longitudeDeg": 19.0402, "altitudeMeters": 120.0 },
"antennas": [
{
"antennaId": "9b2c1e47-2f0a-4c55-8d1e-6a7b8c9d0e1f",
"name": "40 m dipole", "ordinal": 0, "revision": 1,
"type": "DIPOLE", "heightMeters": 10.0, "azimuthDeg": 90.0,
"feedlineLossDb": 1.0, "wireLengthMeters": 0.0, "mount": "FIXED"
}
],
"rigs": [
{
"rigId": "c41d7a52-0e3b-4f6a-9c8d-1b2a3c4d5e6f",
"name": "100 W transceiver", "revision": 1,
"paMaxWatts": 100.0, "noiseFigureDb": 6.0,
"tx": { "carrierLeakDb": 55.0, "oppositeSidebandSuppressionDb": 50.0 }
}
],
"createdAt": "2026-10-24T12:00:00Z",
"updatedAt": "2026-10-24T12:30:00Z"
}
| Field | Type | Description |
|---|---|---|
stationId |
string (UUID) | Never changes. |
ownerAccountId, ownerHandle |
string | The owning account. |
kind |
string | GROUND or SATELLITE.
|
state |
string | ACTIVE, DEORBITING or DEORBITED. Ground stations are always ACTIVE.
|
name, callsign |
string | 1 to 64 characters each. |
visibility |
string | PUBLIC or UNLISTED. See Visibility.
|
revision |
integer | Increases with every edit of the station. |
limits |
object | maxSessions, maxTransmitters, maxReceivers, each 0 to 10,000, clamped to the owner's game.station_sessions.N.
|
location |
object | Ground stations: latitudeDeg (−90 to 90), longitudeDeg (−180 to 180), altitudeMeters (−500 to 10,000).
|
orbit, attitude |
object | Satellites. See Orbit and attitude. |
deorbit |
object | Satellites whose deorbit burn has fired. See Deorbiting. |
antennas |
array | 1 to 8 antennas (satellites: 1 to 4). See Antennas and rigs. |
rigs |
array | 0 to 8 rigs. |
createdAt, updatedAt, launchedAt, deorbitedAt |
string | Timestamps; launchedAt and deorbitedAt for satellites.
|
Antennas and rigs
An antenna has antennaId, name (at most 64 characters), ordinal (its position; the first antenna is the default for tickets), revision, and the fields of the game protocol's AntennaConfig in camelCase:
| Field | Description |
|---|---|
type |
An antenna type name. |
heightMeters |
≥ 0. Default 10 for ground stations, 0 for satellites. |
azimuthDeg |
−360 to 360. |
feedlineLossDb |
≥ 0. Default 1 for ground stations, 0 for satellites. |
wireLengthMeters |
≥ 0. 0 sizes the template for the operating frequency. |
necDeck |
Optional NEC-2 deck, at most 262,144 bytes; replaces the template. Satellite decks must not contain a GN card. Read responses add necDeckSha256, the hex SHA-256 of the deck.
|
mount |
FIXED (default), AZ or AZEL.
|
pointing |
Steerable mounts only: mode (FIXED or TRACK), azimuthDeg (−360 to 360), elevationDeg (−90 to 90), targetStationId (required for TRACK), azimuthRateDegPerSec and elevationRateDegPerSec (0 to 360; 0 = default). A FIXED mount stores no pointing. See SimTX API/Tracking and pointing.
|
A rig is a saved radio profile: rigId, name, revision, paMaxWatts (0 to 10,000,000; default 100), noiseFigureDb (0 to 100; default 6), and tx, an object with the fifteen transmitter imperfection values in camelCase (finalDriveDb, paHeadroomDb, audioCompressionDb, paSoftness, paAmPmDeg, carrierLeakDb, oppositeSidebandSuppressionDb, frequencyOffsetHz, mainsHumDb, mainsHumHz, amModulationIndex, paSupplySagDb, txNoiseFloorDb, oscillatorPhaseNoiseDb, cwKeyRiseMs). Values left out take the generic HF preset.
Orbit and attitude
orbit holds the mean elements of the simtx-j2-v1 model: model (simtx-j2-v1), epoch (read-only), semiMajorAxisKm, eccentricity, inclinationDeg, raanDeg, argumentOfPerigeeDeg, meanAnomalyDeg.
attitude has a mode of NADIR, INERTIAL or SPIN and the fields of that mode: yawDeg; rightAscensionDeg, declinationDeg (−90 to 90), rollDeg; or spinAxis (NADIR, ORBIT_NORMAL, VELOCITY), spinRateRpm (0 to 60), spinPhaseDeg. See Attitude.
Listing stations
GET /api/v1/stations returns the account's stations, ground and satellite, including deorbited satellites that have not been deleted.
curl -s https://auth.simtx.net/api/v1/stations -H "Authorization: Bearer $SIMTX_TOKEN"
Creating a ground station
POST /api/v1/stations
{
"name": "Home",
"callsign": "N0CALL",
"visibility": "UNLISTED",
"location": { "latitudeDeg": 47.4979, "longitudeDeg": 19.0402, "altitudeMeters": 120.0 },
"antennas": [ { "name": "40 m dipole", "type": "DIPOLE", "heightMeters": 10.0, "azimuthDeg": 90.0 } ],
"rigs": [ { "name": "100 W transceiver", "paMaxWatts": 100.0, "noiseFigureDb": 6.0 } ]
}
name, callsign, location and at least one antenna are required. visibility defaults to UNLISTED, limits to 16 sessions, 4 transmitters and 16 receivers before clamping. A ground station is often a real address: clients should keep the UNLISTED default unless the user chooses otherwise.
Reading, editing and deleting
GET /api/v1/stations/{id}returns one station. Another account's station is404 station_not_found.PATCH /api/v1/stations/{id}takes any ofname,callsign,visibility,limitsand, for ground stations,location. Omitted fields keep their values. There is no cooldown on location changes.DELETE /api/v1/stations/{id}deletes a ground station, or a satellite that has reentered (DEORBITED). An active or deorbiting satellite is refused with409 satellite_active.
Every edit increases the station's revision. Sessions bound to the station either continue with the new values or end; see Edits while sessions run.
Antennas and rigs
Ground stations only; a launched satellite is sealed.
POST /api/v1/stations/{id}/antennasadds an antenna (at most 8).PATCH .../antennas/{antennaId}changes one; omitted fields keep their values.DELETE .../antennas/{antennaId}removes one; the last antenna cannot be removed (409 last_antenna).POST /api/v1/stations/{id}/rigsadds a rig (at most 8).PATCH .../rigs/{rigId}changes one; atxobject replaces the stored imperfection values as a whole.DELETE .../rigs/{rigId}removes one.
Each returns the whole station.
Launching a satellite
POST /api/v1/satellites
{
"name": "SimSat-1",
"callsign": "SSAT1",
"visibility": "PUBLIC",
"orbit": {
"model": "simtx-j2-v1",
"semiMajorAxisKm": 6921.0, "eccentricity": 0.001, "inclinationDeg": 97.6,
"raanDeg": 120.0, "argumentOfPerigeeDeg": 90.0, "meanAnomalyDeg": 10.0
},
"attitude": { "mode": "NADIR", "yawDeg": 0.0 },
"antennas": [ { "name": "70 cm turnstile", "type": "TURNSTILE" } ],
"rigs": [ { "name": "Beacon", "paMaxWatts": 2.0, "noiseFigureDb": 2.0 } ]
}
name,callsign,orbitand 1 to 4 antennas are required; up to 8 rigs.- The orbit is sent without
epoch. The account service sets the epoch to the launch instant and interprets the elements at that instant. - The orbit must pass validation: model
simtx-j2-v1, perigee at least 200 km and apogee at most 40,000 km above the 6,371 km sphere, 0 ≤ e < 1, 0 ≤ i ≤ 180°, finite angles, spin rate 0 to 60 rpm. - Satellite antennas are modelled in free space; their NEC decks must not contain a
GNcard. - After launch the satellite is sealed: only
name,callsign,visibilityandlimitscan change. Changes to the orbit, attitude, antennas or rigs are refused with409 station_sealed.
Deorbiting
POST /api/v1/stations/{id}/deorbit/previewreturns theDeorbitobject that a burn fired now would produce, without changing anything. It needs no particular scope. Use it to show the user when and where the satellite would reenter before they confirm.POST /api/v1/stations/{id}/deorbitfires the burn and returns the station, nowDEORBITING, with itsorbitreplaced by the post-burn elements (epoch = burn time) anddeorbitset. The burn is irreversible.
{
"burnAt": "2026-10-24T12:00:00Z",
"reentryAt": "2026-10-24T12:29:00Z",
"reentryLocation": { "latitudeDeg": -12.3, "longitudeDeg": 101.7, "altitudeMeters": 80000.0 },
"deltaVMps": 189.0,
"orbit": {
"model": "simtx-j2-v1", "epoch": "2026-10-24T12:00:00Z",
"semiMajorAxisKm": 6596.0, "eccentricity": 0.0493, "inclinationDeg": 97.6,
"raanDeg": 120.4, "argumentOfPerigeeDeg": 270.0, "meanAnomalyDeg": 180.0
}
}
| Field | Description |
|---|---|
burnAt |
When the burn fires (or fired). |
reentryAt |
The first time after the burn that the height drops below 80 km. Sessions on the satellite end then, and it becomes DEORBITED.
|
reentryLocation |
The sub-satellite point at reentryAt; altitudeMeters is the 80 km interface.
|
deltaVMps |
Velocity change of the burn, m/s. |
orbit |
The exact post-burn elements (epoch = burnAt) that the service stores, or would store. Draw the fall from them; do not re-plan the burn.
|
The values in the example are illustrative. Deorbiting a satellite that is already deorbiting is refused with 409 already_deorbiting, one that has reentered with 409 station_inactive, and a ground station with 400 station_invalid. See Deorbit.
Quotas
The number of stations an account may own is capped by numeric capabilities of the account: game.owned_stations.N for all active stations, ground and satellite, and game.owned_satellites.N for active satellites. Deorbiting satellites count until they reenter. game.station_sessions.N caps a station's session limits. Defaults: members 100, 25 and 16; supporters 500, 100 and 64. There are no cooldowns. A creation over a quota is refused with 409 station_quota_exceeded, with fieldErrors.capability and fieldErrors.limit.
Errors
| HTTP | code |
Meaning |
|---|---|---|
| 400 | station_invalid |
A field is invalid; message and fieldErrors name it.
|
| 403 | scope_required |
The credential's scope lacks station.manage.
|
| 403 | permission_denied |
The account lacks station.manage.
|
| 403 | account_credential_required |
A service credential was used. |
| 404 | station_not_found |
Unknown station, or not yours. |
| 409 | station_sealed |
The change would modify a launched satellite. |
| 409 | station_inactive |
The satellite has reentered. |
| 409 | last_antenna |
A station keeps at least one antenna. |
| 409 | station_quota_exceeded |
fieldErrors name the capability and its limit.
|
| 409 | satellite_active |
Delete refused; deorbit the satellite and wait for its reentry first. |
| 409 | already_deorbiting |
The burn has already fired. |
| 413 | request_too_large |
The body is over 2 MiB. |