{
  "components": {
    "schemas": {
      "BookingWindow": {
        "description": "Redacted cross-org busy window for ``GET /stations/booking-windows``.\n\nDeliberately carries NO satellite/org/user/booking-id fields \u2014 only\nenough to render a busy/free strip across every station the caller can\naccess, across ALL orgs. ``mine`` is the only ownership signal.",
        "properties": {
          "aos": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Acquisition of signal, ISO 8601 UTC.",
            "title": "Aos"
          },
          "enforce_turnaround": {
            "description": "Whether this booking enforces the turnaround buffer.",
            "title": "Enforce Turnaround",
            "type": "boolean"
          },
          "los": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Loss of signal, ISO 8601 UTC.",
            "title": "Los"
          },
          "mine": {
            "description": "True when this booking belongs to one of the caller's groups.",
            "title": "Mine",
            "type": "boolean"
          },
          "station_client_id": {
            "description": "Station tenant client identifier.",
            "title": "Station Client Id",
            "type": "string"
          }
        },
        "required": [
          "station_client_id",
          "enforce_turnaround",
          "mine"
        ],
        "title": "BookingWindow",
        "type": "object"
      },
      "BookingWindows": {
        "properties": {
          "windows": {
            "items": {
              "$ref": "#/components/schemas/BookingWindow"
            },
            "title": "Windows",
            "type": "array"
          }
        },
        "required": [
          "windows"
        ],
        "title": "BookingWindows",
        "type": "object"
      },
      "Envelope_BookingWindows_": {
        "properties": {
          "data": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BookingWindows"
              },
              {
                "type": "null"
              }
            ],
            "description": "Operation-specific payload. ``null`` on errors."
          },
          "message": {
            "description": "Human-readable summary.",
            "title": "Message",
            "type": "string"
          },
          "request_id": {
            "description": "UUID4 echoed from the request middleware. Also returned in the X-Request-ID header.",
            "title": "Request Id",
            "type": "string"
          },
          "status": {
            "description": "Outcome marker. ``ok`` on 200/207 success paths; ``error`` on 4xx/5xx.",
            "enum": [
              "ok",
              "error"
            ],
            "title": "Status",
            "type": "string"
          },
          "timestamp": {
            "description": "Server time at response, ms since epoch.",
            "title": "Timestamp",
            "type": "integer"
          }
        },
        "required": [
          "status",
          "message",
          "request_id",
          "timestamp"
        ],
        "title": "Envelope[BookingWindows]",
        "type": "object"
      },
      "Envelope_Dict_str__Any__": {
        "properties": {
          "data": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Operation-specific payload. ``null`` on errors.",
            "title": "Data"
          },
          "message": {
            "description": "Human-readable summary.",
            "title": "Message",
            "type": "string"
          },
          "request_id": {
            "description": "UUID4 echoed from the request middleware. Also returned in the X-Request-ID header.",
            "title": "Request Id",
            "type": "string"
          },
          "status": {
            "description": "Outcome marker. ``ok`` on 200/207 success paths; ``error`` on 4xx/5xx.",
            "enum": [
              "ok",
              "error"
            ],
            "title": "Status",
            "type": "string"
          },
          "timestamp": {
            "description": "Server time at response, ms since epoch.",
            "title": "Timestamp",
            "type": "integer"
          }
        },
        "required": [
          "status",
          "message",
          "request_id",
          "timestamp"
        ],
        "title": "Envelope[Dict[str, Any]]",
        "type": "object"
      },
      "Envelope_ErrorPayload_": {
        "properties": {
          "data": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ErrorPayload"
              },
              {
                "type": "null"
              }
            ],
            "description": "Operation-specific payload. ``null`` on errors."
          },
          "message": {
            "description": "Human-readable summary.",
            "title": "Message",
            "type": "string"
          },
          "request_id": {
            "description": "UUID4 echoed from the request middleware. Also returned in the X-Request-ID header.",
            "title": "Request Id",
            "type": "string"
          },
          "status": {
            "description": "Outcome marker. ``ok`` on 200/207 success paths; ``error`` on 4xx/5xx.",
            "enum": [
              "ok",
              "error"
            ],
            "title": "Status",
            "type": "string"
          },
          "timestamp": {
            "description": "Server time at response, ms since epoch.",
            "title": "Timestamp",
            "type": "integer"
          }
        },
        "required": [
          "status",
          "message",
          "request_id",
          "timestamp"
        ],
        "title": "Envelope[ErrorPayload]",
        "type": "object"
      },
      "Envelope_PaginatedSatellites_": {
        "properties": {
          "data": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PaginatedSatellites"
              },
              {
                "type": "null"
              }
            ],
            "description": "Operation-specific payload. ``null`` on errors."
          },
          "message": {
            "description": "Human-readable summary.",
            "title": "Message",
            "type": "string"
          },
          "request_id": {
            "description": "UUID4 echoed from the request middleware. Also returned in the X-Request-ID header.",
            "title": "Request Id",
            "type": "string"
          },
          "status": {
            "description": "Outcome marker. ``ok`` on 200/207 success paths; ``error`` on 4xx/5xx.",
            "enum": [
              "ok",
              "error"
            ],
            "title": "Status",
            "type": "string"
          },
          "timestamp": {
            "description": "Server time at response, ms since epoch.",
            "title": "Timestamp",
            "type": "integer"
          }
        },
        "required": [
          "status",
          "message",
          "request_id",
          "timestamp"
        ],
        "title": "Envelope[PaginatedSatellites]",
        "type": "object"
      },
      "Envelope_PaginatedStations_": {
        "properties": {
          "data": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PaginatedStations"
              },
              {
                "type": "null"
              }
            ],
            "description": "Operation-specific payload. ``null`` on errors."
          },
          "message": {
            "description": "Human-readable summary.",
            "title": "Message",
            "type": "string"
          },
          "request_id": {
            "description": "UUID4 echoed from the request middleware. Also returned in the X-Request-ID header.",
            "title": "Request Id",
            "type": "string"
          },
          "status": {
            "description": "Outcome marker. ``ok`` on 200/207 success paths; ``error`` on 4xx/5xx.",
            "enum": [
              "ok",
              "error"
            ],
            "title": "Status",
            "type": "string"
          },
          "timestamp": {
            "description": "Server time at response, ms since epoch.",
            "title": "Timestamp",
            "type": "integer"
          }
        },
        "required": [
          "status",
          "message",
          "request_id",
          "timestamp"
        ],
        "title": "Envelope[PaginatedStations]",
        "type": "object"
      },
      "Envelope_SatelliteDetail_": {
        "properties": {
          "data": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SatelliteDetail"
              },
              {
                "type": "null"
              }
            ],
            "description": "Operation-specific payload. ``null`` on errors."
          },
          "message": {
            "description": "Human-readable summary.",
            "title": "Message",
            "type": "string"
          },
          "request_id": {
            "description": "UUID4 echoed from the request middleware. Also returned in the X-Request-ID header.",
            "title": "Request Id",
            "type": "string"
          },
          "status": {
            "description": "Outcome marker. ``ok`` on 200/207 success paths; ``error`` on 4xx/5xx.",
            "enum": [
              "ok",
              "error"
            ],
            "title": "Status",
            "type": "string"
          },
          "timestamp": {
            "description": "Server time at response, ms since epoch.",
            "title": "Timestamp",
            "type": "integer"
          }
        },
        "required": [
          "status",
          "message",
          "request_id",
          "timestamp"
        ],
        "title": "Envelope[SatelliteDetail]",
        "type": "object"
      },
      "Envelope_TleResponse_": {
        "properties": {
          "data": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TleResponse"
              },
              {
                "type": "null"
              }
            ],
            "description": "Operation-specific payload. ``null`` on errors."
          },
          "message": {
            "description": "Human-readable summary.",
            "title": "Message",
            "type": "string"
          },
          "request_id": {
            "description": "UUID4 echoed from the request middleware. Also returned in the X-Request-ID header.",
            "title": "Request Id",
            "type": "string"
          },
          "status": {
            "description": "Outcome marker. ``ok`` on 200/207 success paths; ``error`` on 4xx/5xx.",
            "enum": [
              "ok",
              "error"
            ],
            "title": "Status",
            "type": "string"
          },
          "timestamp": {
            "description": "Server time at response, ms since epoch.",
            "title": "Timestamp",
            "type": "integer"
          }
        },
        "required": [
          "status",
          "message",
          "request_id",
          "timestamp"
        ],
        "title": "Envelope[TleResponse]",
        "type": "object"
      },
      "Envelope_TransceiverPatchResult_": {
        "properties": {
          "data": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TransceiverPatchResult"
              },
              {
                "type": "null"
              }
            ],
            "description": "Operation-specific payload. ``null`` on errors."
          },
          "message": {
            "description": "Human-readable summary.",
            "title": "Message",
            "type": "string"
          },
          "request_id": {
            "description": "UUID4 echoed from the request middleware. Also returned in the X-Request-ID header.",
            "title": "Request Id",
            "type": "string"
          },
          "status": {
            "description": "Outcome marker. ``ok`` on 200/207 success paths; ``error`` on 4xx/5xx.",
            "enum": [
              "ok",
              "error"
            ],
            "title": "Status",
            "type": "string"
          },
          "timestamp": {
            "description": "Server time at response, ms since epoch.",
            "title": "Timestamp",
            "type": "integer"
          }
        },
        "required": [
          "status",
          "message",
          "request_id",
          "timestamp"
        ],
        "title": "Envelope[TransceiverPatchResult]",
        "type": "object"
      },
      "Envelope_TransceiverSnapshot_": {
        "properties": {
          "data": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TransceiverSnapshot"
              },
              {
                "type": "null"
              }
            ],
            "description": "Operation-specific payload. ``null`` on errors."
          },
          "message": {
            "description": "Human-readable summary.",
            "title": "Message",
            "type": "string"
          },
          "request_id": {
            "description": "UUID4 echoed from the request middleware. Also returned in the X-Request-ID header.",
            "title": "Request Id",
            "type": "string"
          },
          "status": {
            "description": "Outcome marker. ``ok`` on 200/207 success paths; ``error`` on 4xx/5xx.",
            "enum": [
              "ok",
              "error"
            ],
            "title": "Status",
            "type": "string"
          },
          "timestamp": {
            "description": "Server time at response, ms since epoch.",
            "title": "Timestamp",
            "type": "integer"
          }
        },
        "required": [
          "status",
          "message",
          "request_id",
          "timestamp"
        ],
        "title": "Envelope[TransceiverSnapshot]",
        "type": "object"
      },
      "ErrorPayload": {
        "description": "Structured error payload surfaced under ``data`` on /api/v1 errors.\n\nPhase 5 \u00a7E promotes the previous plain-string ``detail`` body into a\nmachine-matchable ``error_code`` plus a human-readable ``message``. SDKs\ncan switch on ``error_code`` instead of regex-matching the message text;\nthe string ``message`` stays for human readers and tooling that hasn't\nbeen updated yet.\n\nEndpoint-specific extras (e.g. the transceiver PATCH ``denied_fields``\nlist) land under ``extra`` so consumers can extract them without parsing\nthe message.",
        "properties": {
          "error_code": {
            "description": "Machine-matchable error code (snake_case).",
            "title": "Error Code",
            "type": "string"
          },
          "extra": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Endpoint-specific extras (e.g. denied_fields list).",
            "title": "Extra"
          },
          "message": {
            "description": "Human-readable detail.",
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "error_code",
          "message"
        ],
        "title": "ErrorPayload",
        "type": "object"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "title": "HTTPValidationError",
        "type": "object"
      },
      "PaginatedSatellites": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/SatelliteSummary"
            },
            "title": "Items",
            "type": "array"
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "items",
          "pagination"
        ],
        "title": "PaginatedSatellites",
        "type": "object"
      },
      "PaginatedStations": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/StationSummary"
            },
            "title": "Items",
            "type": "array"
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "items",
          "pagination"
        ],
        "title": "PaginatedStations",
        "type": "object"
      },
      "Pagination": {
        "description": "Pagination metadata returned alongside a paginated list payload.\n\nPhase 4 wraps every list endpoint in a ``{\"items\": [...], \"pagination\": {...}}``\nenvelope so callers can window through large result sets without leaning on\nthe previous bare-list shape (which silently capped at the route's natural\nreturn size). ``total`` is the count of rows matching the same WHERE clauses\nthe route applies, evaluated against the same store the items came from\n(DB ``SELECT count(*)`` for SQL paths, ``len(in_memory_list)`` for the\nadmin-side TLE-cache walk).",
        "properties": {
          "limit": {
            "description": "Maximum rows returned this call.",
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "description": "0-based row index this call started at.",
            "title": "Offset",
            "type": "integer"
          },
          "total": {
            "description": "Total matching rows on the server.",
            "title": "Total",
            "type": "integer"
          }
        },
        "required": [
          "limit",
          "offset",
          "total"
        ],
        "title": "Pagination",
        "type": "object"
      },
      "SatelliteDetail": {
        "description": "``GET /satellites/{norad}`` response payload.\n\nSourced from the hub TLE cache; the route requires the caller to have\na satellite permission row before TLE-cache contents are surfaced.",
        "properties": {
          "name": {
            "title": "Name",
            "type": "string"
          },
          "norad_id": {
            "title": "Norad Id",
            "type": "string"
          },
          "tle1": {
            "title": "Tle1",
            "type": "string"
          },
          "tle2": {
            "title": "Tle2",
            "type": "string"
          }
        },
        "required": [
          "norad_id",
          "name",
          "tle1",
          "tle2"
        ],
        "title": "SatelliteDetail",
        "type": "object"
      },
      "SatelliteSummary": {
        "description": "Row shape for ``GET /satellites`` and per-row entries on the admin\nfleet listing.",
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "norad_id": {
            "title": "Norad Id",
            "type": "string"
          }
        },
        "required": [
          "norad_id"
        ],
        "title": "SatelliteSummary",
        "type": "object"
      },
      "StationSummary": {
        "description": "Row shape for ``GET /stations``.",
        "properties": {
          "is_online": {
            "title": "Is Online",
            "type": "boolean"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "station_client_id": {
            "description": "Station tenant client identifier.",
            "title": "Station Client Id",
            "type": "string"
          },
          "station_id": {
            "description": "Canonical station UUID. Also accepted in {station_id} URL paths.",
            "title": "Station Id",
            "type": "string"
          }
        },
        "required": [
          "station_id",
          "station_client_id",
          "is_online"
        ],
        "title": "StationSummary",
        "type": "object"
      },
      "TleResponse": {
        "description": "``GET /satellites/{norad}/tle`` response payload.\n\nThe override path returns ``source='override'`` with a populated\n``set_at``; the agent path returns ``source='agent'`` with\n``set_at=null``. Extra agent-returned keys land under ``meta``.",
        "properties": {
          "meta": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Extra agent-returned fields, on the agent path only.",
            "title": "Meta"
          },
          "norad_id": {
            "title": "Norad Id",
            "type": "string"
          },
          "set_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the override was stored. ``null`` on the agent path (no notion of cache freshness).",
            "title": "Set At"
          },
          "source": {
            "enum": [
              "override",
              "agent"
            ],
            "title": "Source",
            "type": "string"
          },
          "tle1": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tle1"
          },
          "tle2": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tle2"
          }
        },
        "required": [
          "norad_id",
          "source"
        ],
        "title": "TleResponse",
        "type": "object"
      },
      "TransceiverPatch": {
        "examples": [
          {
            "rxdsp": {
              "bitrate": 19200
            }
          }
        ],
        "properties": {
          "command": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Nested command config: { packet, data, fec, scrambler, plop }.",
            "examples": [
              {
                "plop": {
                  "plop": "PLOP1"
                }
              }
            ],
            "title": "Command"
          },
          "rxdsp": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "RX DSP fields. Only keys included in the caller's editable_fields are accepted.",
            "examples": [
              {
                "bitrate": 19200,
                "modulation": "GFSK"
              }
            ],
            "title": "Rxdsp"
          },
          "telemetry": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Nested telemetry config: { packet, data, fec, scrambler }.",
            "examples": [
              {
                "packet": {
                  "length": 256
                }
              }
            ],
            "title": "Telemetry"
          },
          "txdsp": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "TX DSP fields.",
            "examples": [
              {
                "bitrate": 19200,
                "gain": 5.0
              }
            ],
            "title": "Txdsp"
          }
        },
        "title": "TransceiverPatch",
        "type": "object"
      },
      "TransceiverPatchResult": {
        "description": "``PATCH /stations/{id}/transceiver`` response payload.\n\nCarries the per-section outcome split introduced in Phase 1B\n(``applied_sections`` / ``failed_sections``) so a partial commit is\nvisible to the caller. HTTP 200 on full success, 207 on partial,\n502 if every section failed.",
        "properties": {
          "applied_sections": {
            "items": {
              "type": "string"
            },
            "title": "Applied Sections",
            "type": "array"
          },
          "failed_sections": {
            "items": {
              "$ref": "#/components/schemas/TransceiverSectionFailure"
            },
            "title": "Failed Sections",
            "type": "array"
          },
          "settings": {
            "additionalProperties": true,
            "title": "Settings",
            "type": "object"
          }
        },
        "required": [
          "settings",
          "applied_sections",
          "failed_sections"
        ],
        "title": "TransceiverPatchResult",
        "type": "object"
      },
      "TransceiverPermissions": {
        "description": "Per-caller editable fields for a station's transceiver.",
        "properties": {
          "editable_fields": {
            "description": "Field paths the caller may PATCH. ``['*']`` for portal-admin; the per-group permission set otherwise.",
            "items": {
              "type": "string"
            },
            "title": "Editable Fields",
            "type": "array"
          },
          "is_admin": {
            "title": "Is Admin",
            "type": "boolean"
          }
        },
        "required": [
          "is_admin",
          "editable_fields"
        ],
        "title": "TransceiverPermissions",
        "type": "object"
      },
      "TransceiverSectionFailure": {
        "description": "One ``failed_sections`` entry from ``PATCH /transceiver``.\n\n``error`` is currently free-form text; Phase 4 may promote it to a\nstructured object with per-section error codes.",
        "properties": {
          "error": {
            "title": "Error",
            "type": "string"
          },
          "section": {
            "title": "Section",
            "type": "string"
          }
        },
        "required": [
          "section",
          "error"
        ],
        "title": "TransceiverSectionFailure",
        "type": "object"
      },
      "TransceiverSnapshot": {
        "description": "``GET /stations/{id}/transceiver`` response payload.\n\n``settings`` is the nested ``{rxdsp, txdsp, telemetry, command}`` tree\nmaterialised from the agent's per-section reads.",
        "properties": {
          "permissions": {
            "$ref": "#/components/schemas/TransceiverPermissions"
          },
          "settings": {
            "additionalProperties": true,
            "title": "Settings",
            "type": "object"
          }
        },
        "required": [
          "settings",
          "permissions"
        ],
        "title": "TransceiverSnapshot",
        "type": "object"
      },
      "ValidationError": {
        "properties": {
          "ctx": {
            "title": "Context",
            "type": "object"
          },
          "input": {
            "title": "Input"
          },
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "title": "Location",
            "type": "array"
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        },
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError",
        "type": "object"
      },
      "_AssignBody": {
        "properties": {
          "force": {
            "default": false,
            "title": "Force",
            "type": "boolean"
          },
          "station_client_ids": {
            "items": {
              "type": "string"
            },
            "title": "Station Client Ids",
            "type": "array"
          },
          "template_id": {
            "title": "Template Id",
            "type": "string"
          }
        },
        "required": [
          "template_id"
        ],
        "title": "_AssignBody",
        "type": "object"
      },
      "_TemplateBody": {
        "properties": {
          "description": {
            "anyOf": [
              {
                "maxLength": 500,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "is_default": {
            "default": false,
            "title": "Is Default",
            "type": "boolean"
          },
          "mission_config": {
            "additionalProperties": true,
            "title": "Mission Config",
            "type": "object"
          },
          "name": {
            "maxLength": 120,
            "minLength": 1,
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "title": "_TemplateBody",
        "type": "object"
      },
      "_TemplatePatch": {
        "properties": {
          "description": {
            "anyOf": [
              {
                "maxLength": 500,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "is_default": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Default"
          },
          "mission_config": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Mission Config"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 120,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          }
        },
        "title": "_TemplatePatch",
        "type": "object"
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "bearerFormat": "JWT",
        "description": "Paste an OAuth2 `client_credentials` access token (without the `Bearer ` prefix).",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "description": "Public REST API for the Umoja satellite operations portal. All endpoints live under `/api/v1`; authenticate with an OAuth2 `client_credentials` token and pass it as `Authorization: Bearer <token>`.\n\n**Getting a token** \u2014 ask Remos to provision an API client (`client_id` / `client_secret`) for your group, then exchange them directly with Keycloak:\n\n```\ncurl -X POST https://umoja.remosspace.com:8443/realms/expedite/protocol/openid-connect/token \\\n  -d grant_type=client_credentials \\\n  -d client_id=<your-client-id> \\\n  -d client_secret=<your-client-secret>\n```\n\nThe response's `access_token` is your bearer for every call below. If your group already has portal access, you can also mint a short-lived test token yourself from **Profile \u2192 API access** without ever handling the secret.\n\n---\n\n## Realtime & Data Integration\n\nThree ways to get pass data out of Umoja programmatically:\n\n1. **`portal-link`**: a small client that exposes the live pass as local TCP\n   ports for a Mission Control System (Yamcs, COSMOS/OpenC3, Gpredict, scripts).\n2. **The realtime WebSocket**: `/ws/realtime`, the same live feed the portal\n   itself consumes.\n3. **The mission-data API**: list and download recordings after a pass.\n\nAll three authenticate with your Keycloak token and respect the same group and\nbooking-window rules as the portal.\n\n### portal-link (TCP bridge)\n\n`portal-link` opens local TCP ports on your machine so an MCS can exchange\ntelemetry and telecommands with the hub during a pass. It speaks the hub's TCP\nbridge protocol and handles sign-in for you.\n\n#### Quick start\n\n```bash\n./portal-link \\\n  --hub bridge.umoja.remosspace.com:10100 \\\n  --station <your-station-id> \\\n  --booking <booking-uuid> \\\n  --kc-url https://umoja.remosspace.com:8443/realms/expedite\n```\n\nOn first run it prints a URL to open in your browser to sign in. After sign-in:\n\n1. The client connects to the hub over TLS.\n2. A local **TM** server starts on `localhost:10025`.\n3. A local **TC** server starts on `localhost:10026`.\n\nOmit `--booking` to get an interactive picker of your active/upcoming passes.\n\n#### Point your MCS at the local ports\n\n- **TM data source:** `localhost:10025` (TCP)\n- **TC data sink:** `localhost:10026` (TCP)\n\n#### CLI reference\n\n```\nUsage: portal-link [flags]\n\nRequired:\n  --hub             Hub TCP bridge address (e.g. bridge.umoja.remosspace.com:10100)\n  --kc-url          Keycloak realm URL\n\nOptional:\n  --api-url         Hub HTTP API URL (auto-derived from --hub if unset)\n  --station         Ground station client ID (e.g. umoja)\n  --booking         Booking UUID (interactive picker if omitted)\n  --streams         Comma-separated streams (default: tm,tc)\n                    Valid: tm,tc,antenna,doppler,ephemeris,command\n  --tm-port         Local TM port (default: 10025)\n  --tc-port         Local TC port (default: 10026)\n  --doppler-port    Local doppler port (default: 10027)\n  --ephemeris-port  Local ephemeris port (default: 10028)\n  --antenna-port    Local antenna port (default: 10029)\n  --command-port    Local command-echo port (default: 10030)\n  --client-id       Keycloak client ID (default: portal-link)\n  --tls             Enable TLS to hub (default: true)\n  --insecure        Skip TLS certificate verification (testing only)\n  --verbose         Enable debug logging\n  --version         Show version\n```\n\n#### Streams and ports\n\nEach requested stream is exposed on its own local TCP port. Multiple tools may\nconnect to the same port at once. Every connection gets a copy of the stream.\n\n| Stream | Default port | Direction | Purpose |\n|--------|--------------|-----------|---------|\n| `tm` | 10025 | hub \u2192 MCS | Telemetry frames from the satellite. |\n| `tc` | 10026 | MCS \u2192 hub | Telecommand frames to the satellite. |\n| `doppler` | 10027 | hub \u2192 MCS | Doppler shift updates during the pass. |\n| `ephemeris` | 10028 | hub \u2192 MCS | Predicted trajectory for the pass. |\n| `antenna` | 10029 | hub \u2192 MCS | Antenna pointing telemetry (az/el). |\n| `command` | 10030 | hub \u2192 MCS | Echo of telecommands as they leave the radio. |\n\nRequest more than the default `tm,tc` by listing them:\n\n```bash\n./portal-link \\\n  --hub bridge.umoja.remosspace.com:10100 \\\n  --station <your-station-id> --booking <booking-uuid> \\\n  --kc-url https://umoja.remosspace.com:8443/realms/expedite \\\n  --streams tm,tc,antenna,doppler,ephemeris,command\n```\n\n#### MCS configuration examples\n\n##### Yamcs\n\n```yaml\ndataLinks:\n  - name: remos-tm\n    class: org.yamcs.tctm.TcpTmDataLink\n    host: localhost\n    port: 10025\n    stream: tm_realtime\n  - name: remos-tc\n    class: org.yamcs.tctm.TcpTcDataLink\n    host: localhost\n    port: 10026\n    stream: tc_realtime\n```\n\n##### COSMOS (OpenC3)\n\n```ruby\nINTERFACE REMOS_TM_INT tcpip_client_interface.rb localhost 10025 10025 10.0 nil\nINTERFACE REMOS_TC_INT tcpip_client_interface.rb localhost 10026 10026 10.0 nil\n```\n\n##### Custom script (Python)\n\n```python\nimport socket\n\n# Receive TM\nsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\nsock.connect((\"localhost\", 10025))\nwhile True:\n    data = sock.recv(4096)\n    if not data:\n        break\n    process_telemetry(data)\n```\n\n```python\n# Send TC\nsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\nsock.connect((\"localhost\", 10026))\nsock.sendall(bytes.fromhex(\"A1B2C3D4\"))\n```\n\n### Realtime WebSocket\n\nIf you'd rather consume the feed directly (the same one the portal uses), open\na WebSocket per stream:\n\n```\nwss://<host>/ws/realtime?station_id=<client_id>&stream=<stream>[&booking_id=<uuid>]\n```\n\nAuthenticate by sending your Keycloak bearer token as a WebSocket subprotocol:\n\n```js\nnew WebSocket(url, [\"bearer\", \"<your-jwt>\"])\n```\n\nAvailable streams: `spectrum`, `constellation`, `doppler`, `ephemeris`,\n`antenna`, `telemetry`, `command`.\n\nFrames are binary, prefixed with a small header: a 2-byte magic (`EX`), a\n1-byte stream tag, and the 16-byte station client ID (NUL-padded), followed by\nthe stream payload (e.g. spectrum is 1024 \u00d7 `[freq, power]` float32 pairs). The\nhub refreshes nothing for you: keep your token fresh and reconnect on drop.\n\n### Mission-data API\n\nAfter a pass, list and download its recordings over REST. Send your Keycloak\ntoken as `Authorization: Bearer <jwt>`.\n\n| Endpoint | Method | Purpose |\n|----------|--------|---------|\n| `/api/data/files` | GET | List files (filter by `station_id`, `booking_id`, `status`, `from_ts`/`to_ts`, `search`; `group_by_pass`). |\n| `/api/data/files/summary` | GET | Aggregate counts and bytes. |\n| `/api/data/files/{file_id}/link` | POST | Mint a short-lived signed download URL for one file. |\n| `/api/data/bookings/{booking_id}/link` | POST | Mint a signed URL for the whole pass as a ZIP bundle. |\n\nMinting a link, then downloading, keeps the long-lived token off the wire:\n\n```bash\n# 1. mint a signed URL (bearer token)\ncurl -X POST https://umoja.remosspace.com/api/data/files/$FILE_ID/link \\\n  -H \"Authorization: Bearer $TOKEN\"\n# -> { \"download_url\": \"...\", \"expires_in\": 900 }\n\n# 2. download (the signed URL carries its own token)\ncurl -L -o capture.iq \"<download_url>\"\n```\n\nSee the **REST API** tab for the full, interactive reference.\n\n### Session window\n\nA live session (portal-link or WebSocket) is tied to a booking and only flows\nduring its window:\n\n- Earliest: **AOS \u2212 5 minutes**. Latest: **LOS + 5 minutes**.\n- Connect before the window opens and the hub rejects the session until the\n  booking becomes active.\n- The session disconnects automatically once the window closes.\n- `portal-admin` accounts bypass the window for live diagnostics.\n\n### Troubleshooting\n\n| Symptom | Cause | What to do |\n|---------|-------|------------|\n| `AUTH_FAIL:invalid_token` | Token expired or malformed. | Re-run portal-link / refresh your token. |\n| `AUTH_FAIL:no_active_booking` | No valid booking in the current window. | Check the window under **Bookings**; wait for AOS \u2212 5 min. |\n| `AUTH_FAIL:station_not_found` | Wrong `--station`. | Use the client ID shown on the **Stations** page. |\n| `AUTH_FAIL:server_full` | Too many concurrent sessions. | Retry shortly, or contact support. |\n| TM stops mid-pass | Network drop or pass ended. | portal-link auto-reconnects until LOS + 5 min. |\n| TC not delivered | Station offline. | Check the station's live state on **Stations**. |",
    "title": "Umoja Portal API",
    "version": "1.0.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/api/v1/satellites": {
      "get": {
        "operationId": "getSatellites",
        "parameters": [
          {
            "description": "Page size; max 500.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 100,
              "description": "Page size; max 500.",
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "description": "0-based offset for pagination.",
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "description": "0-based offset for pagination.",
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_PaginatedSatellites_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "List satellites visible to the caller.",
        "tags": [
          "Satellites"
        ]
      }
    },
    "/api/v1/satellites/{norad}": {
      "get": {
        "operationId": "getSatellite",
        "parameters": [
          {
            "in": "path",
            "name": "norad",
            "required": true,
            "schema": {
              "title": "Norad",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_SatelliteDetail_"
                }
              }
            },
            "description": "Successful Response"
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_ErrorPayload_"
                }
              }
            },
            "description": "Caller's groups have no ``GroupSatellitePermission`` row for this NORAD. Error code ``satellite_permission_denied``."
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_ErrorPayload_"
                }
              }
            },
            "description": "Admin caller asked for a NORAD that's not in the hub TLE cache. Error code ``satellite_not_found``. Non-admin callers see 403 first to avoid an existence oracle."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Get satellite metadata from the hub TLE cache.",
        "tags": [
          "Satellites"
        ]
      }
    },
    "/api/v1/satellites/{norad}/mission-templates": {
      "get": {
        "description": "List this org's mission templates for a satellite.",
        "operationId": "list_mission_templates_api_v1_satellites__norad__mission_templates_get",
        "parameters": [
          {
            "in": "path",
            "name": "norad",
            "required": true,
            "schema": {
              "title": "Norad",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "List Mission Templates",
        "tags": [
          "Satellites"
        ]
      },
      "post": {
        "description": "Create a mission template for this satellite under the caller's org.",
        "operationId": "create_mission_template_api_v1_satellites__norad__mission_templates_post",
        "parameters": [
          {
            "in": "path",
            "name": "norad",
            "required": true,
            "schema": {
              "title": "Norad",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_TemplateBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Create Mission Template",
        "tags": [
          "Satellites"
        ]
      }
    },
    "/api/v1/satellites/{norad}/mission-templates/{template_id}": {
      "delete": {
        "operationId": "delete_mission_template_api_v1_satellites__norad__mission_templates__template_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "norad",
            "required": true,
            "schema": {
              "title": "Norad",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "template_id",
            "required": true,
            "schema": {
              "title": "Template Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Delete Mission Template",
        "tags": [
          "Satellites"
        ]
      },
      "patch": {
        "operationId": "update_mission_template_api_v1_satellites__norad__mission_templates__template_id__patch",
        "parameters": [
          {
            "in": "path",
            "name": "norad",
            "required": true,
            "schema": {
              "title": "Norad",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "template_id",
            "required": true,
            "schema": {
              "title": "Template Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_TemplatePatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Update Mission Template",
        "tags": [
          "Satellites"
        ]
      }
    },
    "/api/v1/satellites/{norad}/mission-templates/{template_id}/default": {
      "post": {
        "operationId": "set_default_mission_template_api_v1_satellites__norad__mission_templates__template_id__default_post",
        "parameters": [
          {
            "in": "path",
            "name": "norad",
            "required": true,
            "schema": {
              "title": "Norad",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "template_id",
            "required": true,
            "schema": {
              "title": "Template Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Set Default Mission Template",
        "tags": [
          "Satellites"
        ]
      }
    },
    "/api/v1/satellites/{norad}/station-template-assignments": {
      "get": {
        "description": "List this org's (station -> template) assignments for a satellite.",
        "operationId": "list_station_template_assignments_api_v1_satellites__norad__station_template_assignments_get",
        "parameters": [
          {
            "in": "path",
            "name": "norad",
            "required": true,
            "schema": {
              "title": "Norad",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "List Station Template Assignments",
        "tags": [
          "Satellites"
        ]
      },
      "put": {
        "description": "Assign a mission template to one or more stations for this satellite.\n\nConflict = a listed station is already pinned to a DIFFERENT template\nunder this org. Returns 409 with the conflicting rows unless\n``force=True``, in which case all listed stations are overwritten to\n``template_id``.",
        "operationId": "put_station_template_assignments_api_v1_satellites__norad__station_template_assignments_put",
        "parameters": [
          {
            "in": "path",
            "name": "norad",
            "required": true,
            "schema": {
              "title": "Norad",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_AssignBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Put Station Template Assignments",
        "tags": [
          "Satellites"
        ]
      }
    },
    "/api/v1/satellites/{norad}/station-template-assignments/{station_client_id}": {
      "delete": {
        "operationId": "delete_station_template_assignment_api_v1_satellites__norad__station_template_assignments__station_client_id__delete",
        "parameters": [
          {
            "in": "path",
            "name": "norad",
            "required": true,
            "schema": {
              "title": "Norad",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "station_client_id",
            "required": true,
            "schema": {
              "title": "Station Client Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Delete Station Template Assignment",
        "tags": [
          "Satellites"
        ]
      }
    },
    "/api/v1/satellites/{norad}/tle": {
      "get": {
        "description": "Return TLE for the satellite.\n\nPriority: hub-side override (if any) > agent-fetched value via\n``/track/gettle``. The override is set via\n``POST /api/v1/satellites/{norad}/tle``. Station-scoped overrides are\nnot surfaced here yet; a global override (``station_id IS NULL``) takes\nprecedence whenever present.",
        "operationId": "getSatelliteTle",
        "parameters": [
          {
            "in": "path",
            "name": "norad",
            "required": true,
            "schema": {
              "title": "Norad",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_TleResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Get the current TLE for a satellite (override or agent-fetched).",
        "tags": [
          "Satellites"
        ]
      }
    },
    "/api/v1/stations": {
      "get": {
        "operationId": "getStations",
        "parameters": [
          {
            "description": "Page size; max 500.",
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 100,
              "description": "Page size; max 500.",
              "maximum": 500,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "description": "0-based offset for pagination.",
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "description": "0-based offset for pagination.",
              "minimum": 0,
              "title": "Offset",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_PaginatedStations_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "List ground stations the caller can access.",
        "tags": [
          "Stations"
        ]
      }
    },
    "/api/v1/stations/booking-windows": {
      "get": {
        "description": "Return active, not-yet-past busy windows across ALL orgs.\n\nStation visibility uses ``list_stations_for_user`` \u2014 the same\nadmin-sees-all / ``StationPermission``-join gate that backs\n``GET /stations`` (this file) and ``/api/proxy/bookings/all`` in\nmain.py (there as ``_get_allowed_station_ids`` + a matching\n``GroundStation`` query). So a caller sees busy windows on exactly the\nstations they can otherwise see \u2014 no more, no less.\n\nUnlike ``/api/proxy/bookings/all``, bookings are NOT filtered to the\ncaller's own groups: this feed is cross-org by design so every caller\ncan see the full busy/free picture on their visible stations. Each\nwindow is redacted down to the four keys below \u2014 no satellite, org,\nuser, or booking-id ever leaves the hub for a non-``mine`` row.",
        "operationId": "getStationBookingWindows",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_BookingWindows_"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Redacted cross-org busy windows for stations the caller can access.",
        "tags": [
          "Stations"
        ]
      }
    },
    "/api/v1/stations/{station_id}/antenna/ip": {
      "get": {
        "operationId": "getStationAntennaIp",
        "parameters": [
          {
            "description": "Station UUID or client_id",
            "in": "path",
            "name": "station_id",
            "required": true,
            "schema": {
              "description": "Station UUID or client_id",
              "title": "Station Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_Dict_str__Any__"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Get the antenna's IP/connection settings.",
        "tags": [
          "Stations"
        ]
      }
    },
    "/api/v1/stations/{station_id}/antenna/position": {
      "get": {
        "operationId": "getStationAntennaPosition",
        "parameters": [
          {
            "description": "Station UUID or client_id",
            "in": "path",
            "name": "station_id",
            "required": true,
            "schema": {
              "description": "Station UUID or client_id",
              "title": "Station Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_Dict_str__Any__"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Get the current antenna position (azimuth / elevation).",
        "tags": [
          "Stations"
        ]
      }
    },
    "/api/v1/stations/{station_id}/antenna/status": {
      "get": {
        "operationId": "getStationAntennaStatus",
        "parameters": [
          {
            "description": "Station UUID or client_id",
            "in": "path",
            "name": "station_id",
            "required": true,
            "schema": {
              "description": "Station UUID or client_id",
              "title": "Station Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_Dict_str__Any__"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Get antenna status flags from the station.",
        "tags": [
          "Stations"
        ]
      }
    },
    "/api/v1/stations/{station_id}/gs/location": {
      "get": {
        "operationId": "getStationGsLocation",
        "parameters": [
          {
            "description": "Station UUID or client_id",
            "in": "path",
            "name": "station_id",
            "required": true,
            "schema": {
              "description": "Station UUID or client_id",
              "title": "Station Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_Dict_str__Any__"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Get the station's geographic location.",
        "tags": [
          "Stations"
        ]
      }
    },
    "/api/v1/stations/{station_id}/missions": {
      "get": {
        "operationId": "getStationMissions",
        "parameters": [
          {
            "description": "Station UUID or client_id",
            "in": "path",
            "name": "station_id",
            "required": true,
            "schema": {
              "description": "Station UUID or client_id",
              "title": "Station Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_Dict_str__Any__"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "List missions known to the station.",
        "tags": [
          "Stations"
        ]
      }
    },
    "/api/v1/stations/{station_id}/missions/config": {
      "get": {
        "operationId": "getStationMissionConfig",
        "parameters": [
          {
            "description": "Station UUID or client_id",
            "in": "path",
            "name": "station_id",
            "required": true,
            "schema": {
              "description": "Station UUID or client_id",
              "title": "Station Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_Dict_str__Any__"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Get the station's mission config.",
        "tags": [
          "Stations"
        ]
      }
    },
    "/api/v1/stations/{station_id}/radio/status": {
      "get": {
        "operationId": "getStationRadioStatus",
        "parameters": [
          {
            "description": "Station UUID or client_id",
            "in": "path",
            "name": "station_id",
            "required": true,
            "schema": {
              "description": "Station UUID or client_id",
              "title": "Station Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_Dict_str__Any__"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Get the station SDR/radio runtime status.",
        "tags": [
          "Stations"
        ]
      }
    },
    "/api/v1/stations/{station_id}/tracking/passes": {
      "get": {
        "description": "Return the agent's pass list with a hub-stable ``pass_id`` per entry.\n\nEach pass is upserted into ``upcoming_passes`` keyed on\n``(station, norad, aos\u00b15min)`` so the ``pass_id`` survives normal\nTLE-refresh AOS drift. Clients pass this ``pass_id`` (and nothing\nelse) to ``POST /passes/{pass_id}/book`` \u2014 the hub re-resolves the\nagent-current ``pass_index`` at booking time. See\n``api_v1.upcoming_passes`` for the bridge mechanics.",
        "operationId": "getStationTrackingPasses",
        "parameters": [
          {
            "description": "Station UUID or client_id",
            "in": "path",
            "name": "station_id",
            "required": true,
            "schema": {
              "description": "Station UUID or client_id",
              "title": "Station Id",
              "type": "string"
            }
          },
          {
            "description": "NORAD catalog id",
            "in": "query",
            "name": "norad",
            "required": true,
            "schema": {
              "description": "NORAD catalog id",
              "title": "Norad",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_Dict_str__Any__"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "List upcoming passes for a satellite at this station.",
        "tags": [
          "Stations"
        ]
      }
    },
    "/api/v1/stations/{station_id}/tracking/satellites": {
      "get": {
        "operationId": "getStationTrackedSatellites",
        "parameters": [
          {
            "description": "Station UUID or client_id",
            "in": "path",
            "name": "station_id",
            "required": true,
            "schema": {
              "description": "Station UUID or client_id",
              "title": "Station Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_Dict_str__Any__"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "List satellites the station is tracking.",
        "tags": [
          "Stations"
        ]
      }
    },
    "/api/v1/stations/{station_id}/tracking/satellites/live": {
      "get": {
        "operationId": "getStationLiveSatellitePositions",
        "parameters": [
          {
            "description": "Station UUID or client_id",
            "in": "path",
            "name": "station_id",
            "required": true,
            "schema": {
              "description": "Station UUID or client_id",
              "title": "Station Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_Dict_str__Any__"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Get live satellite positions from the station.",
        "tags": [
          "Stations"
        ]
      }
    },
    "/api/v1/stations/{station_id}/transceiver": {
      "get": {
        "operationId": "getTransceiver",
        "parameters": [
          {
            "description": "Station UUID or client_id",
            "in": "path",
            "name": "station_id",
            "required": true,
            "schema": {
              "description": "Station UUID or client_id",
              "title": "Station Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_TransceiverSnapshot_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Get the station transceiver settings tree + caller permissions.",
        "tags": [
          "Transceiver"
        ]
      },
      "patch": {
        "operationId": "patchTransceiver",
        "parameters": [
          {
            "description": "Station UUID or client_id",
            "in": "path",
            "name": "station_id",
            "required": true,
            "schema": {
              "description": "Station UUID or client_id",
              "title": "Station Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransceiverPatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_TransceiverPatchResult_"
                }
              }
            },
            "description": "Successful Response"
          },
          "207": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_TransceiverPatchResult_"
                }
              }
            },
            "description": "Partial-commit multi-status. At least one section landed and at least one was rejected; ``applied_sections`` and ``failed_sections`` carry the split."
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          },
          "502": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope_TransceiverPatchResult_"
                }
              }
            },
            "description": "Every requested section was rejected by the agent. ``failed_sections`` carries the per-section error strings."
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "summary": "Patch one or more transceiver sections (per-section partial commit).",
        "tags": [
          "Transceiver"
        ]
      }
    }
  },
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "servers": [
    {
      "description": "Production hub",
      "url": "https://umoja.remosspace.com"
    }
  ]
}