REST API

HTTP/JSON API for client-server communication.

Base URL

  • Production: https://galaxy.example.com/api
  • Development: https://localhost:30002/api

Authentication

Authenticated endpoints require the Authorization header:

Authorization: Bearer <jwt_token>

Common Response Format

Success

Returns appropriate HTTP status code with JSON body (if applicable).

Error

All errors return JSON with error code and message:

{
  "error": {
    "code": "E005",
    "message": "Authentication failed"
  }
}

Endpoints

POST /api/auth/register

Create a new player account.

Request:

{
  "username": "PlayerOne",
  "password": "securepassword123"
}
Field Type Validation
username string 3-20 characters, alphanumeric + underscore, unique
password string Minimum 8 characters

Response (201 Created):

{
  "player_id": "550e8400-e29b-41d4-a716-446655440000",
  "username": "PlayerOne",
  "ship_id": "660e8400-e29b-41d4-a716-446655440001",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Errors:

Status Code Condition
400 E011 Invalid username format
400 E012 Password too short
403 E020 Registration is currently closed
409 E010 Username already taken
500 E008 Server error

POST /api/auth/login

Authenticate and receive JWT token.

Request:

{
  "username": "PlayerOne",
  "password": "securepassword123"
}

Response (200 OK):

{
  "player_id": "550e8400-e29b-41d4-a716-446655440000",
  "username": "PlayerOne",
  "ship_id": "660e8400-e29b-41d4-a716-446655440001",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "is_admin": false
}

Notes:

  • is_admin is included in the response. For admin accounts, this is true.
  • ship_id may be empty string for ship-less admin accounts.
  • This endpoint works for both regular players and admins (unified login).

Errors:

Status Code Condition
401 E005 Invalid username or password
429 E004 Rate limit exceeded (5 attempts/min)
500 E008 Server error

Security notes:

  • Response is identical for wrong username vs wrong password (no enumeration)
  • Rate limited to 5 attempts per minute per IP

DELETE /api/account

Delete the authenticated player’s account.

Headers:

Authorization: Bearer <token>

Response (204 No Content)

No response body.

Errors:

Status Code Condition
401 E005 Invalid or expired token
500 E008 Server error

Side effects:

  • Player’s ship is immediately removed from the game
  • Username becomes available for reuse
  • Action is irreversible

GET /api/player/ship

Get the authenticated player’s current ship state.

Headers:

Authorization: Bearer <token>

Response (200 OK):

{
  "ship_id": "660e8400-e29b-41d4-a716-446655440001",
  "position": {"x": 1.496e11, "y": 0.0, "z": 6771000.0},
  "velocity": {"x": 0.0, "y": 29780.0, "z": 7672.0},
  "attitude": {"w": 1.0, "x": 0.0, "y": 0.0, "z": 0.0},
  "angular_velocity": {"x": 0.0, "y": 0.0, "z": 0.0},
  "thrust_level": 0.0,
  "fuel": 10000.0,
  "fuel_capacity": 10000.0,
  "mass": 20000.0,
  "wheel_saturation": {"x": 0.0, "y": 0.0, "z": 0.0}
}

Errors:

Status Code Condition
401 E005 Invalid or expired token
404 E006 Ship not found
500 E008 Server error

Notes:

  • wheel_saturation is normalized (0.0–1.0 per axis), derived from wheel_momentum / wheel_capacity
  • State is a snapshot at request time; use WebSocket for real-time updates

GET /api/status

Get server status (unauthenticated).

Response (200 OK):

{
  "status": "online",
  "server_name": "Galaxy",
  "tick": 123456,
  "game_time": "2025-01-15T10:30:00Z",
  "players_online": 5,
  "paused": false,
  "time_sync_enabled": true,
  "time_drift_seconds": 3.5,
  "effective_time_scale": 1.0,
  "registration_open": true
}

Data sources:

Field Source
status “online” if api-gateway is serving requests
server_name SERVER_NAME env var (default "Galaxy")
tick Redis game:tick
game_time Redis game:time
players_online Redis SCARD connections:online
paused Redis game:paused
time_sync_enabled tick-engine gRPC TickStatus.time_sync_enabled
time_drift_seconds tick-engine gRPC TickStatus.time_drift_seconds
effective_time_scale tick-engine gRPC TickStatus.effective_time_scale
registration_open Redis game:registration_open (default true if absent)

Admin Endpoints

Admin endpoints require a valid admin JWT token.

POST /api/admin/auth/login

Authenticate as administrator. Routes through the unified players.Authenticate gRPC call, then checks is_admin on the response.

Legacy alias: /api/admin/login is also supported for backward compatibility. Note: Admins can also log in via /api/auth/login (the unified player login). This endpoint exists for backward compatibility with the admin dashboard.

Request:

{
  "username": "admin",
  "password": "adminpassword"
}

Response (200 OK):

{
  "success": true,
  "admin_id": "770e8400-e29b-41d4-a716-446655440002",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "role": "admin",
  "is_admin": true
}

Errors:

Status Code Condition
401 E005 Invalid credentials or not an admin
429 E004 Rate limit exceeded

GET /api/admin/players

List all registered players.

Headers:

Authorization: Bearer <admin_token>

Response (200 OK):

{
  "players": [
    {
      "player_id": "550e8400-e29b-41d4-a716-446655440000",
      "username": "PlayerOne",
      "ship_id": "660e8400-e29b-41d4-a716-446655440001",
      "created_at": "2025-01-10T08:00:00Z",
      "online": true
    }
  ]
}

Errors:

Status Code Condition
401 E005 Invalid or expired admin token

DELETE /api/admin/players/{player_id}

Delete a player account (admin action).

Headers:

Authorization: Bearer <admin_token>

Response (204 No Content)

Errors:

Status Code Condition
401 E005 Invalid or expired admin token
404 E009 Player not found

Side effects:

  • If player is connected, they receive E014 and are disconnected
  • Ship is removed immediately

POST /api/admin/players/{player_id}/reset-password

Reset a player’s password.

Headers:

Authorization: Bearer <admin_token>

Request:

{
  "new_password": "temporarypassword123"
}

Response (200 OK):

{
  "message": "Password reset successfully"
}

Errors:

Status Code Condition
400 E012 Password too short
401 E005 Invalid or expired admin token
404 E009 Player not found

Admin provides the new password to the player out-of-band.


PUT /api/admin/players/{player_id}/role

Promote a player to admin or demote an admin to player.

Headers:

Authorization: Bearer <admin_token>

Request:

{
  "is_admin": true
}
Field Type Description
is_admin boolean true to promote to admin, false to demote to player

Response (200 OK):

{
  "success": true
}

Errors:

Status Code Condition
400 - Cannot change own admin role
400 - Player service returned error
401 E005 Invalid or expired admin token

Constraints:

  • Admins cannot change their own role (self-demotion is blocked)
  • Promoted players keep their existing ship
  • Demoted admins with no ship cannot log in normally until a ship is assigned

GET /api/admin/status

Get current game status including tick info, rates, drift, and sync state.

Headers:

Authorization: Bearer <admin_token>

Response (200 OK):

{
  "current_tick": 123456,
  "tick_rate": 1.0,
  "time_scale": 1.0,
  "actual_rate": 0.998,
  "paused": false,
  "ticks_behind": 0,
  "game_time": "2025-01-15T10:30:00+00:00",
  "energy_drift": 1.2e-8,
  "momentum_drift": 3.4e-9,
  "time_sync_enabled": true,
  "time_drift_seconds": 0.5,
  "effective_time_scale": 1.002,
  "adaptive_tick_rate": false,
  "registration_open": true
}
Field Type Description
current_tick integer Current tick number
tick_rate number Configured ticks per second
time_scale number Configured time scale multiplier
actual_rate number Actual achieved tick rate
paused boolean Whether tick processing is paused
ticks_behind integer Number of ticks behind schedule (0 = healthy)
game_time string Current game time (ISO 8601)
energy_drift number Relative energy drift (dE/E0)
momentum_drift number Relative angular momentum drift (dL/L0)
time_sync_enabled boolean Whether time sync to UTC is active
time_drift_seconds number Game time drift from wall-clock UTC (seconds)
effective_time_scale number Actual time scale after sync adjustment
adaptive_tick_rate boolean Whether adaptive tick rate is enabled
registration_open boolean Whether new player registrations are allowed

Errors:

Status Code Condition
401 E005 Invalid or expired admin token
500 E008 gRPC failure communicating with tick-engine

POST /api/admin/game/pause

Pause tick processing.

Response (200 OK):

{
  "paused": true,
  "paused_at_tick": 123456
}

POST /api/admin/game/resume

Resume tick processing.

Response (200 OK):

{
  "paused": false,
  "resumed_at_tick": 123456
}

PUT /api/admin/game/tick-rate

Set tick rate.

Request:

{
  "tick_rate": 2.0
}

Response (200 OK):

{
  "previous_rate": 1.0,
  "new_rate": 2.0
}

Errors:

Status Code Condition
400 E015 Invalid tick rate (outside 0.1-100.0 range, or zero)

PUT /api/admin/game/time-scale

Set time scale (game speed multiplier).

Request:

{
  "time_scale": 10.0
}

Response (200 OK):

{
  "previous_scale": 1.0,
  "new_scale": 10.0
}

Errors:

Status Code Condition
400 E029 Invalid time scale (outside 0.1-100.0 range, or zero)

POST /api/admin/game/time-sync

Toggle game time synchronization to wall-clock UTC.

Request:

{
  "enabled": true
}

Response (200 OK):

{
  "success": true,
  "previous": false,
  "current": true
}

When enabled and admin time_scale ≈ 1.0, the tick engine adjusts effective time scale (±5% max) to converge game time to UTC. See Game Time Synchronization for details.


POST /api/admin/game/adaptive-tick-rate

Toggle adaptive tick rate. When enabled, the tick engine automatically adjusts tick rate based on processing utilization (target 70%, range 0.5–10 Hz).

Request:

{
  "enabled": true
}

Response (200 OK):

{
  "success": true,
  "adaptive_tick_rate": true
}

Errors:

Status Code Condition
401 E005 Invalid or expired admin token
500 E008 gRPC failure communicating with tick-engine

GET /api/admin/systems

List all star systems with dynamic entity counts.

Headers:

Authorization: Bearer <admin_token>

Response (200 OK):

{
  "systems": [
    {
      "id": "sol",
      "name": "Sol",
      "star_body": "Sun",
      "position": {"x": 0.0, "y": 0.0, "z": 0.0},
      "body_count": 10,
      "player_count": 3
    }
  ]
}
Field Type Description
id string System identifier
name string Display name
star_body string Primary star body name
position vec3 Galactic position (meters)
body_count integer Number of celestial bodies (from Redis system:{id}:bodies set)
player_count integer Number of ships in system (from Redis system:{id}:ships set)

Errors:

Status Code Condition
401 E005 Invalid or expired admin token
500 E008 gRPC failure communicating with galaxy service

POST /api/admin/ship/{ship_id}/system

Move a ship to a different star system (admin testing tool). Updates the ship’s system_id in Redis and moves it between system ship sets.

Path Parameters:

Parameter Type Description
ship_id string UUID of the ship to move

Request:

{
  "system_id": "alpha_centauri"
}

Response (200 OK):

{
  "success": true,
  "previous_system": "sol",
  "new_system": "alpha_centauri"
}

Errors:

Status Code Condition
400 - system_id is required, unknown system, or ship already in that system
401 E005 Invalid or expired admin token
404 - Ship not found

POST /api/admin/registrations

Set whether new player registrations are allowed.

Headers:

Authorization: Bearer <admin_token>

Request:

{
  "open": true
}

Response (200 OK):

{
  "success": true,
  "registration_open": true
}

Errors:

Status Code Condition
401 E005 Invalid or expired admin token

GET /api/admin/registrations

Get current registration status.

Headers:

Authorization: Bearer <admin_token>

Response (200 OK):

{
  "registration_open": true
}

Errors:

Status Code Condition
401 E005 Invalid or expired admin token

POST /api/admin/registrations/enable

Enable new player registrations. Sets game:registration_open to "true" in Redis.

Headers:

Authorization: Bearer <admin_token>

Response (200 OK):

{
  "success": true,
  "registration_open": true
}

Errors:

Status Code Condition
401 E005 Invalid or expired admin token

POST /api/admin/registrations/disable

Disable new player registrations. Sets game:registration_open to "false" in Redis. Players who attempt to register while registrations are disabled receive error E020.

Headers:

Authorization: Bearer <admin_token>

Response (200 OK):

{
  "success": true,
  "registration_open": false
}

Errors:

Status Code Condition
401 E005 Invalid or expired admin token

POST /api/admin/game/reset

Factory reset the game (destructive). Wipes all ships, player accounts, automation rules, maneuvers, game config, and snapshots. A backup is created before destruction.

Headers:

Authorization: Bearer <admin_token>

Response (200 OK):

{
  "success": true,
  "game_time": "2025-01-15T10:30:00+00:00",
  "backup_id": "20250115T103000Z",
  "restart_required": true
}
Field Type Description
success boolean Whether the reset succeeded
game_time string New game time after reset (ISO 8601, current UTC)
backup_id string Identifier for the pre-reset backup
restart_required boolean Whether services should be restarted for clean state

Side effects:

  • Admin account is automatically re-bootstrapped from env vars (no restart needed for admin access)
  • All player WebSocket connections remain open but subsequent commands return E006

Errors:

Status Code Condition
401 E005 Invalid or expired admin token
500 E008 gRPC failure or reset error

POST /api/admin/snapshot

Create a manual snapshot.

Response (200 OK):

{
  "success": true,
  "snapshot_id": 42,
  "tick_number": 123456
}

GET /api/admin/snapshots

List available snapshots.

Response (200 OK):

{
  "snapshots": [
    {
      "id": 42,
      "tick_number": 123456,
      "game_time": "2000-01-01T12:00:00+00:00",
      "created_at": "2025-01-15T10:30:00+00:00"
    }
  ]
}

POST /api/admin/restore

Restore game state from a snapshot.

Request:

{
  "snapshot_id": 42
}

Response (200 OK):

{
  "success": true,
  "tick_number": 123456,
  "game_time": "2000-01-01T12:00:00+00:00"
}

Errors:

Status Code Condition
404 E016 Snapshot not found

POST /api/admin/admins

Create a new admin account.

Headers:

Authorization: Bearer <admin_token>

Request:

{
  "username": "newadmin",
  "password": "securepassword123"
}

Response (201 Created):

{
  "admin_id": "880e8400-e29b-41d4-a716-446655440003",
  "username": "newadmin"
}

Errors:

Status Code Condition
400 E011 Invalid username format
400 E012 Password too short
409 E010 Username already taken

DELETE /api/admin/admins/{admin_id}

Delete an admin account.

Headers:

Authorization: Bearer <admin_token>

Response (204 No Content)

Errors:

Status Code Condition
400 - Cannot delete self
404 E009 Admin not found

PUT /api/admin/admins/{admin_id}/password

Change an admin’s password.

Headers:

Authorization: Bearer <admin_token>

Request:

{
  "new_password": "newsecurepassword123"
}

Response (200 OK):

{
  "message": "Password changed successfully"
}

Notes:

  • Admins can change their own password or another admin’s password
  • Changing own password does not invalidate current token

Errors:

Status Code Condition
400 E012 Password too short
404 E009 Admin not found

GET /api/admin/admins

List all admin accounts.

Headers:

Authorization: Bearer <admin_token>

Response (200 OK):

{
  "admins": [
    {
      "admin_id": "770e8400-e29b-41d4-a716-446655440002",
      "username": "admin",
      "created_at": "2025-01-01T00:00:00Z"
    }
  ]
}

POST /api/admin/station

Spawn a new station. Supports two modes: equatorial orbit (specify altitude) or Lagrange point placement.

Headers:

Authorization: Bearer <admin_token>

Request (equatorial orbit):

{
  "name": "Gateway Station",
  "parent_body": "Earth",
  "altitude": 5500000
}
Field Type Required Description
name string yes Station display name
parent_body string yes Reference body name (e.g., “Earth”)
altitude number conditional Altitude above body surface in meters (required for equatorial orbit mode)

Request (Lagrange point):

{
  "name": "Frontier Outpost",
  "parent_body": "Earth",
  "secondary_body": "Luna",
  "lagrange_point": 5
}
Field Type Required Description
name string yes Station display name
parent_body string yes Primary body name
secondary_body string conditional Secondary body name (required for Lagrange point mode)
lagrange_point integer conditional Lagrange point number 1–5 (required for Lagrange point mode)

Response (200 OK):

{
  "success": true,
  "station_id": "990e8400-e29b-41d4-a716-446655440004",
  "station": {
    "station_id": "990e8400-e29b-41d4-a716-446655440004",
    "name": "Gateway Station",
    "position": {"x": 1.496e11, "y": 0.0, "z": 1.1871e7},
    "velocity": {"x": 0.0, "y": 29780.0, "z": 5790.0},
    "attitude": {"w": 1.0, "x": 0.0, "y": 0.0, "z": 0.0},
    "mass": 420000,
    "radius": 50,
    "parent_body": "Earth"
  }
}

Errors:

Status Code Condition
400 - Invalid parameters (missing fields, unknown body, invalid Lagrange point)
401 E005 Invalid or expired admin token
500 E008 gRPC failure communicating with physics service

DELETE /api/admin/station/{station_id}

Remove a station.

Headers:

Authorization: Bearer <admin_token>

Response (204 No Content)

Errors:

Status Code Condition
401 E005 Invalid or expired admin token
404 - Station not found
500 E008 gRPC failure communicating with physics service

GET /api/admin/stations

List all stations.

Headers:

Authorization: Bearer <admin_token>

Response (200 OK):

{
  "stations": [
    {
      "station_id": "990e8400-e29b-41d4-a716-446655440004",
      "name": "Gateway Station",
      "position": {"x": 1.496e11, "y": 0.0, "z": 1.1871e7},
      "velocity": {"x": 0.0, "y": 29780.0, "z": 5790.0},
      "attitude": {"w": 1.0, "x": 0.0, "y": 0.0, "z": 0.0},
      "mass": 420000,
      "radius": 50,
      "parent_body": "Earth"
    }
  ]
}

Errors:

Status Code Condition
401 E005 Invalid or expired admin token

POST /api/admin/jumpgate

Spawn a new jump gate at a Lagrange point.

Headers:

Authorization: Bearer <admin_token>

Request:

{
  "name": "Earth-Luna L4 Gate",
  "primary_body": "Earth",
  "secondary_body": "Luna",
  "lagrange_point": 4
}
Field Type Required Description
name string yes Jump gate display name (non-empty)
primary_body string yes Primary body name (non-empty)
secondary_body string yes Secondary body name (non-empty)
lagrange_point integer no Lagrange point number 1–5 (default: 4)

All fields are validated server-side via Pydantic (SpawnJumpGateRequest model). Missing required fields or invalid lagrange_point values return 422.

Response (200 OK):

{
  "success": true,
  "jumpgate_id": "aa0e8400-e29b-41d4-a716-446655440005",
  "jumpgate": {
    "jumpgate_id": "aa0e8400-e29b-41d4-a716-446655440005",
    "name": "Earth-Luna L4 Gate",
    "position": {"x": 1.496e11, "y": 0.0, "z": 0.0},
    "velocity": {"x": 0.0, "y": 29780.0, "z": 0.0},
    "mass": 100000,
    "radius": 25,
    "parent_body": "Earth"
  }
}

Errors:

Status Code Condition
400 - Invalid parameters (missing fields, unknown body, invalid Lagrange point)
401 E005 Invalid or expired admin token
500 E008 gRPC failure communicating with physics service

DELETE /api/admin/jumpgate/{jumpgate_id}

Remove a jump gate.

Headers:

Authorization: Bearer <admin_token>

Response (204 No Content)

Errors:

Status Code Condition
401 E005 Invalid or expired admin token
404 - Jump gate not found
500 E008 gRPC failure communicating with physics service

GET /api/admin/jumpgates

List all jump gates.

Headers:

Authorization: Bearer <admin_token>

Response (200 OK):

{
  "jumpgates": [
    {
      "jumpgate_id": "aa0e8400-e29b-41d4-a716-446655440005",
      "name": "Earth-Luna L4 Gate",
      "position": {"x": 1.496e11, "y": 0.0, "z": 0.0},
      "velocity": {"x": 0.0, "y": 29780.0, "z": 0.0},
      "mass": 100000,
      "radius": 25,
      "parent_body": "Earth"
    }
  ]
}

Errors:

Status Code Condition
401 E005 Invalid or expired admin token

Maneuver Logging Endpoints

GET /api/admin/maneuver-logging

Get the current global maneuver logging level.

Headers:

Authorization: Bearer <admin_token>

Response (200 OK):

{
  "level": "normal"
}
Field Type Description
level string Current logging level: "verbose", "normal", or "off"

Errors:

Status Code Condition
401 E005 Invalid or expired admin token

POST /api/admin/maneuver-logging

Set the global maneuver logging level.

Headers:

Authorization: Bearer <admin_token>

Request:

{
  "level": "verbose"
}
Field Type Description
level string "verbose", "normal", or "off"

Response (200 OK):

{
  "success": true,
  "level": "verbose"
}

Errors:

Status Code Condition
400 - Invalid level value
401 E005 Invalid or expired admin token

WebSocket Messages

ship_rename

Rename the player’s ship. The new name propagates to all clients via the next tick broadcast.

Client sends:

{
  "type": "ship_rename",
  "name": "My Ship Name"
}
Field Type Validation
name string 3-32 characters after whitespace trim, non-empty

Server responds (success):

{
  "type": "ship_renamed",
  "name": "My Ship Name"
}

Server responds (validation failure):

{
  "type": "error",
  "code": "E030",
  "message": "Ship name must be 3-32 characters"
}

Implementation notes:

  • api-gateway writes directly to Redis ship:{ship_id} hash name field
  • No gRPC call needed — physics reads name from Redis each tick
  • Name appears in tick broadcasts via ShipState.name automatically

Client-Side Security

Client code must never interpolate server-provided strings (body names, player usernames, ship IDs) directly into innerHTML. Use textContent for plain text, or escape &, <, >, ", and ' as HTML entities before inserting into HTML markup. This applies to all server-provided data regardless of server-side validation, as a defense-in-depth measure.


JWT Token Security

Token Generation

Token Type Generated By Description
Player players service On successful login or registration
Admin api-gateway On successful admin login

Signing key:

  • Algorithm: HS256 (HMAC-SHA256)
  • Key source: Kubernetes Secret (galaxy-secrets)
  • Key environment variable: JWT_SECRET_KEY
  • Key length: Minimum 256 bits (32 bytes)
  • Key rotation: Not supported in initial release (requires redeployment)
  • Startup validation: Services must fail fast at startup if JWT_SECRET_KEY is not set or is shorter than 32 bytes. This prevents silent operation with an empty or weak signing key.

Configuration security:

Sensitive configuration fields (jwt_secret_key, postgres_password, database_url, ssl_keyfile) must be excluded from log output and object repr. Services must use Field(repr=False) on sensitive Pydantic settings fields and must not log connection URLs that embed credentials.

Services that need the signing key:

Service Usage
players Signs player JWTs
api-gateway Signs admin JWTs, validates all JWTs

Token validation:

The api-gateway validates all incoming JWTs:

  1. Check signature using shared secret
  2. Check expiry (exp claim)
  3. Check token type (type claim matches expected)
  4. Extract claims (sub, ship_id for players)

Invalid tokens return E005 error.

JWT Token Structure

Player Token

{
  "sub": "550e8400-e29b-41d4-a716-446655440000",
  "type": "player",
  "ship_id": "660e8400-e29b-41d4-a716-446655440001",
  "iat": 1705315800,
  "exp": 1705402200
}
Claim Description
sub Player UUID
type “player”
ship_id Player’s ship UUID
iat Issued at (Unix timestamp)
exp Expires at (24 hours after issue)

Admin Token

{
  "sub": "770e8400-e29b-41d4-a716-446655440002",
  "type": "admin",
  "iat": 1705315800,
  "exp": 1705402200
}
Claim Description
sub Admin UUID
type “admin”
iat Issued at (Unix timestamp)
exp Expires at (24 hours after issue)

Maneuver Diagnostics Endpoints

GET /api/admin/maneuver-events

Query persistent maneuver lifecycle events from PostgreSQL. Uses AdminAuth.fetch() for database access (not private pool attribute).

Headers:

Authorization: Bearer <admin_token>

Query Parameters:

Parameter Type Required Default Description
ship_id uuid no - Filter by ship
event_type string no - Filter by event type
limit integer no 50 Max rows (1-500)

Response (200 OK):

{
  "events": [
    {
      "id": 1,
      "ship_id": "660e8400-e29b-41d4-a716-446655440001",
      "maneuver_type": "rendezvous",
      "event_type": "maneuver_started",
      "phase": "plane_change",
      "from_phase": null,
      "tick": 123456,
      "game_time": "2025-01-15T10:30:00+00:00",
      "element_errors": null,
      "distance": null,
      "effectivity": null,
      "status_text": null,
      "extra": {"ref_body": "Earth", "target_id": "..."},
      "created_at": "2025-01-15T10:30:00+00:00"
    }
  ]
}

Errors:

Status Code Condition
401 E005 Invalid or expired admin token

GET /api/admin/maneuver-debug

Get per-ship maneuver debug flag.

Headers:

Authorization: Bearer <admin_token>

Query Parameters:

Parameter Type Required Description
ship_id uuid yes Ship to query

Response (200 OK):

{
  "ship_id": "660e8400-e29b-41d4-a716-446655440001",
  "debug": true
}

POST /api/admin/maneuver-debug

Toggle per-ship maneuver diagnostic logging.

Headers:

Authorization: Bearer <admin_token>

Request:

{
  "ship_id": "660e8400-e29b-41d4-a716-446655440001",
  "enabled": true
}

Response (200 OK):

{
  "success": true,
  "ship_id": "660e8400-e29b-41d4-a716-446655440001",
  "debug": true
}

Back to top

Galaxy — Kubernetes-based multiplayer space game

This site uses Just the Docs, a documentation theme for Jekyll.