# Constellation Execution Source: https://docs.rotastellar.com/agent/constellation Multi-satellite DAG orchestration with ISL coordination and automatic failover # Constellation Execution **WS4 Agent Mode** Constellation Execution extends the Operator Agent to orchestrate workloads across multiple satellites. A DAG-based execution plan is distributed across the constellation, with steps assigned to individual satellites and data transferred between them via inter-satellite links (ISLs). The agent runtime handles step lifecycle, ISL coordination, and automatic failover when a satellite becomes unhealthy. Constellation mode requires a multi-satellite deployment created from a constellation DAG plan. See [CAE Constellation DAG](/cae/constellation-dag) for how plans are generated. ## ConstellationState Each agent participating in a constellation deployment maintains a `ConstellationState` that tracks its view of the distributed execution. | Field | Type | Description | | ------------------- | ----- | -------------------------------------------------- | | `assigned_steps` | map | Steps assigned to this satellite, keyed by step ID | | `active_transfers` | array | ISL transfers currently in progress | | `completed_steps` | set | Step IDs that have completed successfully | | `failed_over_steps` | set | Step IDs that were reassigned due to failover | ## Step Lifecycle Each step in the constellation DAG follows a deterministic state machine: ``` Pending --> Executing --> Completed | v FailedOver ``` | State | Description | | ------------ | ----------------------------------------------------------------- | | `Pending` | Step assigned but waiting for dependencies or resources | | `Executing` | Step actively running on the assigned satellite | | `Completed` | Step finished successfully, output available for downstream steps | | `FailedOver` | Step reassigned to another satellite due to health check failure | When a step completes, its output data is made available for dependent steps. If the dependent step is assigned to a different satellite, an ISL transfer is initiated automatically. ## Automatic Failover The agent runtime continuously monitors satellite health during constellation execution. A failover is triggered when any of the following conditions are detected: | Condition | Threshold | Description | | ------------------- | -------------- | ----------------------------------------------- | | Battery critical | \< 10% | Insufficient power to complete compute step | | Thermal exceedance | > 75C | Risk of hardware damage or thermal shutdown | | Compute unavailable | Battery \< 15% | Not enough power headroom for sustained compute | Failover reassigns the step to the next eligible satellite in the DAG. If no eligible satellite is available, the step is marked as failed and the constellation plan terminates with a partial completion status. When a failover occurs, the following sequence executes: 1. The current satellite emits `constellation.failover` with the reason 2. The orchestrator selects an alternate satellite from the DAG 3. The step is reassigned and a `constellation.failover_acknowledged` event is emitted 4. The new satellite begins execution from the last checkpoint (if available) ## ISL Transfer Lifecycle Data transfers between satellites follow a multi-hop model. Each hop represents a direct ISL link between two satellites in range. ``` started --> hop_completed (x N) --> completed + quality_report ``` | State | Description | | ---------------- | -------------------------------------------------------------------- | | `started` | Transfer initiated between source and destination satellites | | `hop_completed` | A single ISL hop finished, includes quality metrics for that segment | | `completed` | All hops finished, data delivered to destination satellite | | `quality_report` | Aggregate link quality metrics for the full transfer path | ### ISL Link Quality Model Link quality between any two satellites is computed dynamically based on distance and eclipse state: | Parameter | Formula / Value | | ------------------- | -------------------------------------------------- | | Distance factor | `1 - (distance_km / 5000) * 0.6` | | Eclipse penalty | `0.9` (applied when either endpoint is in eclipse) | | Effective bandwidth | `100 Mbps * quality` | | Propagation latency | `distance_km / c + 2ms` (where c = 299,792 km/s) | | Max range | 5,000 km (quality = 0 beyond this) | The 2ms additional latency accounts for onboard processing and protocol overhead at each hop. For multi-hop transfers, latency is cumulative across all hops. **Example:** Two satellites 2,000 km apart, one in eclipse: * Distance factor: `1 - (2000 / 5000) * 0.6 = 0.76` * Eclipse penalty: `0.76 * 0.9 = 0.684` * Effective bandwidth: `100 * 0.684 = 68.4 Mbps` * Propagation latency: `2000 / 299792 + 0.002 = 8.67ms` ## Event Enrichment All constellation events are enriched with real-time satellite telemetry at the moment the event is generated: | Field | Type | Description | | ------------------------ | ------- | ------------------------------------------ | | `actual_battery_percent` | number | Battery level at event time | | `actual_temperature_c` | number | Temperature at event time | | `lat` | number | Geodetic latitude | | `lon` | number | Geodetic longitude | | `altitude_km` | number | Altitude above Earth surface | | `in_eclipse` | boolean | Whether the satellite is in Earth's shadow | This telemetry is sourced from the `SimulatedSatellite` executor, which integrates with the [Simulation Sessions](/sim/sessions) service for subsystem state. ## Event Types ### Constellation Events | Event | Description | Key Payload Fields | | ------------------------------------- | ---------------------------------- | ------------------------------------------------------ | | `constellation.step_assigned` | Step assigned to a satellite | `step_id`, `satellite_id`, `dependencies` | | `constellation.step_started` | Step execution begins | `step_id`, `satellite_id` | | `constellation.step_completed` | Step finished successfully | `step_id`, `duration_s`, `data_output_mb` | | `constellation.failover` | Step failover initiated | `step_id`, `from_satellite`, `reason` | | `constellation.failover_acknowledged` | Failover accepted by new satellite | `step_id`, `to_satellite` | | `constellation.satellite_complete` | All steps on a satellite are done | `satellite_id`, `steps_completed`, `steps_failed_over` | ### ISL Events | Event | Description | Key Payload Fields | | ----------------------------- | --------------------------- | ---------------------------------------------------------------------------- | | `isl_transfer.started` | ISL data transfer initiated | `from`, `to`, `data_mb`, `hop_count` | | `isl_transfer.hop_completed` | Single hop finished | `from`, `to`, `hop_index`, `quality`, `latency_ms` | | `isl_transfer.completed` | Full transfer delivered | `from`, `to`, `total_duration_s`, `data_mb` | | `isl_transfer.quality_report` | Aggregate path quality | `avg_quality`, `min_quality`, `total_latency_ms`, `effective_bandwidth_mbps` | ## Integration with SimulatedSatellite In simulation mode, the constellation executor uses the `SimulatedSatellite` backend to model each satellite's behavior. This executor: * Maintains per-satellite subsystem state (battery, thermal, memory, CPU) * Applies realistic charge/discharge and thermal models per tick * Evaluates failover conditions against live subsystem values * Generates ISL quality metrics from actual propagated positions The `SimulatedSatellite` executor connects to the Sim service's [session API](/sim/sessions) to persist and retrieve constellation state. Full protocol specification for agent communication How constellation execution plans are generated # Operator Agent Source: https://docs.rotastellar.com/agent/overview The execution layer for orbital compute — a pull-based agent protocol for running workloads on satellites # Operator Agent The RotaStellar Operator Agent is a lightweight runtime that executes compute workloads on satellites. It uses a **pull-based protocol** designed for intermittent connectivity — agents operate autonomously and sync with Mission Control during contact windows. The Operator Agent is open source. See the [GitHub repository](https://github.com/rotastellar/rotastellar-agent) for the Rust SDK. ## Architecture ```mermaid theme={null} sequenceDiagram participant Agent as Satellite Agent participant API as Console API Agent->>API: POST /api/agent/register API-->>Agent: agent_id confirmed loop Every contact window Agent->>API: GET /api/agent/workloads API-->>Agent: pending workloads + events end Note over Agent: Execute workload steps locally Agent->>API: POST /api/deployments/{id}/events Note right of API: step.started, step.progress,
step.completed, job.completed loop Periodic Agent->>API: POST /api/agent/telemetry Note right of API: heartbeat, resource usage end ``` The agent runs on the satellite (or in simulation on a development machine). It communicates exclusively with the Console API — there is no direct connection to the CAE planner. ## How It Works 1. **Poll** — Agent checks for pending workloads during contact windows 2. **Execute** — Agent runs workload steps locally on the satellite 3. **Report** — Agent streams execution events back to Console 4. **Telemetry** — Agent sends periodic health/status heartbeats The protocol is pull-based by design. Satellites have intermittent ground station contact windows — typically a few minutes per orbit. The agent polls when connectivity is available, executes autonomously, and reports results on the next pass. ## Deployment Modes | Mode | Description | | ----------- | ------------------------------------------------------------------------------------------- | | `simulated` | Console generates events from CAE plan data. No agent involved. Good for testing and demos. | | `live` | Agent polls, executes, and reports events. Real or hardware-in-the-loop execution. | ## Event Types The agent uses the same event format as the [CAE simulator](/cae/understanding-plans). Events track the full lifecycle of a workload execution: | Event | Description | | ------------------------------ | -------------------------------------------- | | `job.accepted` | Workload received and queued | | `placement.decided` | Step placement decision (on-board vs ground) | | `plan.created` | Execution plan finalized | | `step.started` | Compute step begins | | `step.progress` | Progress update (25%, 50%, 75%) | | `step.completed` | Compute step finished | | `transfer.started` | Data transfer initiated | | `transfer.completed` | Data transfer finished | | `checkpoint.saved` | State checkpoint persisted | | `security.encrypted` | Data encrypted | | `job.completed` | All steps finished successfully | | `job.failed` | Execution failed | | `constellation.step_assigned` | DAG step assigned to satellite | | `constellation.step_completed` | DAG step finished | | `constellation.failover` | Step failed, reassigning | | `isl_transfer.started` | ISL data transfer initiated | | `isl_transfer.completed` | ISL transfer done | | `checkpoint.predicted` | Hazard prediction generated | Full protocol specification with auth, lifecycle, and error handling Multi-satellite DAG orchestration with ISL coordination Build agents with the Rust crate Run your first simulation in 5 minutes # Protocol Specification Source: https://docs.rotastellar.com/agent/protocol Full specification of the RotaStellar Agent Protocol — authentication, lifecycle, event types, and error handling # Agent Protocol Specification **Version:** 0.1.0 The RotaStellar Agent Protocol defines how satellite-side agents communicate with the Console API. It is a **pull-based** protocol designed for intermittent satellite connectivity. ## Authentication All agent requests authenticate via API key in the `X-API-Key` header. The agent identifies itself via the `X-Agent-ID` header. ``` X-API-Key: rs_live_... X-Agent-ID: sat-25544 ``` API keys are created in Mission Control under **Developer > API Keys**. Keys are hashed (SHA-256) server-side and compared against stored hashes. Keys can be revoked at any time from the Console. ## Agent Lifecycle ```mermaid theme={null} stateDiagram-v2 [*] --> Register Register --> Poll Poll --> Execute : Workload available Poll --> Poll : No work (sleep) Execute --> Execute : Report events & telemetry Execute --> Complete : job.completed Execute --> Failed : job.failed Complete --> Poll : Ready for next workload Failed --> Poll : Ready for next workload ``` ### 1. Register The agent registers with the Console on first startup. This creates or updates an agent record. ``` POST /api/agent/register ``` **Request:** ```json theme={null} { "agent_id": "sat-25544", "satellite_id": "25544", "satellite_name": "ISS (ZARYA)", "agent_version": "0.1.0" } ``` **Response (201):** ```json theme={null} { "id": "sat-25544", "status": "idle" } ``` If the `agent_id` already exists for this user, the record is updated (upsert). ### 2. Poll for Workloads The agent polls periodically for pending deployments assigned to its satellite. ``` GET /api/agent/workloads ``` **Response (200) — Work available:** ```json theme={null} { "plan_id": "abc-123", "deployment_id": "dep-456", "satellite_id": "25544", "plan_data": { ... }, "events": [ { "type": "job.accepted", "timestamp": "2026-03-07T12:00:00Z", "job_id": "preset-001", "payload": { "preset": "split-learning", "steps": 8 } } ] } ``` **Response (204) — No work available.** The agent should sleep for `poll_interval_s` and retry. The server returns the oldest pending deployment where: * `mode = 'live'` * `satellite_id` matches the agent's registered satellite * `status = 'pending'` On dispatch, the server updates the deployment status to `dispatched`. ### 3. Report Events During execution, the agent reports events as they occur. ``` POST /api/deployments/{deployment_id}/events ``` **Request:** ```json theme={null} { "type": "step.completed", "timestamp": "2026-03-07T14:23:45Z", "job_id": "preset-001", "step_id": "feature_extraction", "payload": { "duration_s": 180, "location": "onboard", "data_output_mb": 10.5 } } ``` **Response (201):** ```json theme={null} { "id": "evt-789" } ``` The server stores the event and updates the deployment status based on event type: * `job.accepted` (when `dispatched`) → deployment status = `running` * `job.completed` → deployment status = `completed` * `job.failed` → deployment status = `failed` ### 4. Report Telemetry Agents send periodic heartbeats with health data. ``` POST /api/agent/telemetry ``` **Request:** ```json theme={null} { "agent_id": "sat-25544", "status": "executing", "timestamp": "2026-03-07T14:23:45Z", "cpu_percent": 67.5, "memory_mb": 128.0, "battery_percent": 82.0, "temperature_c": 34.2 } ``` **Response (200):** ```json theme={null} { "ok": true } ``` All fields except `agent_id`, `status`, and `timestamp` are optional. ## Event Types All events follow this structure: ```json theme={null} { "type": "", "timestamp": "", "job_id": "", "step_id": "", "payload": { ... } } ``` ### Lifecycle Events | Type | Description | Payload | | --------------- | ------------------------------- | --------------------------------------------------- | | `job.accepted` | Workload received and queued | `preset`, `category`, `steps`, `security` | | `plan.created` | Execution plan finalized | `segments`, `windows_used`, `total_duration_s` | | `job.completed` | All steps finished successfully | `total_duration_s`, `status`, `delivery_confidence` | | `job.failed` | Execution failed | `total_duration_s`, `status` | ### Placement Events | Type | Description | Payload | | ------------------- | ----------------------- | ------------------------------------- | | `placement.decided` | Step placement decision | `location` (onboard/ground), `reason` | ### Compute Events | Type | Description | Payload | | ---------------- | --------------------- | ------------------------------------------ | | `step.started` | Compute step begins | `location`, `window`, `window_label` | | `step.progress` | Progress update | `percent` (25, 50, 75) | | `step.completed` | Compute step finished | `duration_s`, `location`, `data_output_mb` | ### Transfer Events | Type | Description | Payload | | ------------------------- | -------------------------- | -------------------------------------------------------- | | `transfer.started` | Data transfer initiated | `type`, `raw_data_mb`, `total_transfer_mb`, `fec_scheme` | | `transfer.pass_started` | Ground station pass begins | `ground_station`, `station_name`, `elevation_peak_deg` | | `transfer.progress` | Transfer progress | `data_transferred_mb`, `total_mb` | | `transfer.pass_completed` | Pass finished | `data_transferred_mb`, `ground_station` | | `transfer.completed` | All transfers done | `total_transferred_mb`, `duration_s` | | `transfer.retransmission` | Blocks retransmitted (BER) | `blocks_retransmitted`, `ber` | ### Security Events | Type | Description | Payload | | ----------------------- | ---------------------- | -------------------------- | | `security.encrypted` | Data encrypted | `algorithm`, `data_mb` | | `security.key_exchange` | Key exchange performed | `duration_s`, `encryption` | ### Checkpoint Events | Type | Description | Payload | | ---------------------- | --------------------------- | --------------------------------------------------------------------------------------------- | | `checkpoint.saved` | State persisted | `checkpoint_number`, `progress_fraction` | | `checkpoint.predicted` | Hazard prediction generated | `hazards_count`, `checkpoints_count`, `next_hazard`, `max_safe_window_s`, `overhead_fraction` | ### Orbital Compute Primitive Events Eclipse, window, and pass steps emit specialized events. See [Orbital Compute Primitives](/cae/orbital-primitives) for details. | Type | Description | Payload | | ------------------------ | --------------------- | ---------------------------------------------------------------- | | `eclipse_step.started` | Eclipse step begins | `energy_budget_j`, `eclipse_policy`, `actual_battery_wh` | | `eclipse_step.completed` | Eclipse step finished | `energy_consumed_j`, `actual_battery_wh`, `actual_temperature_c` | | `window_step.started` | Window step begins | `planned_tier`, `quality_tiers`, `actual_battery_percent` | | `window_step.degraded` | Tier downgraded | `from_tier`, `to_tier`, `reason` | | `window_step.completed` | Window step finished | `achieved_tier`, `output_quality`, `degradations` | | `pass_step.started` | Pass step begins | `sequence_index`, `sequence_total`, `actual_battery_percent` | | `pass_step.completed` | Pass step finished | `sequence_index`, `sequence_total`, `merge_strategy` | ### Constellation Events Multi-satellite DAG orchestration events. See [Constellation Execution](/agent/constellation) for details. | Type | Description | Payload | | ---------------------------------- | -------------------------- | ----------------------------------------------------- | | `constellation.step_assigned` | Step assigned to satellite | `step_id`, `step_name`, `satellite_id`, `window_id` | | `constellation.step_started` | Agent began executing step | `step_id`, `actual_battery_percent` | | `constellation.step_completed` | Step finished | `step_id`, `duration_s`, `actual_battery_percent` | | `constellation.failover` | Step failed, reassigning | `step_id`, `from_satellite`, `to_satellite`, `reason` | | `constellation.satellite_complete` | All assigned steps done | `satellite_id`, `completed_count` | ### ISL Transfer Events | Type | Description | Payload | | ---------------------------- | ---------------------- | ------------------------------------------------------------ | | `isl_transfer.started` | ISL transfer initiated | `src_satellite`, `dst_satellite`, `data_mb`, `hops`, `route` | | `isl_transfer.hop_completed` | One ISL hop done | `from`, `to`, `data_mb`, `quality`, `latency_ms`, `bw_mbps` | | `isl_transfer.completed` | Full transfer done | `total_time_s`, `total_data_mb`, `hops`, `reliability` | ## Error Handling All error responses follow this format: ```json theme={null} { "error": "Human-readable error message" } ``` | Status | Meaning | | ------ | ---------------------------------------------- | | 400 | Invalid request body | | 401 | Missing or invalid API key | | 403 | API key valid but insufficient permissions | | 404 | Resource not found | | 409 | Conflict (e.g., deployment already dispatched) | | 429 | Rate limited | | 500 | Server error | ## Rate Limits | Endpoint | Limit | | --------- | ---------------------------------------- | | Poll | Max 1 request per 10 seconds per agent | | Events | Max 100 events per minute per deployment | | Telemetry | Max 1 request per 30 seconds per agent | ## Versioning The protocol version is included in the `User-Agent` header: ``` User-Agent: rotastellar-agent/0.1.0 ``` Breaking changes will increment the minor version until 1.0. After 1.0, semantic versioning applies. # Agent Quickstart Source: https://docs.rotastellar.com/agent/quickstart Run your first simulated satellite execution in 5 minutes # Agent Quickstart This guide walks you through running a simulated satellite execution using the RotaStellar Operator Agent. ## Prerequisites * [Rust 1.75+](https://rustup.rs/) installed * A RotaStellar Console account at [console.rotastellar.com](https://console.rotastellar.com) * An API key (create one under **Developer > API Keys** in the Console) ## 1. Clone and Build ```bash theme={null} git clone https://github.com/rotastellar/rotastellar-agent.git cd rotastellar-agent cargo build --release ``` The binary is at `target/release/rotastellar-agent`. ## 2. Create a Plan Before running the agent, you need a deployment. In Mission Control: 1. Go to **Missions** and create a new mission 2. Open the mission and click **New Plan** 3. Select a satellite (e.g., ISS — NORAD ID `25544`) and a preset (e.g., On-Board ML Inference) 4. Review the plan and click **Deploy** 5. Choose **Live** mode — this creates a deployment that waits for an agent Alternatively, create a plan via the CAE API and save the response: ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{"satellite_id": "25544", "preset_id": "onboard-ml-inference"}' \ -o plan.json ``` ## 3. Run the Agent ### Option A: Poll mode (recommended) Run the agent in long-running poll mode. It will register with the Console, then continuously poll for pending deployments. ```bash theme={null} export ROTASTELLAR_API_KEY="rs_live_..." ./target/release/rotastellar-agent run \ --agent-id sat-25544 \ --api-url https://console.rotastellar.com \ --api-key $ROTASTELLAR_API_KEY ``` When you deploy a plan in Mission Control with **Live** mode, the agent will pick it up automatically. ### Option B: Simulate a plan file If you have a saved CAE plan JSON, you can replay it directly: ```bash theme={null} ./target/release/rotastellar-agent simulate \ --plan plan.json \ --speed 100 \ --api-url https://console.rotastellar.com \ --api-key $ROTASTELLAR_API_KEY ``` ## 4. Watch the Execution Open the deployment in Mission Control. You'll see events appear in the timeline as the agent reports them: ``` [T+ 0s] job.accepted [T+ 0s] placement.decided capture [T+ 0s] placement.decided preprocess [T+ 5s] step.started capture [T+ 10s] step.progress capture (25%) [T+ 25s] step.completed capture [T+ 30s] step.started preprocess ... [T+ 180s] job.completed ``` The deployment status transitions: `pending` → `dispatched` → `running` → `completed`. ## 5. Check Telemetry While running, the agent sends periodic telemetry heartbeats. You can see agent status in the Console under **Agents** — including status, last heartbeat, and resource usage. ## What's Next Deep dive into the pull-based protocol Build a custom agent for your satellite hardware # Rust SDK Source: https://docs.rotastellar.com/agent/rust-sdk Build satellite agents with the rotastellar-agent Rust crate # Rust SDK The `rotastellar-agent` crate provides everything you need to build a satellite agent: the `Agent` trait, a simulated satellite for testing, an HTTP client for the Console API, and a CLI binary. **License:** [MPL-2.0](https://github.com/rotastellar/rotastellar-agent/blob/master/LICENSE) — modified files must be shared, but you can use the crate in proprietary projects. ## Installation Add to your `Cargo.toml`: ```toml theme={null} [dependencies] rotastellar-agent = { git = "https://github.com/rotastellar/rotastellar-agent" } ``` Or clone and build directly: ```bash theme={null} git clone https://github.com/rotastellar/rotastellar-agent.git cd rotastellar-agent cargo build --release ``` ## The Agent Trait The core abstraction is the `Agent` trait. It defines the satellite-side execution protocol: ```rust theme={null} #[async_trait] pub trait Agent: Send + Sync { /// Poll the Console API for pending workloads. async fn poll(&self) -> Result, AgentError>; /// Report an execution event. async fn report_event(&self, event: &AgentEvent) -> Result<(), AgentError>; /// Report telemetry data (heartbeat, resource usage). async fn report_telemetry(&self, telemetry: &AgentTelemetry) -> Result<(), AgentError>; /// Execute a workload. async fn execute(&self, workload: &WorkloadSpec) -> Result<(), AgentError>; /// Start the agent run loop. async fn start(&self) -> Result<(), AgentError>; /// Stop the agent gracefully. async fn stop(&self) -> Result<(), AgentError>; } ``` ## Using SimulatedSatellite The built-in `SimulatedSatellite` replays pre-computed CAE event streams with realistic timing. Use it for testing and demos. ```rust theme={null} use rotastellar_agent::{AgentConfig, SimulatedSatellite, Agent}; #[tokio::main] async fn main() { let config = AgentConfig { agent_id: "sat-25544".into(), api_url: "https://console.rotastellar.com".into(), api_key: "rs_live_...".into(), poll_interval_s: 30, }; // 100x speed — a 90-minute orbit plays in ~1 minute let agent = SimulatedSatellite::new(config, 100.0).unwrap(); agent.start().await.unwrap(); } ``` The `speed_multiplier` controls replay speed: * `1.0` — real-time (events play at actual orbital timing) * `10.0` — 10x faster * `100.0` — 100x faster (default for demos) * `10000.0` — near-instant (useful for automated tests) ## Building a Custom Agent Implement the `Agent` trait to run real computations on satellite hardware: ```rust theme={null} use async_trait::async_trait; use rotastellar_agent::{Agent, AgentError, AgentEvent, AgentTelemetry, WorkloadSpec}; struct MyAgent { config: AgentConfig, client: ConsoleClient, } #[async_trait] impl Agent for MyAgent { async fn poll(&self) -> Result, AgentError> { self.client.poll_workloads().await } async fn report_event(&self, event: &AgentEvent) -> Result<(), AgentError> { self.client.report_event(&event.job_id, event).await } async fn report_telemetry(&self, telemetry: &AgentTelemetry) -> Result<(), AgentError> { self.client.report_telemetry(telemetry).await } async fn execute(&self, workload: &WorkloadSpec) -> Result<(), AgentError> { // Run your computation here. // Report events for each step transition. for event in &workload.events { self.report_event(event).await?; } Ok(()) } async fn start(&self) -> Result<(), AgentError> { // Implement your run loop todo!() } async fn stop(&self) -> Result<(), AgentError> { // Signal graceful shutdown todo!() } } ``` ## Types ### AgentConfig ```rust theme={null} pub struct AgentConfig { pub agent_id: String, // Unique agent identifier (e.g., "sat-25544") pub api_url: String, // Console API URL pub api_key: String, // API key (rs_live_...) pub poll_interval_s: u64, // Seconds between polls (default: 30) } ``` ### WorkloadSpec ```rust theme={null} pub struct WorkloadSpec { pub plan_id: String, // CAE plan ID pub deployment_id: String, // Console deployment ID pub satellite_id: String, // NORAD catalog ID pub plan_data: serde_json::Value, // Full CAE plan data pub events: Vec, // Pre-computed event timeline } ``` ### AgentEvent ```rust theme={null} pub struct AgentEvent { pub event_type: String, // Serializes as "type" in JSON pub timestamp: String, // ISO 8601 pub job_id: String, pub step_id: Option, // Omitted from JSON when None pub payload: serde_json::Value, } ``` ### AgentTelemetry ```rust theme={null} pub struct AgentTelemetry { pub agent_id: String, pub status: AgentStatus, // idle, executing, transferring, offline pub timestamp: String, pub cpu_percent: Option, // Omitted when None pub memory_mb: Option, pub battery_percent: Option, pub temperature_c: Option, } ``` ### AgentError ```rust theme={null} pub enum AgentError { ApiError(String), // API request failed NetworkError(reqwest::Error), // Network error SerializationError(serde_json::Error), ExecutionError(String), // Execution error Stopped, // Agent stopped } ``` ## CLI The crate builds a CLI binary with two subcommands: ### `simulate` — Replay a plan file ```bash theme={null} rotastellar-agent simulate \ --plan plan.json \ --speed 100 \ --api-url https://console.rotastellar.com \ --api-key rs_live_... ``` ### `run` — Long-running poll mode ```bash theme={null} rotastellar-agent run \ --agent-id sat-25544 \ --api-url https://console.rotastellar.com \ --api-key rs_live_... ``` The agent will register, then loop: poll → execute → report → sleep → repeat. # Constellation Pareto Frontier Source: https://docs.rotastellar.com/api-reference/cae/constellation-pareto POST /v1/constellation/pareto Computes the Pareto frontier across a constellation for multi-objective trade-off analysis **Base URL:** `https://rotastellar-cae.subhadip-mitra.workers.dev` — No API key required. CORS-validated. ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/constellation/pareto \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{ "fleet": [ { "norad_id": "99901", "name": "RS-LEO-1", "role": "compute", "orbit": { "altitude_km": 550, "inclination_deg": 53 } }, { "norad_id": "99902", "name": "RS-LEO-2", "role": "compute", "orbit": { "altitude_km": 550, "inclination_deg": 53 } } ], "preset_id": "split-learning" }' ``` ```json 200 OK theme={null} { "frontier": [ { "satellite": "RS-LEO-1", "pareto": [ { "ocu": 0.25, "latency_s": 120, "reliability": 0.99 }, { "ocu": 0.50, "latency_s": 80, "reliability": 0.97 }, { "ocu": 0.75, "latency_s": 55, "reliability": 0.94 } ] }, { "satellite": "RS-LEO-2", "pareto": [ { "ocu": 0.25, "latency_s": 125, "reliability": 0.99 }, { "ocu": 0.50, "latency_s": 82, "reliability": 0.96 }, { "ocu": 0.75, "latency_s": 58, "reliability": 0.93 } ] } ], "constellation_metrics": { "total_ocu": 1.50, "min_latency_s": 55, "avg_reliability": 0.963, "isl_overhead_s": 14 } } ``` # Plan Constellation DAG Source: https://docs.rotastellar.com/api-reference/cae/constellation-plan POST /v1/constellation/plan Generates an optimized execution plan (DAG) for a satellite constellation workload **Base URL:** `https://rotastellar-cae.subhadip-mitra.workers.dev` — No API key required. CORS-validated. ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/constellation/plan \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{ "fleet": [ { "norad_id": "99901", "name": "RS-LEO-1", "role": "compute", "orbit": { "altitude_km": 550, "inclination_deg": 53 } }, { "norad_id": "99902", "name": "RS-LEO-2", "role": "compute", "orbit": { "altitude_km": 550, "inclination_deg": 53 } }, { "norad_id": "99903", "name": "RS-LEO-3", "role": "aggregator", "orbit": { "altitude_km": 550, "inclination_deg": 53 } } ], "preset_id": "split-learning" }' ``` ```json 200 OK theme={null} { "plan_id": "plan_cst_7f3a1b", "preset_id": "split-learning", "metrics": { "critical_path_s": 342, "satellites_used": 3, "isl_transfers": 4, "reliability": 0.973 }, "steps": [ { "step": 1, "satellite": "RS-LEO-1", "task": "forward_pass_split", "duration_s": 45, "depends_on": [] }, { "step": 2, "satellite": "RS-LEO-2", "task": "forward_pass_split", "duration_s": 45, "depends_on": [] }, { "step": 3, "satellite": "RS-LEO-3", "task": "aggregate_activations", "duration_s": 30, "depends_on": [1, 2], "isl_route": ["RS-LEO-1 → RS-LEO-3", "RS-LEO-2 → RS-LEO-3"] } ], "isl_routing": [ { "from": "RS-LEO-1", "to": "RS-LEO-3", "latency_ms": 12, "bandwidth_mbps": 100 }, { "from": "RS-LEO-2", "to": "RS-LEO-3", "latency_ms": 14, "bandwidth_mbps": 100 } ] } ``` # Create Plan Source: https://docs.rotastellar.com/api-reference/cae/create-plan POST /v1/plan Create a constraint-aware execution plan for a satellite and workload **Base URL:** `https://rotastellar-cae.subhadip-mitra.workers.dev` — No API key required. ## Request NORAD catalog ID (e.g., `"25544"` for ISS). Preset workload ID. One of: `onboard-ml-inference`, `split-learning`, `earth-observation-qa`, `federated-learning`, `resilient-store-forward`. Mutually exclusive with `custom_job`. Custom workload definition with arbitrary step DAG. Mutually exclusive with `preset_id`. See [Custom Workloads](/cae/custom-workloads) for the full schema. * `name` (string) — Workload name * `steps` (array, required) — Step definitions with dependencies * `security` (object) — Security policy overrides * `policy` (object) — Execution policy overrides Override security settings from the preset or custom job: * `encryption` — `none`, `aes128`, or `aes256` * `data_classification` — `open`, `restricted`, or `confidential` * `require_authenticated_uplink` — boolean * `key_rotation_orbits` — number Planning options: * `prediction_hours` (number, 1–48, default: 12) — Orbital prediction window * `min_elevation_deg` (number, 0–90, default: 5) — Minimum ground station elevation Either `preset_id` or `custom_job` is required, but not both. ```bash Preset theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{ "satellite_id": "25544", "preset_id": "onboard-ml-inference" }' ``` ```bash Custom Job theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{ "satellite_id": "25544", "custom_job": { "name": "Capture and Process", "steps": [ { "id": "capture", "name": "Sensor Capture", "location": "onboard", "duration_s": 30, "depends_on": [], "requires": {"power_w": 40, "compute": 0.3, "thermal_w": 15, "memory_mb": 256, "storage_mb": 1024}, "input_data_mb": 0, "output_data_mb": 500 }, { "id": "process", "name": "Ground Processing", "location": "ground", "duration_s": 60, "depends_on": ["capture"], "requires": {"power_w": 100, "compute": 1.0, "thermal_w": 50, "memory_mb": 2048, "storage_mb": 2048}, "input_data_mb": 500, "output_data_mb": 50, "data_reduction_ratio": 0.1 } ] } }' ``` ```python Python theme={null} import requests response = requests.post( "https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan", headers={ "Content-Type": "application/json", "Origin": "https://rotastellar.com" }, json={ "satellite_id": "25544", "preset_id": "onboard-ml-inference" } ) plan = response.json() print(f"Plan {plan['id']}: {plan['plan']['windows_used']} windows, " f"confidence {plan['error_budget']['delivery_confidence']}") ``` ```json 201 Created theme={null} { "id": "a92f33e8-a349-494c-8b4e-f87d859b9ec5", "created_at": "2026-03-05T06:55:37.811Z", "version": "1.0.0", "satellite": { "id": "25544", "name": "ISS (ZARYA)", "norad_id": 25544, "altitude_km": 417, "inclination_deg": 51.6, "period_min": 93, "tle_epoch": "26063.86671769" }, "preset": { "id": "onboard-ml-inference", "name": "On-Board ML Inference", "category": "ml-inference", "steps": 4 }, "orbital_environment": { "prediction_start": "2026-03-05T06:55:37.811Z", "prediction_hours": 12, "eclipse_fraction": 0.348, "bus": { "..." : "..." }, "windows": [ "..." ], "ground_passes": [ "..." ], "summary": { "total_windows": 14, "comms_windows": 6, "sunlit_windows": 9, "eclipse_windows": 5, "total_pass_time_s": 2847, "ground_stations_visible": 8 } }, "placement_decisions": [ { "step_id": "capture", "location": "onboard", "reason": "preset_defined" }, { "step_id": "preprocess", "location": "onboard", "reason": "preset_defined" }, { "step_id": "inference", "location": "onboard", "reason": "preset_defined" }, { "step_id": "encrypt_results", "location": "onboard", "reason": "preset_defined" } ], "transfer_schedule": { "transfers": [ "..." ], "total_transfers": 1, "total_downlink_mb": 11.03, "total_uplink_mb": 0, "passes_used": 1, "total_transfer_time_s": 12 }, "error_budget": { "worst_case_ber": 0.00001, "total_fec_overhead_mb": 0.53, "total_retransmission_reserve_mb": 0.11, "delivery_confidence": 0.997 }, "security_summary": { "encryption": "aes256", "total_encryption_overhead_mb": 0.53, "total_key_exchanges": 1, "data_classification": "restricted" }, "plan": { "segments": [ "..." ], "total_duration_s": 1382, "total_compute_s": 170, "total_transfer_s": 12, "total_ground_s": 0, "windows_used": 2, "policy": { "objective": "min_latency", "deadline_orbits": 3 } }, "events": [ "..." ] } ``` ```json 400 Validation Error theme={null} { "error": { "code": "validation_error", "message": "satellite_id is required" } } ``` ```json 422 Planning Failed theme={null} { "error": { "code": "planning_failed", "message": "No feasible window for step 'inference': thermal constraint exceeded" } } ``` ## Errors | Status | Code | Description | | ------ | -------------------- | --------------------------------------- | | 400 | `validation_error` | Invalid request body or parameters | | 400 | `invalid_body` | Request body is not valid JSON | | 403 | `origin_not_allowed` | Request from disallowed origin | | 422 | `planning_failed` | Planner cannot find a feasible schedule | | 500 | `internal_error` | Unexpected server error | # Get Plan Source: https://docs.rotastellar.com/api-reference/cae/get-plan GET /v1/plan/{plan_id} Retrieve a previously created execution plan **Base URL:** `https://rotastellar-cae.subhadip-mitra.workers.dev` — No API key required. Plans expire after 1 hour. ## Request UUID returned from `POST /v1/plan`. ```bash cURL theme={null} curl https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan/a92f33e8-a349-494c-8b4e-f87d859b9ec5 \ -H "Origin: https://rotastellar.com" ``` ```python Python theme={null} import requests plan_id = "a92f33e8-a349-494c-8b4e-f87d859b9ec5" response = requests.get( f"https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan/{plan_id}", headers={"Origin": "https://rotastellar.com"} ) print(response.json()) ``` ```json 200 OK theme={null} { "id": "a92f33e8-a349-494c-8b4e-f87d859b9ec5", "created_at": "2026-03-05T06:55:37.811Z", "version": "1.0.0", "satellite": { "..." : "..." }, "preset": { "..." : "..." }, "orbital_environment": { "..." : "..." }, "placement_decisions": [ "..." ], "transfer_schedule": { "..." : "..." }, "error_budget": { "..." : "..." }, "security_summary": { "..." : "..." }, "plan": { "..." : "..." }, "events": [ "..." ] } ``` ```json 404 Not Found theme={null} { "error": { "code": "not_found", "message": "Plan a92f33e8-... not found or expired" } } ``` # Get Plan Events Source: https://docs.rotastellar.com/api-reference/cae/get-plan-events GET /v1/plan/{plan_id}/events Get the simulated execution event stream for a plan **Base URL:** `https://rotastellar-cae.subhadip-mitra.workers.dev` — No API key required. Plans expire after 1 hour. ## Request UUID returned from `POST /v1/plan`. ```bash cURL theme={null} curl https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan/a92f33e8-a349-494c-8b4e-f87d859b9ec5/events \ -H "Origin: https://rotastellar.com" ``` ```python Python theme={null} import requests plan_id = "a92f33e8-a349-494c-8b4e-f87d859b9ec5" response = requests.get( f"https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan/{plan_id}/events", headers={"Origin": "https://rotastellar.com"} ) data = response.json() for event in data["events"]: print(f"[{event['type']}] {event.get('message', '')}") ``` ```json 200 OK theme={null} { "plan_id": "a92f33e8-a349-494c-8b4e-f87d859b9ec5", "events": [ { "type": "job.accepted", "timestamp_s": 0, "message": "Workload accepted: On-Board ML Inference" }, { "type": "placement.decided", "timestamp_s": 0, "step_id": "capture", "location": "onboard", "message": "Step 'capture' placed on-board" }, { "type": "step.started", "timestamp_s": 0, "step_id": "capture", "message": "Starting Sensor Data Capture" }, { "type": "step.completed", "timestamp_s": 30, "step_id": "capture", "output_data_mb": 2000, "message": "Completed Sensor Data Capture" }, { "type": "transfer.started", "timestamp_s": 170, "direction": "downlink", "data_mb": 11.03, "message": "Starting downlink transfer" }, { "type": "job.completed", "timestamp_s": 1382, "message": "Pipeline completed successfully", "delivery_confidence": 0.997 } ], "count": 73 } ``` ```json 404 Not Found theme={null} { "error": { "code": "not_found", "message": "Plan a92f33e8-... not found or expired" } } ``` # Predict Hazards Source: https://docs.rotastellar.com/api-reference/cae/hazards POST /v1/hazards Predicts orbital hazards and generates a checkpoint schedule for a satellite **Base URL:** `https://rotastellar-cae.subhadip-mitra.workers.dev` — No API key required. CORS-validated. ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/hazards \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{ "satellite_id": "25544", "prediction_hours": 24 }' ``` ```json 200 OK theme={null} { "hazards": [ { "type": "eclipse_entry", "start_epoch": "2026-03-10T14:22:00Z", "duration_s": 2160, "severity": 0.6 }, { "type": "saa_crossing", "start_epoch": "2026-03-10T16:45:00Z", "duration_s": 480, "severity": 0.8 }, { "type": "eclipse_entry", "start_epoch": "2026-03-10T15:54:00Z", "duration_s": 2100, "severity": 0.6 }, { "type": "thermal_peak", "start_epoch": "2026-03-11T02:10:00Z", "duration_s": 300, "severity": 0.4 } ], "checkpoint_schedule": [ { "epoch": "2026-03-10T14:18:00Z", "reason": "pre_eclipse" }, { "epoch": "2026-03-10T16:40:00Z", "reason": "pre_saa" }, { "epoch": "2026-03-11T02:05:00Z", "reason": "pre_thermal" } ], "summary": { "hazards_count": 4, "checkpoints_count": 3, "max_safe_window_s": 2400, "overhead_fraction": 0.05 } } ``` # List Presets Source: https://docs.rotastellar.com/api-reference/cae/list-presets GET /v1/presets List available workload presets with metadata **Base URL:** `https://rotastellar-cae.subhadip-mitra.workers.dev` — No API key required. ## Request No parameters. ```bash cURL theme={null} curl https://rotastellar-cae.subhadip-mitra.workers.dev/v1/presets \ -H "Origin: https://rotastellar.com" ``` ```python Python theme={null} import requests response = requests.get( "https://rotastellar-cae.subhadip-mitra.workers.dev/v1/presets", headers={"Origin": "https://rotastellar.com"} ) for preset in response.json()["presets"]: print(f"{preset['id']}: {preset['steps']} steps, {preset['data_flow']['overall_reduction']} reduction") ``` ```json Response theme={null} { "presets": [ { "id": "onboard-ml-inference", "name": "On-Board ML Inference", "description": "Run ML inference on-board to achieve 190:1 data reduction before downlink...", "category": "ml-inference", "steps": 4, "onboard_steps": 4, "ground_steps": 0, "total_compute_s": 170, "data_flow": { "initial_capture_mb": 2000, "final_output_mb": 10.5, "overall_reduction": "190:1" }, "needs_downlink": true, "needs_uplink": false, "security": { "encryption": "aes256", "data_classification": "restricted", "allowed_ground_stations": null, "require_authenticated_uplink": true, "key_rotation_orbits": 24 }, "policy": { "objective": "min_latency", "deadline_orbits": 3, "max_data_loss_fraction": 0.001, "min_delivery_confidence": 0.99 } } ], "count": 5 } ``` # Service Metrics Source: https://docs.rotastellar.com/api-reference/cae/metrics GET /v1/metrics Returns per-endpoint latency percentiles, request counts, and status distribution **Base URL:** `https://rotastellar-cae.subhadip-mitra.workers.dev` — No API key required. CORS-validated. ```bash theme={null} curl https://rotastellar-cae.subhadip-mitra.workers.dev/v1/metrics \ -H "Origin: https://rotastellar.com" ``` ```json 200 OK theme={null} { "endpoints": { "POST /v1/constellation/plan": { "requests": 1284, "latency_ms": { "p50": 42, "p95": 110, "p99": 245 }, "status": { "200": 1260, "400": 18, "500": 6 } }, "POST /v1/constellation/pareto": { "requests": 873, "latency_ms": { "p50": 55, "p95": 140, "p99": 310 }, "status": { "200": 861, "400": 10, "500": 2 } }, "POST /v1/hazards": { "requests": 2041, "latency_ms": { "p50": 28, "p95": 72, "p99": 160 }, "status": { "200": 2018, "400": 20, "500": 3 } }, "POST /v1/ocu/negotiate": { "requests": 3512, "latency_ms": { "p50": 18, "p95": 45, "p99": 98 }, "status": { "200": 3480, "400": 28, "500": 4 } }, "GET /v1/ocu/summary/:busClass": { "requests": 1890, "latency_ms": { "p50": 8, "p95": 22, "p99": 50 }, "status": { "200": 1878, "400": 12 } } }, "uptime_s": 604800, "collected_at": "2026-03-10T12:00:00Z" } ``` # Negotiate OCU Source: https://docs.rotastellar.com/api-reference/cae/ocu-negotiate POST /v1/ocu/negotiate Negotiates an Orbital Compute Unit allocation for a satellite workload **Base URL:** `https://rotastellar-cae.subhadip-mitra.workers.dev` — No API key required. CORS-validated. ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/ocu/negotiate \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{ "satellite_id": "25544", "workload_power_w": 50 }' ``` ```json 200 OK theme={null} { "satellite_id": "25544", "ocu_negotiation": { "ocu_allocated": 0.62, "sunlit_hours": 10.4, "eclipse_hours": 5.6, "daily_compute_hours": 8.2, "confidence": 0.94, "cost_usd_per_hour": 0.035, "limiting_resource": "power" }, "power_budget": { "generation_w": 120, "bus_overhead_w": 45, "available_w": 75, "requested_w": 50, "margin_w": 25 } } ``` # OCU Summary Source: https://docs.rotastellar.com/api-reference/cae/ocu-summary GET /v1/ocu/summary/{busClass} Returns the OCU capacity profile for a given satellite bus class **Base URL:** `https://rotastellar-cae.subhadip-mitra.workers.dev` — No API key required. CORS-validated. ### Path Parameters | Parameter | Type | Description | | ---------- | ------ | ---------------------------------------------------------------------- | | `busClass` | string | Satellite bus class. One of: `1U`, `2U`, `3U`, `6U`, `12U`, `SmallSat` | ```bash theme={null} curl https://rotastellar-cae.subhadip-mitra.workers.dev/v1/ocu/summary/6U \ -H "Origin: https://rotastellar.com" ``` ```json 200 OK theme={null} { "bus_class": "6U", "profile": { "power_generation_w": 80, "bus_overhead_w": 30, "compute_available_w": 50, "memory_mb": 4096, "storage_gb": 32 }, "capacity_bands": [ { "ocu": 0.25, "power_w": 12.5, "description": "Light sensing / telemetry" }, { "ocu": 0.50, "power_w": 25.0, "description": "Edge inference" }, { "ocu": 0.75, "power_w": 37.5, "description": "Split learning / compression" }, { "ocu": 1.00, "power_w": 50.0, "description": "Full compute allocation" } ], "ocu_reference": { "sunlit_ocu_max": 1.0, "eclipse_ocu_max": 0.4, "daily_average_ocu": 0.72 } } ``` # Service Index Source: https://docs.rotastellar.com/api-reference/cae/service-index GET /v1 Get CAE service capabilities and endpoints **Base URL:** `https://rotastellar-cae.subhadip-mitra.workers.dev` — This is a separate service from the main RotaStellar API. No API key required. ## Request No parameters. ```bash cURL theme={null} curl https://rotastellar-cae.subhadip-mitra.workers.dev/v1 \ -H "Origin: https://rotastellar.com" ``` ```python Python theme={null} import requests response = requests.get( "https://rotastellar-cae.subhadip-mitra.workers.dev/v1", headers={"Origin": "https://rotastellar.com"} ) print(response.json()) ``` ```json Response theme={null} { "service": "rotastellar-cae", "version": "1.0.0", "description": "Constraint-Aware Execution — orbital compute orchestration across the space-ground boundary", "capabilities": [ "SGP4 orbital propagation", "Real eclipse detection (cylindrical shadow model)", "Ground station pass prediction (12-station network)", "Compute placement optimization (on-board vs ground)", "Data transfer scheduling with FEC and encryption overhead", "Multi-pass downlink allocation", "Deterministic error budget and delivery confidence" ], "endpoints": { "GET /v1/presets": "List available workload presets", "POST /v1/plan": "Create an execution plan for a satellite + workload", "GET /v1/plan/:id": "Retrieve a previously created plan", "GET /v1/plan/:id/events": "Get simulated execution event stream" } } ``` # Create Deployment Source: https://docs.rotastellar.com/api-reference/deployments/create-deployment POST /api/deployments Create a new deployment from a plan **Base URL:** `https://console.rotastellar.com` — Requires session cookie or API key authentication. ## Request The ID of the plan to deploy. The plan must belong to the authenticated user. Simulation speed for simulated deployments. Default: `100`. A value of `100` means a 90-minute orbit plays in \~1 minute. ```bash cURL theme={null} curl -X POST https://console.rotastellar.com/api/deployments \ -H "Content-Type: application/json" \ -H "Cookie: session=..." \ -d '{ "plan_id": "abc-123", "speed_multiplier": 100 }' ``` ```bash API Key theme={null} curl -X POST https://console.rotastellar.com/api/deployments \ -H "Content-Type: application/json" \ -H "X-API-Key: rs_live_..." \ -d '{ "plan_id": "abc-123" }' ``` ```json 201 Created theme={null} { "id": "dep-456", "status": "pending" } ``` ```json 400 Validation Error theme={null} { "error": "plan_id is required" } ``` ```json 404 Not Found theme={null} { "error": "Plan not found" } ``` ## Status Lifecycle After creation, the deployment status transitions: | Status | Meaning | | ------------ | -------------------------------- | | `pending` | Created, waiting to start | | `dispatched` | Assigned to an agent (live mode) | | `running` | Agent is executing | | `completed` | All steps finished successfully | | `failed` | Execution failed | | `cancelled` | Cancelled by user | # Deployment Events Source: https://docs.rotastellar.com/api-reference/deployments/deployment-events GET /api/deployments/{id}/events Get and report execution events for a deployment **Base URL:** `https://console.rotastellar.com` ## List Events Retrieve execution events for a deployment, ordered chronologically. ``` GET /api/deployments/{id}/events ``` **Authentication:** Session cookie (Console UI) or API key. The deployment ID. Pagination offset. Default: `0`. Maximum number of events to return. Default: `100`, max: `500`. ```bash cURL theme={null} curl "https://console.rotastellar.com/api/deployments/dep-456/events?limit=50" \ -H "Cookie: session=..." ``` ```json 200 OK theme={null} { "events": [ { "id": "evt-001", "event_type": "job.accepted", "step_id": null, "payload": { "preset": "onboard-ml-inference", "category": "ml-inference", "steps": 4 }, "event_timestamp": "2026-03-07T12:00:00Z", "created_at": "2026-03-07T12:00:01Z" }, { "id": "evt-002", "event_type": "placement.decided", "step_id": "capture", "payload": { "location": "onboard", "reason": "preset_defined" }, "event_timestamp": "2026-03-07T12:00:00Z", "created_at": "2026-03-07T12:00:01Z" } ], "total": 24, "offset": 0, "limit": 50 } ``` *** ## Report Event Agents use this endpoint to report execution events during a live deployment. ``` POST /api/deployments/{id}/events ``` **Authentication:** API key only (`X-API-Key` + `X-Agent-ID` headers). The event type. See [Event Types](/agent/protocol#event-types) for the full list. ISO 8601 timestamp of when the event occurred. Job identifier linking related events. Step identifier, if the event relates to a specific compute or transfer step. Event-specific data. Contents vary by event type. ```bash Agent Event theme={null} curl -X POST https://console.rotastellar.com/api/deployments/dep-456/events \ -H "Content-Type: application/json" \ -H "X-API-Key: rs_live_..." \ -H "X-Agent-ID: sat-25544" \ -d '{ "type": "step.completed", "timestamp": "2026-03-07T14:23:45Z", "job_id": "preset-001", "step_id": "feature_extraction", "payload": { "duration_s": 180, "location": "onboard", "data_output_mb": 10.5 } }' ``` ```json 201 Created theme={null} { "id": "evt-789" } ``` ```json 400 Validation Error theme={null} { "error": "type and timestamp are required" } ``` ## Status Side Effects Terminal events automatically update the deployment status: | Event Type | Deployment Status Change | | --------------- | ------------------------ | | `job.accepted` | `dispatched` → `running` | | `job.completed` | → `completed` | | `job.failed` | → `failed` | # Get Deployment Source: https://docs.rotastellar.com/api-reference/deployments/get-deployment GET /api/deployments/{id} Get deployment details including plan data and event count **Base URL:** `https://console.rotastellar.com` — Requires session cookie or API key authentication. ## Request The deployment ID. ```bash cURL theme={null} curl https://console.rotastellar.com/api/deployments/dep-456 \ -H "Cookie: session=..." ``` ```json 200 OK theme={null} { "id": "dep-456", "mission_id": "mis-123", "plan_id": "plan-789", "satellite_id": "25544", "status": "completed", "mode": "simulated", "speed_multiplier": 100, "started_at": "2026-03-07T12:00:05Z", "completed_at": "2026-03-07T12:01:32Z", "created_at": "2026-03-07T12:00:00Z", "mission_name": "ISS ML Pipeline", "plan_label": "On-Board ML Inference", "plan_data": { "id": "a92f33e8-...", "satellite": { ... }, "preset": { ... }, "plan": { "total_duration_s": 1382, "windows_used": 2 }, "events": [ ... ] }, "event_count": 24 } ``` ```json 404 Not Found theme={null} { "error": "Deployment not found" } ``` ## Response Fields Includes all fields from [List Deployments](/api-reference/deployments/list-deployments), plus: | Field | Type | Description | | ------------- | ------ | ------------------------------------------------------------------------------------------------------------------------- | | `plan_data` | object | Full CAE plan data (satellite, preset, orbital environment, placement decisions, transfer schedule, error budget, events) | | `event_count` | number | Total number of execution events recorded | ## Delete / Cancel ``` DELETE /api/deployments/{id} ``` * If the deployment is `running`, it is marked as `cancelled` * If the deployment is `pending`, it is deleted # List Deployments Source: https://docs.rotastellar.com/api-reference/deployments/list-deployments GET /api/deployments List all deployments for the authenticated user **Base URL:** `https://console.rotastellar.com` — Requires session cookie or API key authentication. ## Request No parameters required. Returns the 50 most recent deployments for the authenticated user. ```bash cURL theme={null} curl https://console.rotastellar.com/api/deployments \ -H "Cookie: session=..." ``` ```bash API Key theme={null} curl https://console.rotastellar.com/api/deployments \ -H "X-API-Key: rs_live_..." ``` ```json 200 OK theme={null} { "deployments": [ { "id": "dep-456", "mission_id": "mis-123", "plan_id": "plan-789", "satellite_id": "25544", "status": "completed", "mode": "simulated", "speed_multiplier": 100, "started_at": "2026-03-07T12:00:05Z", "completed_at": "2026-03-07T12:01:32Z", "created_at": "2026-03-07T12:00:00Z", "mission_name": "ISS ML Pipeline", "sat_norad_id": "25544", "plan_label": "On-Board ML Inference" } ] } ``` ## Response Fields | Field | Type | Description | | ------------------ | ------ | ---------------------------------------------------------------------- | | `id` | string | Deployment ID | | `mission_id` | string | Parent mission ID | | `plan_id` | string | Source plan ID | | `satellite_id` | string | NORAD catalog ID | | `status` | string | `pending`, `dispatched`, `running`, `completed`, `failed`, `cancelled` | | `mode` | string | `simulated` or `live` | | `speed_multiplier` | number | Simulation speed (simulated mode only) | | `started_at` | string | ISO 8601 timestamp when execution started | | `completed_at` | string | ISO 8601 timestamp when execution finished | | `created_at` | string | ISO 8601 timestamp when deployment was created | | `mission_name` | string | Name of the parent mission | | `plan_label` | string | Label of the source plan | # API Directory Source: https://docs.rotastellar.com/api-reference/directory Consolidated directory of all RotaStellar public APIs # API Directory RotaStellar exposes three categories of public APIs across multiple services. Each service is independently deployed and has its own base URL. Internal Console APIs (session-authenticated) are documented in **Mission Control > Admin > API Directory** for authorized operators only. *** ## External APIs Public APIs requiring a Bearer API key (`rs_...`). Available to all developers. ### Satellite Intelligence API **Base URL:** `https://api.rotastellar.com/v1` **Auth:** Bearer API key **Docs:** [Full reference →](/api-reference) | Method | Endpoint | Description | | ------ | ------------------------------ | ---------------------------------------- | | GET | `/satellites/active` | Active satellites with live orbital data | | GET | `/satellites` | List satellites with filters | | GET | `/satellites/{id}` | Satellite details | | GET | `/satellites/{id}/position` | Current position (lat/lon/alt) | | GET | `/satellites/{id}/orbit` | Orbital parameters | | GET | `/satellites/{id}/visibility` | Ground station visibility | | GET | `/satellites/{id}/passes` | Predict ground passes | | GET | `/satellites/{id}/feasibility` | Compute feasibility analysis | | GET | `/satellites/{id}/latency` | Communication latency analysis | | GET | `/conjunctions` | Conjunction (collision) analysis | | GET | `/patterns` | Anomaly and maneuver detection | | GET | `/ground-stations` | Ground station network (12 stations) | **Planning endpoints:** | Method | Endpoint | Description | | ------ | ------------------- | -------------------- | | POST | `/planning/analyze` | Feasibility analysis | | POST | `/planning/thermal` | Thermal simulation | | POST | `/planning/latency` | Latency simulation | **15 endpoints** — Intelligence + Planning *** ### Workloads API (Control Plane) The developer API to run, track, and control workloads on the orbital fleet. One submission surface — the workload **class** (`single`, `data-parallel`, `spatial`, `federated`, `model-parallel`, `split-learning`) drives execution; the CAE places it and the durable lifecycle runs it. **Base URL:** `https://api.rotastellar.com/v1` **Auth:** Bearer API key | Method | Endpoint | Description | | ------ | ------------------------------ | --------------------------------------------------------------------------------------------------------- | | POST | `/v1/workloads` | Submit (run) a workload of any class | | POST | `/v1/workloads/preview` | **Plan** — the CAE verdict (feasibility + cut/partition + ISL-bound) **+ cost estimate**, without running | | GET | `/v1/workloads` | List your workloads (newest first) | | GET | `/v1/workloads/{id}` | Status + placement + outcome (poll `phase`) | | GET | `/v1/workloads/{id}/stages` | Per-satellite execution — which satellite ran each stage | | GET | `/v1/workloads/{id}/artifacts` | The result manifest (outputs + how to fetch each) | | POST | `/v1/workloads/{id}/cancel` | Stop a queued/running workload | **7 endpoints** — plan → run → track → retrieve → cancel. A *frontier* workload (`model-parallel` / `split-learning`) runs as a pipeline across the constellation; `distributed-training` is ISL-bound, so it's preview-only. Full guide: [Workloads →](/api-reference/workloads). *** ### Constraint-Aware Execution (CAE) **Base URL:** `https://rotastellar-cae.subhadip-mitra.workers.dev` **Auth:** None (CORS-restricted to allowed origins) **Docs:** [CAE reference →](/api-reference/cae/service-index) | Method | Endpoint | Description | | ------ | ---------------------------- | ---------------------------------------- | | GET | `/v1` | Service index and capabilities | | GET | `/v1/presets` | List workload presets | | POST | `/v1/plan` | Create execution plan (single satellite) | | GET | `/v1/plan/{id}` | Retrieve a plan | | GET | `/v1/plan/{id}/events` | Simulated execution events | | POST | `/v1/ocu/negotiate` | OCU Negotiator — match workload to fleet | | GET | `/v1/ocu/summary/{busClass}` | OCU capacity for a satellite class | | POST | `/v1/hazards` | Predict orbital hazards + checkpoints | | POST | `/v1/constellation/plan` | Multi-satellite DAG planning with ISL | | POST | `/v1/constellation/pareto` | Fleet-level Pareto frontier planning | | GET | `/v1/metrics` | Worker performance metrics | **11 endpoints** — Orbital compute orchestration *** ### Orbital Simulation (Sim) **Base URL:** `https://sim.rotastellar.com` **Auth:** None (CORS-restricted) **Docs:** [Sim reference →](/api-reference/sim/service-index) | Method | Endpoint | Description | | ------ | ----------------------------------------- | ----------------------------------- | | POST | `/v1/state` | Orbital state at a timestamp | | POST | `/v1/state/batch` | Batch state for multiple satellites | | POST | `/v1/propagate` | Full trajectory over time window | | POST | `/v1/passes` | Ground station pass computation | | POST | `/v1/orbital-params` | Orbital parameters from altitude | | GET | `/v1/templates` | Orbit templates | | GET | `/v1/constellation-templates` | Constellation patterns | | POST | `/v1/constellation-templates/{id}/expand` | Generate satellite definitions | | GET | `/v1/ground-stations` | Ground station network | **9 endpoints** — Stateless orbital computation *** ## Agent Protocol APIs APIs used by the RotaStellar Operator Agent running on satellites (real or simulated). Authenticated via API key + Agent-ID headers. **Base URL:** Console URL (e.g., `https://rotastellar.com`) **Auth:** `X-API-Key` + `X-Agent-ID` headers **Docs:** [Agent Protocol →](/agent/protocol) | Method | Endpoint | Description | | ------ | ------------------------------ | ------------------------------ | | POST | `/api/agent/register` | Register agent with Console | | GET | `/api/agent/workloads` | Poll for pending deployments | | POST | `/api/agent/telemetry` | Report health/status heartbeat | | POST | `/api/deployments/{id}/events` | Report execution events | **4 endpoints** — Pull-based satellite agent protocol *** ## Summary | Service | Endpoints | Auth Method | Base URL | | ----------------------------- | --------- | ------------------ | ----------------------------- | | Intelligence API | 15 | Bearer API key | `api.rotastellar.com/v1` | | Workloads API (Control Plane) | 7 | Bearer API key | `api.rotastellar.com/v1` | | CAE | 11 | CORS-restricted | `rotastellar-cae.workers.dev` | | Sim | 9 | CORS-restricted | `sim.rotastellar.com` | | Agent Protocol | 4 | API key + Agent-ID | Console URL | | **Total** | **46** | | | Internal Console APIs (88 routes for auth, billing, admin, missions, etc.) are documented in the Console's **Admin > API Directory** page, accessible to authenticated administrators only. # Batch State Source: https://docs.rotastellar.com/api-reference/sim/batch-state POST /v1/state/batch Compute orbital state for up to 100 satellites at once **Base URL:** `https://sim.rotastellar.com` — No API key required. ## Request Array of satellite objects, each with `id` (string) and `elements` (orbital elements object). Maximum 100 satellites per request. ISO 8601 timestamp for computation. Defaults to current time. ```bash theme={null} curl -X POST https://sim.rotastellar.com/v1/state/batch \ -H "Content-Type: application/json" \ -d '{ "satellites": [ { "id": "rs-leo-1", "elements": { "altitude_km": 550, "inclination_deg": 51.6, "raan_deg": 0, "mean_anomaly_deg": 0 } }, { "id": "rs-leo-2", "elements": { "altitude_km": 550, "inclination_deg": 51.6, "raan_deg": 0, "mean_anomaly_deg": 180 } } ], "timestamp": "2026-03-08T12:00:00Z" }' ``` ```json 200 OK theme={null} { "states": { "rs-leo-1": { "lat": 42.15, "lon": -73.82, "altitude_km": 550.3, "velocity_km_s": 7.59, "in_eclipse": false, "orbit_fraction": 0.234 }, "rs-leo-2": { "lat": -38.90, "lon": 106.18, "altitude_km": 550.1, "velocity_km_s": 7.59, "in_eclipse": true, "orbit_fraction": 0.734 } }, "timestamp": "2026-03-08T12:00:00Z", "count": 2 } ``` ```json 400 Too Many theme={null} { "error": "too_many", "message": "Maximum 100 satellites per batch request" } ``` ## Errors | Status | Code | Description | | ------ | ------------------- | ----------------------------------- | | 400 | `invalid_request` | `satellites` array missing or empty | | 400 | `too_many` | More than 100 satellites | | 400 | `invalid_timestamp` | Invalid ISO 8601 timestamp | # Create Session Source: https://docs.rotastellar.com/api-reference/sim/create-session POST /v1/sessions Creates a new simulation session with the given satellite constellation **Base URL:** `https://sim.rotastellar.com` — No API key required. ```bash theme={null} curl -X POST https://sim.rotastellar.com/v1/sessions \ -H "Content-Type: application/json" \ -d '{ "satellites": [ { "id": "sat-001", "name": "RS-LEO-1", "elements": { "altitude_km": 550, "inclination_deg": 53 } }, { "id": "sat-002", "name": "RS-LEO-2", "elements": { "altitude_km": 550, "inclination_deg": 53 } }, { "id": "sat-003", "name": "RS-LEO-3", "elements": { "altitude_km": 600, "inclination_deg": 97.4 } } ] }' ``` ```json 200 OK theme={null} { "session_id": "ses_abc123", "satellites": 3, "created_at": "2026-03-10T12:00:00Z" } ``` # Get Session State Source: https://docs.rotastellar.com/api-reference/sim/get-session GET /v1/sessions/{sessionId} Returns the full state of a simulation session including satellite positions, subsystems, and events **Base URL:** `https://sim.rotastellar.com` — No API key required. ### Path Parameters | Parameter | Type | Description | | ----------- | ------ | ------------------------------------------- | | `sessionId` | string | The session ID returned from Create Session | ```bash theme={null} curl https://sim.rotastellar.com/v1/sessions/ses_abc123 ``` ```json 200 OK theme={null} { "session_id": "ses_abc123", "epoch": "2026-03-10T12:05:00Z", "tick_count": 5, "satellites": [ { "id": "sat-001", "name": "RS-LEO-1", "position": { "lat_deg": 32.4, "lon_deg": -118.2, "alt_km": 548.7 }, "velocity_km_s": 7.59, "sunlit": true, "subsystems": { "power_w": 115, "thermal_c": 22.4, "comms_dbm": -82, "memory_used_mb": 1024 }, "faults": [] }, { "id": "sat-002", "name": "RS-LEO-2", "position": { "lat_deg": -14.1, "lon_deg": 45.8, "alt_km": 550.1 }, "velocity_km_s": 7.59, "sunlit": true, "subsystems": { "power_w": 118, "thermal_c": 21.8, "comms_dbm": -79, "memory_used_mb": 512 }, "faults": [] } ], "isl_links": [ { "from": "sat-001", "to": "sat-002", "distance_km": 1240, "latency_ms": 4.1, "active": true } ], "recent_events": [ { "epoch": "2026-03-10T12:03:00Z", "type": "eclipse_exit", "satellite": "sat-001" } ] } ``` # Get State Source: https://docs.rotastellar.com/api-reference/sim/get-state POST /v1/state Compute satellite position, velocity, and eclipse status at a timestamp **Base URL:** `https://sim.rotastellar.com` — No API key required. ## Request Orbital elements defining the satellite orbit. Must include either `altitude_km` or `mean_motion`, plus `inclination_deg`. See [Orbital Elements](/sim/overview#orbital-elements) for full schema. ISO 8601 timestamp for computation. Defaults to current time. ```bash theme={null} curl -X POST https://sim.rotastellar.com/v1/state \ -H "Content-Type: application/json" \ -d '{ "elements": { "altitude_km": 550, "inclination_deg": 53, "eccentricity": 0.0001, "raan_deg": 0, "mean_anomaly_deg": 0, "epoch": "2026-03-08T00:00:00Z" }, "timestamp": "2026-03-08T12:00:00Z" }' ``` ```python Python theme={null} import requests response = requests.post( "https://sim.rotastellar.com/v1/state", json={ "elements": { "altitude_km": 550, "inclination_deg": 53 } } ) state = response.json() print(f"Position: {state['lat']:.2f}°, {state['lon']:.2f}°") print(f"Eclipse: {state['in_eclipse']}") ``` ```json 200 OK theme={null} { "lat": 42.15, "lon": -73.82, "altitude_km": 550.3, "velocity_km_s": 7.59, "in_eclipse": false, "orbit_fraction": 0.234, "timestamp": "2026-03-08T12:00:00Z" } ``` ```json 400 Invalid Elements theme={null} { "error": "invalid_elements", "message": "elements must include altitude_km or mean_motion, and inclination_deg" } ``` ## Response Fields | Field | Type | Description | | ---------------- | ------- | -------------------------------------- | | `lat` | number | Geodetic latitude (degrees) | | `lon` | number | Geodetic longitude (degrees) | | `altitude_km` | number | Height above WGS-84 ellipsoid | | `velocity_km_s` | number | Orbital velocity | | `in_eclipse` | boolean | Whether satellite is in Earth's shadow | | `orbit_fraction` | number | Position in orbit (0–1) | | `timestamp` | string | ISO 8601 computation timestamp | # Inject Fault Source: https://docs.rotastellar.com/api-reference/sim/inject-fault POST /v1/sessions/{sessionId}/fault Injects a fault into a satellite within a simulation session **Base URL:** `https://sim.rotastellar.com` — No API key required. ### Path Parameters | Parameter | Type | Description | | ----------- | ------ | ------------------------------------------- | | `sessionId` | string | The session ID returned from Create Session | ### Fault Types | Type | Description | | -------------------- | ------------------------------------------------------------ | | `power_loss` | Reduces available power generation | | `thermal_exceedance` | Raises subsystem temperature beyond nominal range | | `radiation_upset` | Simulates single-event upset from radiation | | `comms_failure` | Degrades or disables communication links | | `isl_degradation` | Reduces inter-satellite link bandwidth and increases latency | ```bash theme={null} curl -X POST https://sim.rotastellar.com/v1/sessions/ses_abc123/fault \ -H "Content-Type: application/json" \ -d '{ "satellite_id": "sat-001", "fault_type": "power_loss", "severity": 0.8 }' ``` ```json 200 OK theme={null} { "session_id": "ses_abc123", "satellite": { "id": "sat-001", "name": "RS-LEO-1", "position": { "lat_deg": 33.8, "lon_deg": -114.5, "alt_km": 548.6 }, "sunlit": true, "subsystems": { "power_w": 23, "thermal_c": 22.6, "comms_dbm": -81, "memory_used_mb": 1028 }, "faults": [ { "type": "power_loss", "severity": 0.8, "injected_at": "2026-03-10T12:06:00Z", "effect": "power_generation reduced by 80%" } ] } } ``` # Ground Passes Source: https://docs.rotastellar.com/api-reference/sim/passes POST /v1/passes Compute ground station AOS/LOS windows with elevation data **Base URL:** `https://sim.rotastellar.com` — No API key required. ## Request Orbital elements. See [Orbital Elements](/sim/overview#orbital-elements). ISO 8601 start time. Defaults to current time. Prediction window in hours. Default: 24. Max: 72. Minimum satellite elevation above horizon (degrees). Default: 5. Custom ground station list. Defaults to the 12-station global network (KSAT, NASA, AWS). Each station needs `id`, `name`, `lat`, `lon`. ```bash theme={null} curl -X POST https://sim.rotastellar.com/v1/passes \ -H "Content-Type: application/json" \ -d '{ "elements": { "altitude_km": 550, "inclination_deg": 53 }, "duration_hours": 24, "min_elevation_deg": 10 }' ``` ```json 200 OK theme={null} { "passes": [ { "station_id": "gs_svalbard", "station_name": "Svalbard", "provider": "KSAT", "aos": "2026-03-08T12:34:56Z", "los": "2026-03-08T12:45:23Z", "duration_s": 627, "max_elevation_deg": 45.6, "points": [ { "timestamp": "2026-03-08T12:34:56Z", "elevation_deg": 10.0, "azimuth_deg": 90.5, "range_km": 2500.1 } ] } ], "count": 8, "start": "2026-03-08T12:00:00Z", "duration_hours": 24, "stations_checked": 12 } ``` ## Default Ground Stations The service includes a 12-station global network: | Station | Location | Provider | | --------- | --------------- | -------- | | Svalbard | 78.2°N, 15.4°E | KSAT | | Troll | 72.0°S, 2.5°E | KSAT | | Awarua | 46.5°S, 168.4°E | KSAT | | Fairbanks | 64.9°N, 147.9°W | NASA | | Wallops | 37.9°N, 75.5°W | NASA | | McMurdo | 77.9°S, 166.7°E | NASA | | Singapore | 1.4°N, 103.8°E | AWS | | Bahrain | 26.1°N, 50.5°E | AWS | | Oregon | 43.8°N, 120.6°W | AWS | | Cape Town | 33.9°S, 18.4°E | AWS | | Stockholm | 59.3°N, 18.1°E | AWS | | Sydney | 33.9°S, 151.2°E | AWS | # Propagate Trajectory Source: https://docs.rotastellar.com/api-reference/sim/propagate POST /v1/propagate Generate full satellite trajectory as a time series over up to 48 hours **Base URL:** `https://sim.rotastellar.com` — No API key required. ## Request Orbital elements. See [Orbital Elements](/sim/overview#orbital-elements). ISO 8601 start time. Defaults to current time. ISO 8601 end time. Default: start + 6 hours. Max window: 48 hours. Seconds between trajectory points. Default: 60. Max 5,000 total points. ```bash theme={null} curl -X POST https://sim.rotastellar.com/v1/propagate \ -H "Content-Type: application/json" \ -d '{ "elements": { "altitude_km": 550, "inclination_deg": 53 }, "start": "2026-03-08T12:00:00Z", "end": "2026-03-08T14:00:00Z", "step_s": 60 }' ``` ```json 200 OK theme={null} { "trajectory": [ { "t": "2026-03-08T12:00:00Z", "lat": 42.15, "lon": -73.82, "altitude_km": 550.3, "velocity_km_s": 7.59, "in_eclipse": false, "orbit_fraction": 0.000 }, { "t": "2026-03-08T12:01:00Z", "lat": 42.58, "lon": -72.14, "altitude_km": 550.3, "velocity_km_s": 7.59, "in_eclipse": false, "orbit_fraction": 0.010 } ], "count": 121, "start": "2026-03-08T12:00:00Z", "end": "2026-03-08T14:00:00Z", "step_s": 60 } ``` ```json 400 Range Too Large theme={null} { "error": "range_too_large", "message": "Propagation window exceeds 48 hours" } ``` ## Constraints | Constraint | Limit | | -------------- | ---------- | | Max window | 48 hours | | Max points | 5,000 | | Default step | 60 seconds | | Default window | 6 hours | # Service Index Source: https://docs.rotastellar.com/api-reference/sim/service-index GET /v1 Returns service metadata and available endpoints **Base URL:** `https://sim.rotastellar.com` — No API key required. ```bash theme={null} curl https://sim.rotastellar.com/v1 ``` ```json 200 OK theme={null} { "service": "rotastellar-sim", "version": "1.0.0", "description": "Orbital Simulation — stateless orbital computation for satellite digital twins", "endpoints": [ { "method": "POST", "path": "/v1/state", "description": "Compute orbital state at a timestamp" }, { "method": "POST", "path": "/v1/state/batch", "description": "Batch orbital state for multiple satellites" }, { "method": "POST", "path": "/v1/propagate", "description": "Propagate trajectory over a time window" }, { "method": "POST", "path": "/v1/passes", "description": "Compute ground station passes" }, { "method": "POST", "path": "/v1/orbital-params", "description": "Derive orbital parameters from altitude" }, { "method": "GET", "path": "/v1/templates", "description": "List orbit templates" }, { "method": "GET", "path": "/v1/constellation-templates", "description": "List constellation templates" }, { "method": "GET", "path": "/v1/ground-stations", "description": "List ground station network" } ] } ``` # Templates Source: https://docs.rotastellar.com/api-reference/sim/templates GET /v1/templates Predefined orbit and constellation templates **Base URL:** `https://sim.rotastellar.com` — No API key required. ## Orbit Templates `GET /v1/templates` returns predefined orbit profiles. ```bash Orbit Templates theme={null} curl https://sim.rotastellar.com/v1/templates ``` ```bash Constellation Templates theme={null} curl https://sim.rotastellar.com/v1/constellation-templates ``` ```bash Expand Constellation theme={null} curl -X POST https://sim.rotastellar.com/v1/constellation-templates/walker-star-6-3/expand \ -H "Content-Type: application/json" \ -d '{"base_orbit": "leo-standard"}' ``` ```json 200 Orbit Templates theme={null} [ { "id": "leo-standard", "name": "LEO Standard", "altitude_km": 550, "inclination_deg": 53, "eccentricity": 0.0001, "description": "Standard low-Earth orbit at 550 km" }, { "id": "leo-low", "name": "LEO Low", "altitude_km": 420, "inclination_deg": 51.6, "eccentricity": 0.0002, "description": "Low LEO at ISS altitude" }, { "id": "sun-sync-500", "name": "Sun-Synchronous 500km", "altitude_km": 500, "inclination_deg": 97.4, "eccentricity": 0.0001, "description": "Dawn-dusk sun-synchronous orbit" }, { "id": "sun-sync-700", "name": "Sun-Synchronous 700km", "altitude_km": 700, "inclination_deg": 98.2, "eccentricity": 0.0001, "description": "Higher sun-synchronous orbit" }, { "id": "polar-800", "name": "Polar 800km", "altitude_km": 800, "inclination_deg": 98.7, "eccentricity": 0.0001, "description": "Near-polar orbit" }, { "id": "meo-navigation", "name": "MEO Navigation", "altitude_km": 20200, "inclination_deg": 55, "eccentricity": 0.001, "description": "Medium Earth orbit (GPS/Galileo)" }, { "id": "geo-comms", "name": "Geostationary", "altitude_km": 35786, "inclination_deg": 0, "eccentricity": 0.0001, "description": "Geostationary orbit" } ] ``` ```json 200 Constellation Templates theme={null} [ { "id": "walker-star-6-3", "name": "Walker Star 6/3/1", "satellite_count": 6, "planes": 3, "sats_per_plane": 2, "base_orbit": "leo-standard", "description": "6 satellites across 3 orbital planes" }, { "id": "walker-star-12-4", "name": "Walker Star 12/4/1", "satellite_count": 12, "planes": 4, "sats_per_plane": 3, "base_orbit": "leo-standard", "description": "12 satellites across 4 planes" }, { "id": "polar-ring-4", "name": "Polar Ring", "satellite_count": 4, "planes": 2, "sats_per_plane": 2, "base_orbit": "sun-sync-500", "description": "4 satellites in 2 sun-synchronous planes" }, { "id": "single-plane-3", "name": "Single Plane Trio", "satellite_count": 3, "planes": 1, "sats_per_plane": 3, "base_orbit": "leo-standard", "description": "3 satellites in a single plane" } ] ``` ## Expand Constellation `POST /v1/constellation-templates/:id/expand` generates per-satellite orbital elements from a constellation template. Override the template's base orbit. Must be a valid orbit template ID (e.g., `leo-standard`, `sun-sync-500`). The response includes an `orbits` array with fully resolved orbital elements for each satellite, including computed RAAN spacing and mean anomaly offsets. # Tick Session Source: https://docs.rotastellar.com/api-reference/sim/tick-session POST /v1/sessions/{sessionId}/tick Advances the simulation by a given duration and returns the updated state **Base URL:** `https://sim.rotastellar.com` — No API key required. ### Path Parameters | Parameter | Type | Description | | ----------- | ------ | ------------------------------------------- | | `sessionId` | string | The session ID returned from Create Session | ```bash theme={null} curl -X POST https://sim.rotastellar.com/v1/sessions/ses_abc123/tick \ -H "Content-Type: application/json" \ -d '{ "duration_s": 60 }' ``` ```json 200 OK theme={null} { "session_id": "ses_abc123", "epoch": "2026-03-10T12:06:00Z", "tick_count": 6, "duration_s": 60, "satellites": [ { "id": "sat-001", "name": "RS-LEO-1", "position": { "lat_deg": 33.8, "lon_deg": -114.5, "alt_km": 548.6 }, "velocity_km_s": 7.59, "sunlit": true, "subsystems": { "power_w": 116, "thermal_c": 22.6, "comms_dbm": -81, "memory_used_mb": 1028 }, "faults": [] } ], "isl_links": [ { "from": "sat-001", "to": "sat-002", "distance_km": 1235, "latency_ms": 4.1, "active": true } ], "events": [ { "epoch": "2026-03-10T12:05:30Z", "type": "isl_handover", "from": "sat-002", "to": "sat-003" } ] } ``` # Workloads Source: https://docs.rotastellar.com/api-reference/workloads Run, preview, track, and control workloads on the orbital fleet — one API, class-driven. A **workload** is a unit of compute you run on the satellite fleet. There is **one submission surface** — `POST /v1/workloads` — and the workload's **class** decides how it executes: | `parallelism.class` | Runs as | | ------------------- | ------------------------------------------------------------------- | | `single` (default) | one satellite (the CAE places it) | | `data-parallel` | sharded across satellites, recombined on the ground | | `spatial` | each satellite processes its footprint of an area-of-interest | | `federated` | a global model trained from on-board data (only deltas leave orbit) | | `model-parallel` | a pipeline split across satellites — activations flow stage → stage | | `split-learning` | a head on the data-owning satellite, the heavy tail offloaded | **Base URL:** `https://api.rotastellar.com/v1` · **Auth:** `Authorization: Bearer rs_...` ## Lifecycle `preview` (optional) → `submit` → poll `GET /{id}` → inspect `stages` / `artifacts` → `cancel` (any time). ## Preview — the plan `POST /v1/workloads/preview` returns the CAE's verdict — feasibility, the model cut/partition, whether it's ISL-bound — **and a cost estimate**, *without running anything* (read-only; no quota, no billing). It's the "plan" to submit's "apply". ```bash theme={null} curl -X POST https://api.rotastellar.com/v1/workloads/preview \ -H "Authorization: Bearer $RS_API_KEY" -H "content-type: application/json" -d '{ "placement": { "satellites": [25544, 48274, 53807] }, "parallelism": { "class": "model-parallel", "stages": 3 }, "model": { "layers": [{"name":"embed","compute_fwd":2,"activation_mb":4}] } }' ``` ```json theme={null} { "kind": "model_parallel", "candidates": 3, "plan": { "feasible": true, "stages": 3, "partition": [/* ... */], "isl_bound": false }, "cost_estimate": { "ocu": 450, "cents": 5400, "per_stage_ocu": 150, "stages": 3, "price_per_ocu_cents": 12 } } ``` `distributed-training` is ISL-bound (gradient AllReduce over sparse inter-satellite links), so it is **preview-only** — preview it to see the honest verdict; it is not executable. ## Submit — run `POST /v1/workloads` takes the same body and executes it. Returns the id + a `status_url`. ```json theme={null} { "id": "wl_9a0b…", "status": "scheduling", "status_url": "/v1/workloads/wl_9a0b…" } ``` A frontier workload (`model-parallel` / `split-learning`) runs as a pipeline across the constellation — the CAE places each stage on a satellite, and the stages run in sequence as a coordinated pipeline. ## Track status Poll `GET /v1/workloads/{id}` and read `phase`: `submitted → scheduling → dispatching → awaiting_report → done` (or `failed` / `timed_out` / `canceled`). `workflow_status` is the coarse pill (`RUNNING` / `COMPLETED` / `FAILED` / …). The response also carries `placement`, the structured `outcome`, the `result` manifest, and `cost` once billable. ## Stages — per-satellite execution `GET /v1/workloads/{id}/stages` — for a frontier / scatter-gather workload, which satellite ran each stage and its status. ```json theme={null} { "id": "wl_9a0b…", "stages": [ { "index": 0, "satellite": "48274", "satellite_name": "CSS (TIANHE)", "status": "done", "role": "stage" }, { "index": 1, "satellite": "25544", "satellite_name": "ISS (ZARYA)", "status": "done", "role": "stage" } ] } ``` ## Results & cancel * `GET /v1/workloads/{id}/artifacts` — the result manifest (the outputs + how to fetch each: custodied `contentId` or external `uri`). * `POST /v1/workloads/{id}/cancel` — stop a queued or running workload; its queued / in-flight stages are dropped. ## SDKs & CLI Every operation is in the SDKs and the CLI: ```python theme={null} rs.workloads.preview(placement={...}, parallelism={"class": "model-parallel", "stages": 3}, model={...}) wl = rs.workloads.submit(type="fine-tune", placement={...}, parallelism={...}, model={...}) rs.workloads.get(wl["id"]); rs.workloads.stages(wl["id"]); rs.workloads.cancel(wl["id"]) ``` ```bash theme={null} rotastellar jobs preview --file workload.json rotastellar jobs submit --file workload.json rotastellar jobs get ; rotastellar jobs stages ; rotastellar jobs cancel ``` # Authentication Source: https://docs.rotastellar.com/authentication Secure your API requests # Authentication The RotaStellar API uses API keys for authentication. All requests must include a valid API key. ## Getting an API Key Sign up for [early access](https://rotastellar.com/developers) to receive your API credentials. You'll receive an email with your API key (starts with `rs_`). Store your API key securely. Never commit it to version control. ## Using Your API Key Include your API key in the `Authorization` header with the `Bearer` prefix: ```bash theme={null} Authorization: Bearer rs_your_api_key ``` ### Example Request ```bash cURL theme={null} curl https://api.rotastellar.com/v1/satellites/ISS \ -H "Authorization: Bearer rs_your_api_key" ``` ```python Python theme={null} from rotastellar import RotaStellarClient # From parameter client = RotaStellarClient(api_key="rs_your_api_key") # Or from environment variable # export ROTASTELLAR_API_KEY=rs_your_api_key client = RotaStellarClient() # Reads from env ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; // From parameter const client = new RotaStellarClient({ apiKey: 'rs_your_api_key' }); // Or from environment variable // export ROTASTELLAR_API_KEY=rs_your_api_key const client = new RotaStellar(); // Reads from env ``` ```rust Rust theme={null} use rotastellar::RotaStellar; // From parameter let client = RotaStellar::new("rs_your_api_key")?; // Or from environment variable // export ROTASTELLAR_API_KEY=rs_your_api_key let client = RotaStellar::from_env()?; ``` ## API Key Types | Type | Prefix | Use Case | | ---- | ---------- | ----------------------- | | Live | `rs_live_` | Production applications | | Test | `rs_test_` | Development and testing | Test keys have rate limits and may return simulated data. Use live keys for production applications. ## Security Best Practices API keys should only be used in server-side code. Never include them in JavaScript bundles, mobile apps, or anywhere users can inspect. Store API keys in environment variables, not in code: ```bash theme={null} export ROTASTELLAR_API_KEY=rs_live_... ``` Rotate your API keys periodically and immediately if you suspect compromise. Use different API keys for development, staging, and production. ## Revoking Keys If your API key is compromised: 1. Go to your [dashboard](https://rotastellar.com/dashboard/) 2. Navigate to API Keys 3. Click "Revoke" on the compromised key 4. Generate a new key 5. Update your applications ## Errors | Code | Description | | ----- | ------------------------------------------------- | | `401` | Invalid or missing API key | | `403` | API key doesn't have permission for this endpoint | | `429` | Rate limit exceeded | ```json theme={null} { "error": { "code": "invalid_api_key", "message": "The API key provided is invalid or has been revoked." } } ``` # Constellation DAG Source: https://docs.rotastellar.com/cae/constellation-dag I-3 — multi-satellite workflow orchestration with ISL routing # Constellation DAG Single-satellite planning assigns steps to orbital windows on one spacecraft. Constellation DAG planning distributes a workload across multiple satellites, routing intermediate data through inter-satellite links (ISL) and ground relays to minimize end-to-end latency. **When to use this** — Any workload that benefits from parallelism across satellites, or where a single satellite lacks the resources (compute, power, storage, contact time) to complete the job within the deadline. ## Architecture Constellation planning is built on two core components: ### ContactGraph The ContactGraph builds a time-expanded graph of all communication opportunities across the fleet within the planning horizon. | Capability | Details | | --------------------- | -------------------------------------------------------------------------------- | | ISL detection | Line-of-sight between satellite pairs, accounting for Earth obstruction | | Ground pass detection | Visibility windows to all 12 ground stations per satellite | | Routing algorithm | Time-expanded Dijkstra — finds shortest-latency path through ISL and ground hops | | Fleet construction | `buildContactGraph` generates the full fleet graph from TLE data | The graph edges are weighted by link capacity (data rate x duration) and propagation delay. Dijkstra finds the minimum-latency path for transferring data from any satellite to any other satellite or ground station. ### ConstellationPlacer The placer runs a 5-phase algorithm to assign steps to satellites: | Phase | Description | | -------------------- | --------------------------------------------------------------------------------------------------------------------- | | 1. Preparation | Propagate orbits, build contact graph, compute per-satellite resource envelopes | | 2. Greedy placement | Score each satellite for each step (resource fit, data locality, contact opportunity) and assign greedily by priority | | 3. Replication | For critical steps, place redundant copies on backup satellites for fault tolerance | | 4. Schedule assembly | Build the final timeline with ISL transfer segments between cross-satellite dependencies | | 5. Metrics | Compute critical path, reliability estimate, and resource utilization | **Scoring** considers four factors: available compute capacity, proximity to upstream data, upcoming contact windows, and current battery state-of-charge. For fleets of 10 or more satellites, the placer uses a k-d tree spatial index to accelerate nearest-neighbor queries during ISL detection. This keeps planning time sub-linear with fleet size. ## ISL Transfer Segments When two dependent steps are placed on different satellites, the planner inserts ISL transfer segments. These are scheduled during mutual visibility windows and include FEC overhead. ```json theme={null} { "type": "isl_transfer", "from_satellite": "25544", "to_satellite": "48274", "data_mb": 36.75, "fec_overhead_mb": 1.84, "link_budget": { "distance_km": 1240, "data_rate_mbps": 10, "duration_s": 31 }, "window": { "start": "2026-03-10T08:12:00Z", "end": "2026-03-10T08:18:30Z" } } ``` If no direct ISL path exists, the contact graph routes through intermediate satellites or ground relay (satellite A downlinks to a ground station, which uplinks to satellite B during a later pass). ## API Usage ### Create Constellation Plan ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/constellation/plan \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{ "satellite_ids": ["25544", "48274", "55909"], "custom_job": { "name": "Distributed EO Pipeline", "steps": [ { "id": "capture_1", "name": "Capture Region A", "location": "onboard", "compute_s": 60, "output_mb": 2000, "depends_on": [] }, { "id": "capture_2", "name": "Capture Region B", "location": "onboard", "compute_s": 60, "output_mb": 2000, "depends_on": [] }, { "id": "merge", "name": "Merge and Mosaic", "location": "onboard", "compute_s": 180, "input_mb": 4000, "output_mb": 500, "depends_on": ["capture_1", "capture_2"] }, { "id": "downlink", "name": "Deliver Results", "location": "ground", "depends_on": ["merge"] } ], "policy": { "objective": "min_latency", "deadline_orbits": 6 } } }' ``` ### Request Parameters | Parameter | Type | Required | Description | | ------------------------ | --------- | -------- | ------------------------------------------------------------ | | `satellite_ids` | string\[] | Yes | NORAD catalog IDs of satellites in the constellation | | `preset_id` | string | No | Use a preset workload (mutually exclusive with `custom_job`) | | `custom_job` | object | No | Custom DAG definition | | `policy.objective` | string | No | `min_latency`, `balanced`, `max_reliability` | | `policy.deadline_orbits` | number | No | Maximum orbits to complete the workflow | | `replication_factor` | number | No | Number of redundant copies for critical steps (default: 1) | ### Response Structure The response extends the standard plan format with constellation-specific fields: ```json theme={null} { "id": "const-7b2e4f...", "constellation": { "satellites_used": 3, "satellites_available": 3, "isl_transfers": 2, "ground_relays": 0 }, "critical_path": { "steps": ["capture_1", "isl_transfer_1", "merge", "downlink"], "duration_s": 4320, "bottleneck": "isl_transfer_1" }, "metrics": { "total_compute_s": 300, "total_transfer_s": 186, "isl_data_mb": 2038.5, "ground_data_mb": 525, "reliability": 0.964, "satellites_used": 3 }, "placements": [ { "step_id": "capture_1", "satellite_id": "25544", "reason": "best_resource_fit" }, { "step_id": "capture_2", "satellite_id": "48274", "reason": "best_resource_fit" }, { "step_id": "merge", "satellite_id": "55909", "reason": "data_locality" } ], "plan": { ... }, "events": [ ... ] } ``` ## Metrics | Metric | Description | | -------------------------- | ------------------------------------------------------------ | | `critical_path.duration_s` | Longest sequential chain through the DAG including transfers | | `critical_path.bottleneck` | The step or transfer that dominates the critical path | | `satellites_used` | Number of satellites with at least one assigned step | | `isl_transfers` | Number of inter-satellite link transfers in the plan | | `reliability` | Combined delivery confidence across all paths | ## Console Integration The Console displays constellation plans in a **DAG tab** powered by React Flow: * Each satellite is a swim lane * Steps are nodes, colored by satellite assignment * ISL transfers appear as animated edges between lanes * The critical path is highlighted * Clicking a node shows step detail, resource usage, and the scoring breakdown from the placement phase Constellation planning requires valid TLE data for all satellites in the request. If any satellite ID is not found in the CelesTrak catalog, the request returns a 400 error with the missing IDs listed. Multi-objective optimization for constellation plans Agent constellation mode for multi-satellite execution # Custom Workloads Source: https://docs.rotastellar.com/cae/custom-workloads Define your own orbital compute DAGs # Custom Workloads Instead of using a [preset](/cae/presets), you can define arbitrary step DAGs with `custom_job` in your plan request. The planner handles placement, transfer insertion, and scheduling the same way it does for presets. ## Request Structure Send `custom_job` instead of `preset_id` in `POST /v1/plan`: ```json theme={null} { "satellite_id": "25544", "custom_job": { "name": "My Pipeline", "steps": [ ... ], "security": { ... }, "policy": { ... } } } ``` ## Step Schema Each step in the `steps` array: Unique identifier within the job. Used in `depends_on` references. Human-readable step name. Where the step runs: `onboard`, `ground`, or `either`. When set to `either`, the planner decides based on data reduction ratio and transfer cost. Execution duration in seconds. Must be positive. IDs of prerequisite steps. Use `[]` for steps with no dependencies. Resource requirements: * `power_w` — Power consumption in watts * `compute` — Fraction of compute capacity (0.0–1.0) * `thermal_w` — Thermal dissipation in watts * `memory_mb` — Memory required in MB * `storage_mb` — Storage required in MB Input data size in MB. Output data size in MB. Output/input ratio. `0.1` means 10:1 reduction. Set to `null` for data-generating steps. Checkpoint frequency in seconds. `0` disables checkpointing. `fail`, `retry_next_window`, or `retry_immediate`. Maximum retry attempts. `none`, `aes128`, or `aes256`. Adds data expansion overhead. `none`, `crc32`, or `sha256`. Fault tolerance. If set, provide `min_data_fraction` (0.0–1.0) and `reduced_duration_s`. ## Security Overrides Optional `security` object at the job level: ```json theme={null} "security": { "encryption": "aes256", "data_classification": "restricted", "require_authenticated_uplink": true, "key_rotation_orbits": 24 } ``` Defaults: AES-256 encryption, `restricted` classification, authenticated uplink, key rotation every 24 orbits. ## Policy Optional `policy` object: ```json theme={null} "policy": { "objective": "balanced", "deadline_orbits": 6, "max_data_loss_fraction": 0.01, "min_delivery_confidence": 0.95 } ``` | Field | Options | Default | | ------------------------- | ---------------------------------------------------------- | ------------ | | `objective` | `min_latency`, `min_energy`, `max_reliability`, `balanced` | `balanced` | | `deadline_orbits` | Number of orbital periods | `6` | | `max_data_loss_fraction` | 0.0–1.0 | `0.01` (1%) | | `min_delivery_confidence` | 0.0–1.0 | `0.95` (95%) | ## Validation Rules * Every step must have a unique `id` * `depends_on` references must point to existing step IDs * No circular dependencies (validated via DFS) * `location` must be `onboard`, `ground`, or `either` * `duration_s` must be positive * `requires` must include all 5 resource fields Invalid requests return `400` with a `validation_error` describing the issue. ## Example A 2-step pipeline: capture sensor data on-board, then process on the ground. ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{ "satellite_id": "25544", "custom_job": { "name": "Capture and Process", "steps": [ { "id": "capture", "name": "Sensor Capture", "location": "onboard", "duration_s": 30, "depends_on": [], "requires": { "power_w": 40, "compute": 0.3, "thermal_w": 15, "memory_mb": 256, "storage_mb": 1024 }, "input_data_mb": 0, "output_data_mb": 500 }, { "id": "process", "name": "Ground Processing", "location": "ground", "duration_s": 60, "depends_on": ["capture"], "requires": { "power_w": 100, "compute": 1.0, "thermal_w": 50, "memory_mb": 2048, "storage_mb": 2048 }, "input_data_mb": 500, "output_data_mb": 50, "data_reduction_ratio": 0.1 } ] } }' ``` The planner automatically inserts transfer steps (downlink/uplink) at space-ground boundaries. Your 2-step job may produce a plan with 3+ segments. # Hazard Prediction Source: https://docs.rotastellar.com/cae/hazard-prediction I-4 — eclipse-boundary preservation via predictive checkpointing # Hazard Prediction The HazardPredictor identifies upcoming orbital hazards — eclipse transitions, South Atlantic Anomaly (SAA) traversals, and thermal excursions — and schedules checkpoints so that in-progress computation can survive them without data loss. **Why this matters** — An eclipse boundary can cut available power by 95% in seconds. Without predictive checkpointing, any in-flight step that spans an eclipse transition risks silent data corruption or abrupt termination. ## The 9-Phase Algorithm The HazardPredictor runs a 9-phase pipeline over the planning horizon: | Phase | Name | Description | | ----- | --------------------------- | ---------------------------------------------------------------------------------------- | | 1 | Orbit propagation | Keplerian + J2 perturbation model propagates the satellite state at 10-second intervals | | 2 | Eclipse detection | Cylindrical shadow model identifies sunlit/eclipse transitions | | 3 | Eclipse boundary refinement | Binary search narrows each transition to sub-second precision | | 4 | SAA detection | Point-in-polygon test against the SAA boundary polygon for each propagation point | | 5 | SAA window construction | Clusters SAA detections into contiguous traversal windows | | 6 | Thermal prediction | Projects component temperatures using power dissipation and orbital thermal environment | | 7 | Thermal excursion detection | Flags windows where predicted temperature exceeds component limits | | 8 | Checkpoint scheduling | Places checkpoints before each hazard with sufficient margin for state serialization | | 9 | Checkpoint merge | Consolidates checkpoints that fall within a configurable merge window to reduce overhead | ## Hazard Types ### Eclipse Boundaries Detected using the cylindrical shadow model — the same model used in the CAE orbital environment builder. The predictor identifies both eclipse entry (sunlit-to-shadow) and eclipse exit (shadow-to-sunlit) transitions. | Parameter | Value | | --------------- | -------------------------------------------------- | | Detection model | Cylindrical Earth shadow | | Propagation | Keplerian + J2 secular perturbations | | Time resolution | Sub-second (binary search refinement) | | Margin | Configurable, default 30 seconds before transition | ### South Atlantic Anomaly The SAA is a region of elevated radiation over the South Atlantic where the inner Van Allen belt dips closest to Earth. Sensitive electronics (GPUs, FPGAs) experience elevated single-event upset rates during SAA traversals. | Parameter | Value | | ---------------- | --------------------------------------------- | | Detection method | Point-in-polygon against SAA boundary contour | | Boundary model | AP-8/AE-8 derived, updated annually | | Altitude scaling | Contour expands at lower altitudes | | Typical duration | 10-20 minutes per traversal for LEO | ### Thermal Excursions The thermal predictor models component temperature based on solar flux, Earth albedo, bus power dissipation, and radiator capacity. Excursions are flagged when any component is predicted to exceed its operational limit. | Parameter | Value | | ----------------- | ------------------------------------------ | | Thermal model | Single-node lumped parameter per component | | Heat sources | Solar flux, Earth IR, internal dissipation | | Heat sinks | Radiator panels, thermal mass | | Warning threshold | 5 degrees C below operational limit | ## Checkpoint Scheduling For each detected hazard, the predictor inserts a checkpoint at `hazard_start - margin - serialization_time`. If two hazards are close together (within the merge window), their checkpoints are consolidated into one. ``` Timeline: |---step running---|--ckpt--|--margin--|==ECLIPSE==|---step resumes---| ^ ^ checkpoint hazard start ``` The checkpoint includes full step state: intermediate buffers, model weights, progress counters, and RNG state. The agent serializes this to on-board storage before the hazard arrives. ## API Usage ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/hazards \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{ "satellite_id": "25544", "prediction_hours": 24, "hazard_types": ["eclipse", "saa", "thermal"], "checkpoint_margin_s": 30, "merge_window_s": 60 }' ``` ### Request Parameters | Parameter | Type | Required | Default | Description | | --------------------- | --------- | -------- | ------- | ------------------------------------ | | `satellite_id` | string | Yes | — | NORAD catalog ID | | `prediction_hours` | number | No | 12 | Prediction horizon | | `hazard_types` | string\[] | No | all | Filter to specific hazard types | | `checkpoint_margin_s` | number | No | 30 | Seconds of margin before each hazard | | `merge_window_s` | number | No | 60 | Merge checkpoints closer than this | ### Response Structure ```json theme={null} { "satellite_id": "25544", "prediction_start": "2026-03-10T12:00:00Z", "prediction_hours": 24, "hazards": [ { "type": "eclipse_entry", "start": "2026-03-10T12:34:12.847Z", "end": "2026-03-10T13:07:45.231Z", "duration_s": 2012, "severity": "high", "details": { "battery_soc_at_entry": 0.82, "predicted_soc_at_exit": 0.41 } }, { "type": "saa", "start": "2026-03-10T14:18:30.000Z", "end": "2026-03-10T14:32:15.000Z", "duration_s": 825, "severity": "medium", "details": { "peak_flux_ratio": 3.2, "upset_probability": 0.0012 } }, { "type": "thermal_excursion", "start": "2026-03-10T16:45:00.000Z", "end": "2026-03-10T17:02:00.000Z", "duration_s": 1020, "severity": "low", "details": { "component": "gpu", "predicted_temp_c": 78.5, "limit_c": 85 } } ], "checkpoint_schedule": [ { "time": "2026-03-10T12:33:22.847Z", "reason": "eclipse_entry", "hazard_index": 0, "serialization_budget_s": 20 }, { "time": "2026-03-10T14:17:40.000Z", "reason": "saa", "hazard_index": 1, "serialization_budget_s": 20 } ], "max_safe_window_s": 6137, "overhead_fraction": 0.018 } ``` ### Response Fields | Field | Type | Description | | --------------------- | ------ | -------------------------------------------------------------- | | `hazards` | array | All detected hazards in chronological order | | `hazards[].severity` | string | `low`, `medium`, or `high` based on impact to computation | | `checkpoint_schedule` | array | Recommended checkpoint times with reasons | | `max_safe_window_s` | number | Longest uninterrupted compute window in the prediction horizon | | `overhead_fraction` | number | Fraction of total time consumed by checkpoint serialization | The `overhead_fraction` helps you decide whether predictive checkpointing is worth the cost. Values below 0.05 (5%) are typical for LEO orbits with 90-minute periods. ## Console Integration The Console surfaces hazard predictions on the **Hazards tab** of the asset detail page: * Timeline visualization shows hazards as colored bands (red for eclipse, orange for SAA, yellow for thermal) * Checkpoint markers appear on the timeline with serialization budget indicators * The max safe window is highlighted * Clicking a hazard expands its detail panel with severity, duration, and predicted impact ## Agent Integration When the agent receives a plan with predictive checkpoints, it listens for the `checkpoint.predicted` event and serializes state to on-board storage at the scheduled time. See the [Agent Protocol](/agent/protocol) documentation for event handling details. Eclipse and window-aware step types How to read plan responses including hazard data # Orbital Compute Unit Source: https://docs.rotastellar.com/cae/orbital-compute-unit I-5 — standardized orbital compute capacity measurement # Orbital Compute Unit An Orbital Compute Unit (OCU) is a standardized measure of how much useful computation a satellite can deliver per orbit, accounting for power constraints, eclipse fractions, thermal limits, and ground contact availability. **Why OCUs exist** — Satellite compute capacity is not a fixed number. It varies with orbit geometry, season, battery age, and thermal state. OCUs normalize this into a single comparable metric so you can plan workloads without modeling the physics yourself. ## Bus Profiles OCU computation starts with a bus profile — a standardized description of the satellite's compute, power, and thermal capabilities. CAE includes 6 built-in bus classes. | Bus Class | Typical Platform | Compute (GFLOPS) | Solar (W) | Battery (Wh) | Storage (GB) | Memory (MB) | | ------------- | --------------------------- | ---------------- | --------- | ------------ | ------------ | ----------- | | `1U_cubesat` | 1U CubeSat | 2 | 2.5 | 5 | 8 | 256 | | `3U_cubesat` | 3U CubeSat | 10 | 7.5 | 20 | 32 | 512 | | `6U_cubesat` | 6U CubeSat | 50 | 25 | 60 | 64 | 1024 | | `12U_cubesat` | 12U CubeSat | 150 | 50 | 120 | 128 | 2048 | | `microsat` | Microsatellite (50-100kg) | 500 | 150 | 400 | 256 | 4096 | | `smallsat` | Small Satellite (100-500kg) | 2000 | 500 | 1500 | 512 | 8192 | ### Auto-Detection with inferBusClass If you don't specify a bus class, CAE infers it from the satellite's NORAD ID using orbital parameters and known catalog metadata: * **Altitude and inclination** narrow the platform category * **Radar cross-section** (when available) estimates physical size * **Catalog metadata** matches against known spacecraft databases The inferred class is returned in the response so you can verify or override it. ## OCU Computation The OCU model combines bus capabilities with orbital geometry to produce a per-orbit capacity estimate. ### Sunlit and Eclipse Hours From the satellite's current TLE, CAE propagates the orbit and computes: | Metric | Description | | ------------------------- | ------------------------------------------------------------------ | | `sunlit_hours_per_orbit` | Time in sunlight — full solar power and thermal headroom available | | `eclipse_hours_per_orbit` | Time in Earth's shadow — battery-only, reduced thermal dissipation | | `daily_orbits` | Number of complete orbits per 24-hour period | | `daily_sunlit_hours` | Total sunlit time per day | | `daily_eclipse_hours` | Total eclipse time per day | ### Confidence Model OCU values carry a confidence score reflecting the quality of the input data: | Factor | Impact on Confidence | | -------------------------- | ------------------------------------------------------------------------------- | | TLE age | Degrades as TLE epoch age increases (stale elements reduce positional accuracy) | | Bus class source | Higher for explicit bus class, lower for inferred | | Eclipse fraction stability | Higher when eclipse fraction is stable across the prediction horizon | | Thermal margin | Higher when peak temperature is well below limits | Confidence is reported as a value between 0 and 1. Values above 0.8 are considered high-confidence. ### Cost Model Each OCU carries an estimated cost based on the bus class and orbital parameters: | Component | Basis | | ------------- | ------------------------------------------------------------------- | | Compute cost | GFLOPS-hours available per orbit, weighted by bus class | | Power cost | Watt-hours consumed, factoring solar generation and battery cycling | | Storage cost | GB-hours of on-board storage occupied | | Transfer cost | Data volume deliverable per orbit given contact window availability | ### Limiting Resource The OCU computation identifies which resource constrains capacity: ```json theme={null} "limiting_resource": { "resource": "power", "utilization": 0.92, "headroom": 0.08, "recommendation": "Reduce eclipse compute load or extend deadline to span more orbits" } ``` Common limiting resources: `power` (eclipse battery budget), `thermal` (heat dissipation during sunlit compute), `storage` (on-board buffer for multi-pass transfers), `contact` (ground pass availability for data delivery). ## negotiateOCU Algorithm The `negotiateOCU` function runs a 4-phase algorithm to determine achievable OCU for a specific workload: | Phase | Description | | ------------------------ | --------------------------------------------------------------------------------- | | 1. Resource survey | Compute available GFLOPS-hours, watt-hours, storage, and contact time per orbit | | 2. Workload mapping | Map workload resource requirements to per-orbit resource availability | | 3. Constraint resolution | Identify the binding constraint and compute the maximum sustainable throughput | | 4. OCU normalization | Express the result as a standardized OCU value with confidence and cost breakdown | The negotiation accounts for workload-specific factors like checkpoint overhead, FEC requirements, and quality tier selection. ## API Usage ### Negotiate OCU for a Workload ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/ocu/negotiate \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{ "satellite_id": "25544", "workload": { "compute_gflops": 50, "memory_mb": 512, "storage_mb": 2048, "output_mb": 100 } }' ``` #### Response ```json theme={null} { "satellite_id": "25544", "bus_class": "smallsat", "bus_class_source": "inferred", "ocu": { "value": 14.2, "unit": "OCU/orbit", "daily": 218.7, "confidence": 0.87 }, "orbital_geometry": { "sunlit_hours_per_orbit": 0.96, "eclipse_hours_per_orbit": 0.59, "daily_orbits": 15.4 }, "limiting_resource": { "resource": "power", "utilization": 0.92, "headroom": 0.08, "recommendation": "Reduce eclipse compute load or extend deadline to span more orbits" }, "cost": { "compute_cost_per_orbit": 0.42, "power_cost_per_orbit": 0.18, "storage_cost_per_orbit": 0.05, "total_cost_per_orbit": 0.65, "currency": "OCU-credits" } } ``` ### Get Bus Class Summary Retrieve the reference profile for a bus class without specifying a satellite: ```bash theme={null} curl https://rotastellar-cae.subhadip-mitra.workers.dev/v1/ocu/summary/6U_cubesat \ -H "Origin: https://rotastellar.com" ``` #### Response ```json theme={null} { "bus_class": "6U_cubesat", "profile": { "compute_gflops": 50, "solar_w": 25, "battery_wh": 60, "storage_gb": 64, "memory_mb": 1024 }, "reference_ocu": { "value": 3.8, "unit": "OCU/orbit", "assumptions": { "altitude_km": 550, "inclination_deg": 97.5, "eclipse_fraction": 0.35 } } } ``` ### Negotiate and Summary Parameters | Parameter | Type | Required | Description | | ------------------------- | ------ | --------------- | ---------------------------------------------- | | `satellite_id` | string | Yes (negotiate) | NORAD catalog ID | | `workload` | object | No | Workload resource requirements for negotiation | | `workload.compute_gflops` | number | No | Required compute in GFLOPS | | `workload.memory_mb` | number | No | Required memory | | `workload.storage_mb` | number | No | Required on-board storage | | `workload.output_mb` | number | No | Output data to deliver to ground | | `bus_class` | string | No | Override inferred bus class | ## Console Integration The Console displays an **OCU Capacity** card in the sidebar of the asset detail page: * OCU/orbit and OCU/day values with confidence indicator * Bus class label (with "inferred" badge when auto-detected) * Limiting resource bar chart showing utilization per resource * Sunlit/eclipse breakdown as a ring chart * Cost estimate per orbit OCU values are estimates based on current orbital geometry and bus profiles. Actual capacity may vary due to battery degradation, thermal anomalies, or attitude constraints not captured in the bus model. Predictive checkpointing around orbital hazards Constraint-Aware Execution fundamentals # Orbital Compute Primitives Source: https://docs.rotastellar.com/cae/orbital-primitives I-1 — 3 new step types for orbit-aware workload scheduling # Orbital Compute Primitives Standard compute steps treat satellites like ground servers. Orbital primitives don't — they decompose workloads around the physical realities of eclipse boundaries, contact windows, and ground passes. **New in Orbital Resilience** — Eclipse, Window, and Pass steps extend the existing step schema. All existing presets and custom workloads continue to work unchanged. ## Eclipse Steps Eclipse steps run during battery-only orbital night periods. They carry an explicit energy budget so the planner never over-commits the bus during eclipse. | Parameter | Type | Description | | ------------------ | ----------- | ---------------------------------------------------------------------- | | `type` | `"eclipse"` | Marks the step as eclipse-aware | | `energy_budget_wh` | number | Maximum energy the step may consume during eclipse | | `eclipse_policy` | string | Power management strategy: `conservative`, `balanced`, or `aggressive` | | `min_battery_soc` | number | Minimum battery state-of-charge to maintain (0-1) | | `priority` | number | Scheduling priority relative to other eclipse steps | ### Eclipse Policies | Policy | Behaviour | | -------------- | -------------------------------------------------------------------------------------------------------- | | `conservative` | Limits compute to 40% of eclipse battery capacity. Safe for missions where power margin is thin. | | `balanced` | Uses up to 65% of eclipse battery. Default for most workloads. | | `aggressive` | Uses up to 85% of eclipse battery. Use only when the next sunlit window is guaranteed to fully recharge. | ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{ "satellite_id": "25544", "custom_job": { "name": "Eclipse Compute", "steps": [ { "id": "night_inference", "name": "Battery-Only Inference", "type": "eclipse", "location": "onboard", "energy_budget_wh": 12.5, "eclipse_policy": "balanced", "min_battery_soc": 0.3, "compute_s": 120, "output_mb": 5 } ], "policy": { "objective": "balanced", "deadline_orbits": 4 } } }' ``` *** ## Window Steps Window steps adapt their output quality based on how much time is available in the current orbital window. The planner selects a quality tier automatically — no manual tuning required. | Parameter | Type | Description | | ---------------- | ---------- | ------------------------------------------- | | `type` | `"window"` | Marks the step as window-adaptive | | `quality_tiers` | object | Map of tier names to resource requirements | | `min_tier` | string | Lowest acceptable tier (default: `minimal`) | | `preferred_tier` | string | Tier the planner targets if time allows | ### Quality Tiers Each tier defines the compute time, memory, and output size the step needs at that quality level. | Tier | Typical Use Case | | ---------- | ------------------------------------------------------------ | | `minimal` | Abbreviated result — good enough for monitoring or alerting | | `standard` | Normal quality. Suitable for most operational workloads | | `enhanced` | Higher fidelity output. Requires longer windows | | `maximum` | Full-resolution result. Only feasible in long sunlit windows | The planner evaluates the remaining time in the assigned orbital window and selects the highest tier that fits. If even `minimal` doesn't fit, the step is deferred to the next window. ```json theme={null} { "id": "process_imagery", "name": "Adaptive Image Processing", "type": "window", "location": "onboard", "quality_tiers": { "minimal": { "compute_s": 30, "memory_mb": 256, "output_mb": 10 }, "standard": { "compute_s": 90, "memory_mb": 512, "output_mb": 50 }, "enhanced": { "compute_s": 180, "memory_mb": 1024, "output_mb": 120 }, "maximum": { "compute_s": 360, "memory_mb": 2048, "output_mb": 300 } }, "preferred_tier": "enhanced" } ``` The selected tier is recorded in the plan response under `placement_decisions[].quality_tier` and in the event stream as `window_step.tier_selected`. *** ## Pass Steps Pass steps are atomic units of work that the planner decomposes around ground contact windows. A long-running task is broken into segments that align with pass start/end times, with configurable merge strategies for reassembling results. | Parameter | Type | Description | | --------------------- | -------- | ------------------------------------------------------------ | | `type` | `"pass"` | Marks the step as pass-aligned | | `merge_strategy` | string | How segments are recombined: `concat`, `reduce`, or `latest` | | `max_segments` | number | Maximum number of pass-aligned segments (default: unlimited) | | `min_pass_duration_s` | number | Ignore passes shorter than this | ### Merge Strategies | Strategy | Behaviour | | -------- | ------------------------------------------------------------------------------------- | | `concat` | Append all segment outputs in chronological order. Use for streaming data collection. | | `reduce` | Apply a reduction function across segments (e.g., averaging model gradients). | | `latest` | Only the last segment's output is kept. Use for iterative refinement. | ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{ "satellite_id": "25544", "custom_job": { "name": "Multi-Pass Collection", "steps": [ { "id": "collect", "name": "Pass-Aligned Data Collection", "type": "pass", "location": "onboard", "merge_strategy": "concat", "min_pass_duration_s": 120, "compute_s": 60, "output_mb": 200 } ], "policy": { "objective": "max_reliability", "deadline_orbits": 6 } } }' ``` *** ## Event Types Orbital primitive steps emit dedicated events in the execution event stream. | Event Type | Description | | ----------------------------- | -------------------------------------------------- | | `eclipse_step.scheduled` | Eclipse step assigned to an eclipse window | | `eclipse_step.energy_check` | Energy budget validated against battery state | | `eclipse_step.started` | Execution begins in eclipse | | `eclipse_step.completed` | Eclipse step finished within energy budget | | `eclipse_step.deferred` | Deferred — insufficient battery for this eclipse | | `window_step.tier_selected` | Quality tier chosen based on available window time | | `window_step.started` | Window-adaptive step begins at selected tier | | `window_step.completed` | Window step finished | | `window_step.deferred` | No window large enough for even the minimal tier | | `pass_step.decomposed` | Step split into pass-aligned segments | | `pass_step.segment_started` | Individual segment begins during a pass | | `pass_step.segment_completed` | Segment finished | | `pass_step.merged` | All segments merged using the configured strategy | Eclipse steps with `aggressive` policy and low `min_battery_soc` can leave the satellite with insufficient power for the next sunlit boot sequence. Use conservative margins for early-stage missions. ## Combining Primitives Orbital primitives can be mixed with standard steps and with each other in the same DAG. Use `depends_on` as usual: ```json theme={null} { "steps": [ { "id": "capture", "type": "pass", "merge_strategy": "concat", "depends_on": [] }, { "id": "process", "type": "window", "preferred_tier": "enhanced", "depends_on": ["capture"] }, { "id": "compress", "type": "eclipse", "eclipse_policy": "balanced", "depends_on": ["process"] } ] } ``` Built-in workloads that use orbital primitives How agents handle orbital primitive events at runtime # CAE Overview Source: https://docs.rotastellar.com/cae/overview Constraint-Aware Execution — orbital compute orchestration across the space-ground boundary # Constraint-Aware Execution POST a workload and a satellite ID. Get back a physically-accurate execution plan — computed from real orbital mechanics, real ground station passes, and real power/thermal constraints. **Available now** — CAE v1.0 is live. No API key required. ## How It Works 1. **Choose a workload** — pick from 5 built-in [presets](/cae/presets) or define a [custom DAG](/cae/custom-workloads) 2. **CAE builds the orbital environment** — SGP4 propagation from real TLE data, eclipse detection, ground station pass prediction 3. **4-phase planner runs** — topological sort, compute placement (on-board vs ground), transfer insertion, window scheduling 4. **You get a complete plan** — placement decisions, transfer schedule, error budget, security summary, and a simulated execution event stream 5 ready-to-use orbital compute workloads Define your own step DAGs with dependencies How to read plan responses Eclipse, window, and pass step types Multi-objective trade-off analysis Multi-satellite workflow orchestration ## Capabilities | Capability | Details | | -------------------- | -------------------------------------------------------------- | | Orbital propagation | SGP4 from real CelesTrak TLE data | | Eclipse detection | Cylindrical shadow model | | Ground network | 12 stations (KSAT, NASA, AWS) | | Compute placement | Automatic on-board vs ground optimization | | Transfer scheduling | Multi-pass downlink/uplink with FEC overhead | | Error correction | Reed-Solomon FEC, retransmission reserves | | Security | AES-128/256 encryption, SHA-256/CRC32 integrity | | Delivery confidence | Deterministic error budget calculation | | Orbital primitives | Eclipse, window, and pass step types (I-1) | | Pareto planning | Multi-objective frontier with 4 relaxation types (I-2) | | Constellation DAG | Multi-satellite orchestration with ISL routing (I-3) | | Hazard prediction | Eclipse-boundary checkpointing via SAA/thermal detection (I-4) | | Orbital Compute Unit | Standardized capacity measurement across bus classes (I-5) | | Monitoring | Per-endpoint latency percentiles and request metrics | ## Base URL ``` https://rotastellar-cae.subhadip-mitra.workers.dev ``` CAE does not require an API key. Access is controlled via CORS origin checking. Requests from `rotastellar.com` and `localhost:4000` are allowed. For cURL testing, include `-H "Origin: https://rotastellar.com"`. ## Quick Example Create an execution plan for the ISS using the on-board ML inference preset: ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{ "satellite_id": "25544", "preset_id": "onboard-ml-inference" }' ``` The response includes the full execution plan with orbital environment, placement decisions, transfer schedule, error budget, and a simulated event stream. See [Understanding Plans](/cae/understanding-plans) for a walkthrough. ## Endpoints | Method | Path | Description | | ------ | --------------------------------------------------------------------- | ----------------------------- | | `GET` | [`/v1/presets`](/api-reference/cae/list-presets) | List workload presets | | `POST` | [`/v1/plan`](/api-reference/cae/create-plan) | Create an execution plan | | `GET` | [`/v1/plan/:id`](/api-reference/cae/get-plan) | Retrieve a plan | | `GET` | [`/v1/plan/:id/events`](/api-reference/cae/get-plan-events) | Get execution event stream | | `POST` | [`/v1/constellation/plan`](/api-reference/cae/constellation-plan) | Plan a constellation DAG | | `POST` | [`/v1/constellation/pareto`](/api-reference/cae/constellation-pareto) | Constellation Pareto frontier | | `POST` | [`/v1/hazards`](/api-reference/cae/hazards) | Predict orbital hazards | | `POST` | [`/v1/ocu/negotiate`](/api-reference/cae/ocu-negotiate) | Negotiate OCU capacity | | `GET` | [`/v1/ocu/summary/:busClass`](/api-reference/cae/ocu-summary) | OCU summary by bus class | | `GET` | [`/v1/metrics`](/api-reference/cae/metrics) | Service metrics and latency | # Predictive Pareto Planning Source: https://docs.rotastellar.com/cae/pareto-planning I-2 — multi-objective optimization across the Pareto frontier # Predictive Pareto Planning A single execution plan optimizes for one objective. Pareto planning generates the full set of non-dominated trade-offs across four objectives simultaneously, letting you choose the plan that best fits your mission constraints. **How it works** — CAE evaluates thousands of candidate plans with different relaxation combinations, filters dominated solutions, and returns only the Pareto-optimal frontier. ## Objectives Every plan is scored on four axes: | Objective | Unit | Direction | Description | | ----------- | ----------- | --------- | ------------------------------------------------------------------ | | Latency | seconds | minimize | Total time from job start to final output delivery | | Energy | watt-hours | minimize | Total on-board energy consumed across all steps | | Reliability | probability | maximize | Delivery confidence accounting for link errors and retransmissions | | Quality | 0-1 score | maximize | Output fidelity — driven by quality tier selection in window steps | A plan is **Pareto-optimal** (non-dominated) if no other plan is better on every objective. The frontier is the set of all non-dominated plans. ## Relaxation Types To explore the frontier, the planner applies controlled relaxations — each trades one objective for gains in others. | Relaxation | Trades Away | Gains | | -------------------- | ----------- | ----------------------------------------------------------------------------------- | | `extend_windows` | Latency | Reliability, Quality — more time allows higher tiers and more retransmission margin | | `skip_checkpoint` | Reliability | Latency, Energy — removing checkpoints saves time and power | | `reduce_fec` | Reliability | Latency, Energy — less FEC overhead means smaller transfers | | `lower_quality_tier` | Quality | Latency, Energy — lower tiers complete faster with less compute | The planner generates candidates by combining relaxations at multiple levels, then applies dominance filtering to discard any solution that is strictly worse than another. ## Dominance Filtering Given two plans A and B, A **dominates** B if A is at least as good as B on all four objectives and strictly better on at least one. The Pareto frontier is the set of plans that no other plan dominates. ``` Plan A: latency=4200s energy=18Wh reliability=0.97 quality=0.85 Plan B: latency=5100s energy=22Wh reliability=0.95 quality=0.80 → A dominates B (better on all four axes) Plan C: latency=3800s energy=24Wh reliability=0.93 quality=0.90 → A does not dominate C (C has better latency and quality) → Both A and C are on the frontier ``` ## API Usage ### Single-Satellite Pareto Add `pareto: true` to a standard plan request: ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{ "satellite_id": "25544", "preset_id": "onboard-ml-inference", "pareto": true }' ``` The response includes a `frontier` array instead of a single plan: ```json theme={null} { "id": "pareto-a92f33e8-...", "frontier": [ { "plan_index": 0, "objectives": { "latency_s": 3240, "energy_wh": 14.2, "reliability": 0.991, "quality": 0.95 }, "relaxations_applied": [], "plan": { ... } }, { "plan_index": 1, "objectives": { "latency_s": 2880, "energy_wh": 12.8, "reliability": 0.967, "quality": 0.85 }, "relaxations_applied": ["lower_quality_tier", "reduce_fec"], "plan": { ... } } ], "frontier_size": 5, "candidates_evaluated": 128, "dominated_filtered": 123 } ``` ### Fleet-Level Pareto For constellation workloads, use the fleet Pareto endpoint: ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/constellation/pareto \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{ "satellite_ids": ["25544", "48274", "55909"], "preset_id": "split-learning", "pareto": true }' ``` Fleet Pareto evaluates trade-offs across all satellites in the constellation, including ISL transfer alternatives and cross-satellite placement variations. ## Response Parameters | Field | Type | Description | | -------------------------------- | ------ | ------------------------------------------------ | | `frontier` | array | Array of Pareto-optimal plan variants | | `frontier[].plan_index` | number | Index within the frontier (0 = baseline) | | `frontier[].objectives` | object | Objective scores for this variant | | `frontier[].relaxations_applied` | array | Which relaxations produced this variant | | `frontier[].plan` | object | Full plan object (same schema as standard plans) | | `frontier_size` | number | Number of non-dominated solutions | | `candidates_evaluated` | number | Total candidate plans generated | | `dominated_filtered` | number | Candidates eliminated by dominance filtering | ## Console Integration In the RotaStellar Console, the **Generate Trade-offs** button on the plan detail page triggers a Pareto analysis. Results are displayed as an interactive scatter chart where: * Each axis maps to one of the four objectives * Each point is a Pareto-optimal plan variant * Clicking a point loads the full plan detail * Hovering shows the relaxations applied and objective scores Pareto planning takes longer than single-objective planning because the planner must evaluate and filter many candidates. For complex workloads with many steps, expect 2-5x the normal planning time. API reference for POST /v1/plan Fleet-level orchestration with ISL routing # Workload Presets Source: https://docs.rotastellar.com/cae/presets 5 ready-to-use orbital compute workloads # Workload Presets Presets are complete workload definitions you can use immediately with `POST /v1/plan`. Each defines a multi-step pipeline with resource requirements, dependencies, security policies, and optimization objectives. List all presets: ```bash theme={null} curl https://rotastellar-cae.subhadip-mitra.workers.dev/v1/presets \ -H "Origin: https://rotastellar.com" ``` ## On-Board ML Inference All computation on-board. Captures 2GB of sensor data, runs ML inference, and downlinks only the 10.5MB encrypted result — a **190:1 data reduction**. | Property | Value | | ------------ | ----------------------------------------------- | | ID | `onboard-ml-inference` | | Category | ml-inference | | Steps | 4 (capture, preprocess, inference, encrypt) | | All on-board | Yes | | Data flow | 2,000 MB → 10.5 MB | | Policy | `min_latency`, 3-orbit deadline, 99% confidence | **Pipeline:** Sensor Capture → Data Preprocessing & Calibration → ML Model Inference → Encrypt Results ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{"satellite_id": "25544", "preset_id": "onboard-ml-inference"}' ``` *** ## Split Learning Pipeline Bidirectional training. Satellite runs the first 3 neural network layers (feature extraction, 40:1 reduction), downlinks 36.75MB of activations. Ground trains the remaining layers and uplinks 5.25MB of updated weights. | Property | Value | | -------- | ----------------------------------------------------------------------------------------------------------- | | ID | `split-learning` | | Category | ml-training | | Steps | 9 (capture → feature extraction → compress → encrypt → train backend → compress weights → encrypt → deploy) | | Downlink | 36.75 MB (activations) | | Uplink | 5.25 MB (weights) | | Policy | `balanced`, 6-orbit deadline, 95% confidence | | Security | `confidential`, authenticated uplink, key rotation every 12 orbits | ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{"satellite_id": "25544", "preset_id": "split-learning"}' ``` *** ## Earth Observation with QA Captures 5GB of imagery, runs on-board quality assurance to discard bad frames and cloudy scenes, compresses to 400MB, applies Reed-Solomon FEC and AES-256, then downlinks 560MB across multiple ground station passes. | Property | Value | | ------------------- | -------------------------------------------------------------------------------------------------------- | | ID | `earth-observation-qa` | | Category | earth-observation | | Steps | 8 (capture → QA → cloud filter → JPEG2000 compress → FEC encode → encrypt → ground validation → archive) | | Data flow | 5,000 MB → 560 MB transferred | | Multi-pass downlink | Yes | | Policy | `max_reliability`, 8-orbit deadline, 95% confidence | ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{"satellite_id": "25544", "preset_id": "earth-observation-qa"}' ``` *** ## Federated Learning Privacy-preserving distributed training. The satellite trains locally on 500MB of data, computes and sparsifies gradients (top-k, 90% zeros), downlinks 3.7MB. Ground aggregates via FedAvg and uplinks 5.8MB updated global model. **Raw data never leaves the satellite.** | Property | Value | | -------- | ------------------------------------------------------------------------------------------------------------ | | ID | `federated-learning` | | Category | ml-training | | Steps | 10 (local train → gradients → sparsify → compress → encrypt → aggregate → compress model → encrypt → deploy) | | Downlink | 3.7 MB (sparse gradients) | | Uplink | 5.8 MB (global model) | | Policy | `balanced`, 6-orbit deadline, 95% confidence | | Security | `confidential`, authenticated uplink, key rotation every 12 orbits | ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{"satellite_id": "25544", "preset_id": "federated-learning"}' ``` *** ## Resilient Store-and-Forward Relay Receives 100MB from a remote sensor during one pass, applies Reed-Solomon erasure coding (rate 2/3 — any 2-of-3 blocks reconstruct), buffers on-board, and transmits during a different ground pass. | Property | Value | | ---------------- | ---------------------------------------------------------------------------------------- | | ID | `resilient-store-forward` | | Category | relay | | Steps | 5 (uplink receive → integrity check → erasure coding → encrypt & buffer → ground decode) | | Data transferred | 157.5 MB (with erasure coding overhead) | | Policy | `max_reliability`, 4-orbit deadline, 99% confidence | ```bash theme={null} curl -X POST https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan \ -H "Content-Type: application/json" \ -H "Origin: https://rotastellar.com" \ -d '{"satellite_id": "25544", "preset_id": "resilient-store-forward"}' ``` *** ## Comparison | Preset | Steps | Data Reduction | Downlink | Uplink | Objective | Deadline | | --------------------- | ----- | ----------------- | -------- | ------- | ---------------- | -------- | | On-Board ML Inference | 4 | 190:1 | 10.5 MB | — | min\_latency | 3 orbits | | Split Learning | 9 | 40:1 | 36.75 MB | 5.25 MB | balanced | 6 orbits | | Earth Observation QA | 8 | 9:1 | 560 MB | — | max\_reliability | 8 orbits | | Federated Learning | 10 | 135:1 | 3.7 MB | 5.8 MB | balanced | 6 orbits | | Store-and-Forward | 5 | 1:1.6 (expansion) | 157.5 MB | — | max\_reliability | 4 orbits | Need something different? Define a [custom workload](/cae/custom-workloads). # Understanding Plans Source: https://docs.rotastellar.com/cae/understanding-plans How to read CAE execution plan responses # Understanding Plans When you create a plan via `POST /v1/plan`, the response contains a complete execution plan computed from real orbital mechanics. This page walks through each section. ## Response Structure ```json theme={null} { "id": "a92f33e8-...", "created_at": "2026-03-05T06:55:37.811Z", "version": "1.0.0", "satellite": { ... }, "preset": { ... }, "orbital_environment": { ... }, "placement_decisions": [ ... ], "transfer_schedule": { ... }, "error_budget": { ... }, "security_summary": { ... }, "plan": { ... }, "events": [ ... ] } ``` ## Satellite Orbital parameters computed from real TLE data at plan creation time. ```json theme={null} "satellite": { "id": "25544", "name": "ISS (ZARYA)", "norad_id": 25544, "altitude_km": 417, "inclination_deg": 51.6, "period_min": 93, "tle_epoch": "26063.86671769" } ``` ## Orbital Environment The physical context the planner works within: eclipse fraction, satellite bus capabilities, orbital windows (sunlit/eclipse periods with resource envelopes), and predicted ground station passes. ```json theme={null} "orbital_environment": { "prediction_start": "2026-03-05T06:55:37.811Z", "prediction_hours": 12, "eclipse_fraction": 0.348, "bus": { "peak_solar_w": 789, "eclipse_battery_w": 20, "max_thermal_w": 45, "compute_sunlit": 1, "compute_eclipse": 0.6, "storage_mb": 4096, "memory_mb": 2048 }, "windows": [ ... ], "ground_passes": [ ... ], "summary": { "total_windows": 14, "comms_windows": 6, "sunlit_windows": 9, "eclipse_windows": 5, "total_pass_time_s": 2847, "ground_stations_visible": 8 } } ``` **Windows** are orbital time slots with available resources. The planner fits steps into windows based on power, thermal, and compute constraints. **Ground passes** are periods when the satellite is visible from a ground station — required for data transfer. ## Placement Decisions For each step, the planner decides whether it runs on-board or on the ground. Steps with `location: "either"` are automatically placed based on data reduction ratio and transfer cost. ```json theme={null} "placement_decisions": [ { "step_id": "capture", "location": "onboard", "reason": "preset_defined" }, { "step_id": "inference", "location": "onboard", "reason": "data_reduction_50x" }, { "step_id": "validate", "location": "ground", "reason": "onboard_infeasible (thermal)" } ] ``` ## Transfer Schedule The planner auto-inserts transfer segments at space-ground boundaries. This section shows all data transfers with FEC overhead, encryption expansion, and ground station assignments. ```json theme={null} "transfer_schedule": { "transfers": [ { "from_step": "encrypt", "to_step": "ground_validation", "direction": "downlink", "raw_data_mb": 560, "fec_overhead_mb": 28, "encryption_overhead_mb": 5.6, "total_transfer_mb": 593.6, "passes": [ { "station": "Svalbard", "data_mb": 350, "duration_s": 420 }, { "station": "Fairbanks", "data_mb": 243.6, "duration_s": 310 } ] } ], "total_transfers": 1, "total_downlink_mb": 593.6, "total_uplink_mb": 0, "passes_used": 2, "total_transfer_time_s": 730 } ``` ## Error Budget Quantifies data integrity: worst-case bit error rate, FEC overhead, retransmission reserves, and the resulting delivery confidence. ```json theme={null} "error_budget": { "worst_case_ber": 0.00001, "total_fec_overhead_mb": 28, "total_retransmission_reserve_mb": 14, "delivery_confidence": 0.967 } ``` The `delivery_confidence` is the probability that all data is delivered correctly within the deadline, accounting for link errors and retransmissions. ## Security Summary Encryption overhead and key exchange details. ```json theme={null} "security_summary": { "encryption": "aes256", "total_encryption_overhead_mb": 5.6, "total_key_exchanges": 2, "data_classification": "restricted" } ``` ## Plan Segments The scheduled execution timeline. Each segment is a step assigned to an orbital window with a start time. ```json theme={null} "plan": { "segments": [ { "step_id": "capture", "location": "onboard", "window_index": 0, "start_offset_s": 0, "duration_s": 60, "resources": { ... } } ], "total_duration_s": 8940, "total_compute_s": 253, "total_transfer_s": 730, "total_ground_s": 75, "windows_used": 4, "policy": { "objective": "max_reliability", "deadline_orbits": 8 } } ``` The plan may contain more segments than your original step count — the planner auto-inserts transfer segments at every space-ground boundary. ## Event Stream A simulated execution trace showing every significant moment. Retrieve via the plan response or separately via `GET /v1/plan/:id/events`. | Event Type | Description | | ------------------------- | ---------------------------------- | | `job.accepted` | Workload received | | `placement.decided` | Step location assigned | | `plan.created` | Plan is ready | | `step.started` | Step execution begins | | `step.progress` | Progress at 25%, 50%, 75% | | `checkpoint.saved` | Intermediate checkpoint | | `step.completed` | Step finished | | `transfer.started` | Data transfer begins | | `transfer.pass_started` | Transfer via ground station | | `transfer.progress` | Transfer midpoint | | `transfer.retransmission` | Blocks retransmitted due to errors | | `transfer.pass_completed` | Ground station pass finished | | `transfer.completed` | All data transferred | | `security.key_exchange` | Encryption key exchange | | `security.encrypted` | Data encrypted | | `job.completed` | Pipeline finished successfully | | `job.failed` | Pipeline failed | ## Plan Storage Plans are stored for **1 hour**. Retrieve a plan by ID: ```bash theme={null} curl https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan/{plan_id} \ -H "Origin: https://rotastellar.com" ``` Get just the event stream: ```bash theme={null} curl https://rotastellar-cae.subhadip-mitra.workers.dev/v1/plan/{plan_id}/events \ -H "Origin: https://rotastellar.com" ``` # Changelog Source: https://docs.rotastellar.com/changelog API version history and updates # Changelog All notable changes to the RotaStellar API. ## 2026-03-05 — CAE v1.0 ### New: Constraint-Aware Execution * **CAE API** — POST a workload + satellite ID, get a physically-accurate execution plan computed from real orbital mechanics * **5 built-in presets:** on-board ML inference, split learning, earth observation with QA, federated learning, resilient store-and-forward * **Custom workload DAGs** — define arbitrary step pipelines with dependencies, resource requirements, and security policies * **4-phase planner:** topological sort, compute placement, transfer insertion, window scheduling * **Real orbital mechanics:** SGP4 propagation, eclipse detection, 12-station ground network (KSAT, NASA, AWS) * **Simulated execution events:** full event stream with transfer, checkpoint, and security events *** ## 2026-02-01 — SDK Updates & Documentation Improvements ### SDK Updates * **Python SDK v0.2.0** — Fixed `Position` type to use `latitude`/`longitude` fields consistently * **Node.js SDK v0.2.0** — Aligned field names with Python SDK (`latitude`, `longitude`, `altitudeKm`) * **Rust SDK v0.1.1** — Types-only release with `Position`, `Orbit`, `Satellite`, `TimeRange` structs ### API Improvements * **Trajectory API** — Now accepts ISO 8601 strings for `start` and `end` parameters * **Patterns API** — Added `type` filter parameter for filtering by pattern type (`maneuver`, `anomaly`, `proximity`) * **Conjunctions API** — Response now includes `miss_distance_km` and `collision_probability` fields ### Documentation * Updated all SDK examples to use correct `RotaStellarClient` class name * Fixed code examples across 20+ documentation pages * Added comprehensive error handling examples *** ## 2026-01-28 — Dashboard Beta & Distributed Compute Preview ### New Features * **Dashboard Beta** — Web-based dashboard for satellite tracking and conjunction monitoring at [app.rotastellar.com](https://app.rotastellar.com) * Real-time satellite position visualization * Conjunction risk timeline * API usage metrics * **Distributed Compute SDK Preview** — `rotastellar-distributed` package now available * `FederatedClient` for gradient compression and federated learning * `CompressionConfig` with TopK + quantization (100x compression) * Python: `pip install rotastellar-distributed` * Node.js: `npm install @rotastellar/distributed` ### API Updates * **List Satellites** — Added `constellation` and `operator` filter parameters * **Get Satellite** — Response now includes `orbit` object with computed properties * **Rate Limits** — Increased Pro tier limits to 100 req/min *** ## 2026-01-24 — Intelligence API Enhancements ### New Endpoints * `GET /v1/satellites/{id}/trajectory` — Get predicted positions over a time range * `GET /v1/patterns` — Detect maneuvers, anomalies, and proximity operations * `POST /v1/conjunctions/watch` — Set up webhook alerts for conjunction events ### Improvements * **Conjunction Analysis** — Now includes avoidance maneuver recommendations * **Pattern Detection** — Added confidence scores and detailed descriptions * **Satellite Metadata** — Enhanced with operator, constellation, and launch date fields *** ## 2026-01-21 — Early Access Launch Initial early access release of the RotaStellar API. ### Available * **Planning Tools API** — Feasibility analysis, thermal modeling, latency simulation, power budgeting * **Orbital Intelligence API** — Satellite tracking, conjunction analysis, pattern detection * **Python SDK** — `pip install rotastellar` * **Node.js SDK** — `npm install @rotastellar/sdk` * **Rust SDK** — `cargo add rotastellar` ### Coming Soon * **Orbital Runtime API** — Scheduled for Q2 2026 * **Webhook notifications** — Q1 2026 * **Bulk data export** — Q1 2026 *** ## Versioning The API uses date-based versioning in the URL path: ``` https://api.rotastellar.com/v1/... ``` Breaking changes will be released as new versions with migration guides. ## Deprecation Policy * Deprecated features are announced 6 months before removal * Deprecated endpoints return `X-Deprecated: true` header * Migration guides are provided for all breaking changes ## Subscribe to Updates Get notified about API changes and new features. # Getting Started Source: https://docs.rotastellar.com/console/getting-started Sign up, create your first mission, build a plan, and deploy # Getting Started with Mission Control This guide walks you through your first satellite compute deployment — from sign-up to watching events roll in. ## 1. Create an Account Go to [console.rotastellar.com](https://console.rotastellar.com) and sign up with your email. You'll receive a magic link — click it to log in. No password required. ## 2. Create a Mission Missions group related satellite operations. 1. Click **Missions** in the sidebar 2. Click **New Mission** 3. Enter a name (e.g., "ISS ML Pipeline") and optional description 4. Click **Create** ## 3. Build a Plan A plan is a complete execution schedule built by the [CAE engine](/cae/overview). 1. Open your mission and click **New Plan** 2. Search for a satellite by name or NORAD ID (e.g., "ISS" or "25544") 3. Choose a workload: * **Preset** — Select from 5 built-in workloads like [On-Board ML Inference](/cae/presets#on-board-ml-inference) or [Split Learning](/cae/presets#split-learning-pipeline) * **Custom** — Define your own step DAG with dependencies, resource requirements, and security policies 4. Click **Generate Plan** The plan builder shows: * **Timeline** — Step-by-step execution with orbital window scheduling * **Placement** — Which steps run on-board vs on the ground * **Transfers** — Ground station passes used for downlink/uplink * **Error budget** — Delivery confidence based on link quality and FEC * **Cost estimate** — Compute and transfer costs ## 4. Deploy 1. From the plan detail page, click **Deploy** 2. Choose a mode: * **Simulated** — Events are generated server-side. Adjust the speed multiplier (default: 100x). * **Live** — Requires a registered [Operator Agent](/agent/overview) on the target satellite. 3. Click **Deploy** The deployment page shows a real-time event timeline as the execution progresses. ## 5. Create an API Key To use the Agent SDK or call the Deploy API programmatically: 1. Go to **Developer > API Keys** in the sidebar 2. Click **Create Key** 3. Give it a name and copy the key (it won't be shown again) Use the key in the `X-API-Key` header for API requests and agent authentication. ## Next Steps Deep dive into mission management and plan configuration Set up the Operator Agent for live deployments # Missions & Plans Source: https://docs.rotastellar.com/console/missions-and-plans Organize satellite operations with missions and build execution plans with presets or custom workloads # Missions & Plans Missions and plans are the core organizing concepts in Mission Control. ## Missions A **mission** is a workspace that groups related satellite operations. It contains plans, deployments, and an activity log. ### Creating Missions Click **New Mission** from the missions page. Each mission has: * **Name** — A descriptive label (e.g., "Arctic Monitoring Fleet", "ISS ML Pipeline") * **Description** — Optional context about the mission's objectives ### Activity Feed Every mission has an activity feed that logs: * Plan creation and updates * Deployment starts and completions * Configuration changes ## Plans A **plan** is a constraint-aware execution schedule generated by the [CAE engine](/cae/overview). It maps a workload to a specific satellite's orbital environment. ### Presets vs Custom **Presets** are ready-to-use workload definitions: | Preset | Steps | Use Case | | ------------------------------------------------------------------- | ----- | ------------------------------------------------------- | | [On-Board ML Inference](/cae/presets#on-board-ml-inference) | 4 | Run ML models entirely on-board, downlink only results | | [Split Learning](/cae/presets#split-learning-pipeline) | 9 | Bidirectional training across space-ground boundary | | [Earth Observation QA](/cae/presets#earth-observation-with-qa) | 8 | Capture, quality filter, compress, and downlink imagery | | [Federated Learning](/cae/presets#federated-learning) | 10 | Privacy-preserving distributed training | | [Store-and-Forward](/cae/presets#resilient-store-and-forward-relay) | 5 | Erasure-coded relay through orbit | **Custom workloads** let you define your own step DAG: ```json theme={null} { "name": "My Pipeline", "steps": [ { "id": "capture", "name": "Sensor Capture", "location": "onboard", "duration_s": 30, "depends_on": [], "requires": { "power_w": 40, "compute": 0.3, "thermal_w": 15, "memory_mb": 256, "storage_mb": 1024 }, "output_data_mb": 500 }, { "id": "process", "name": "Ground Processing", "location": "ground", "duration_s": 60, "depends_on": ["capture"], "requires": { "power_w": 100, "compute": 1.0, "memory_mb": 2048 }, "input_data_mb": 500, "output_data_mb": 50 } ] } ``` See [Custom Workloads](/cae/custom-workloads) for the full schema. ### Plan Contents Every plan includes: | Section | Description | | ----------------------- | ------------------------------------------------------------ | | **Orbital Environment** | Eclipse fraction, ground station passes, available windows | | **Placement Decisions** | Which steps run on-board vs on the ground, with reasoning | | **Transfer Schedule** | Ground station passes used, FEC overhead, data volumes | | **Error Budget** | Worst-case BER, retransmission reserves, delivery confidence | | **Security Summary** | Encryption algorithm, key exchanges, data classification | | **Execution Timeline** | Step-by-step event stream with timestamps | | **Cost Estimate** | Compute and transfer costs in USD | ### Plan Comparison When you have multiple plans (different presets, satellites, or configurations), use the **Compare** feature on the mission page. Select 2-3 plans to see side-by-side metrics: duration, cost, confidence, and data volumes. ## Deployments Deploy a plan to run it. Choose between: * **Simulated** — Server generates events from the plan's event timeline. Configurable speed (1x to 10,000x). No agent required. * **Live** — Creates a pending deployment that an [Operator Agent](/agent/overview) picks up during its next poll cycle. Track deployment progress in real-time with the event timeline. Events are grouped by phase: placement, compute, transfer, security, and lifecycle. ### Status Flow ``` pending → dispatched → running → completed → failed → cancelled ``` # Mission Control Source: https://docs.rotastellar.com/console/overview The operations console for orbital compute — plan, deploy, and monitor satellite workloads # Mission Control Mission Control is the RotaStellar operations console. It provides a complete workflow for planning, deploying, and monitoring compute workloads on satellites. Access Mission Control at [console.rotastellar.com](https://console.rotastellar.com). ## Capabilities ### Missions Organize your satellite operations into missions. Each mission groups related plans, deployments, and activity into a single workspace. ### Plan Builder Create execution plans using CAE presets or custom workload DAGs. The plan builder shows: * Orbital environment (eclipse fraction, ground station passes) * Placement decisions (on-board vs ground compute) * Transfer schedule (downlink/uplink with FEC overhead) * Error budget and delivery confidence * Cost estimation * Full execution timeline ### Deployments Deploy plans in **simulated** or **live** mode: * **Simulated** — Console generates events from CAE plan data with configurable speed. No agent required. * **Live** — A satellite agent picks up the deployment and reports events in real-time. Track deployment status: `pending` → `dispatched` → `running` → `completed`. ### Constellations Group satellites into constellations for fleet operations. Add satellites by NORAD ID and view orbital parameters. ### Monitor Real-time satellite tracking with an interactive 3D globe. View satellite positions, orbits, and ground station coverage. ### Developer Tools * **API Keys** — Create and manage keys for agent authentication and API access * **Usage** — Track API usage and billing * **Settings** — Profile, preferences (timezone, units, globe style) ## Architecture Mission Control is built on: * **Next.js** — React-based web application * **CAE API** — Constraint-Aware Execution engine for orbital compute planning * **RotaStellar API** — Satellite tracking, feasibility analysis, orbital intelligence * **Operator Agent** — Pull-based protocol for satellite-side execution ```mermaid theme={null} graph TD subgraph Mission Control A[Missions] --> DB[(Postgres)] B[Plans] --> CAE[CAE API] C[Deploy] --> Agent[Agent Protocol] D[Monitor] --> Tracking[Tracking API] end ``` # Federated Learning Source: https://docs.rotastellar.com/distributed/federated-learning Train models across Earth and orbital nodes with gradient compression # Federated Learning **Coming Q1 2026** — This feature is in development. [Request early access](https://rotastellar.com/developers) to be notified when available. ## Overview Train machine learning models across distributed Earth and orbital infrastructure. Each node trains locally on its data, then synchronizes compressed gradients during ground station passes. ## Key Components Local training client for Earth or orbital nodes Central coordinator for gradient synchronization Gradient compression settings (TopK + quantization) Lossless compression via error accumulation ## Gradient Compression Bandwidth between orbital and ground nodes is extremely limited. Raw gradient synchronization is infeasible for large models. Our compression pipeline achieves 100x reduction with minimal accuracy loss: ### Compression Pipeline Raw gradient tensor from backpropagation, e.g., `∇ = [0.12, -0.08, 0.003, ...]` Keep only top 1% of gradients by magnitude. Reduces size by 100x while preserving the most important updates. Convert Float32 to Int8 with scale factor. Further 4x reduction with minimal precision loss. Accumulate dropped gradients for the next round. Guarantees eventual convergence despite aggressive compression. ### Configuration ```python Python theme={null} from rotastellar_distributed import CompressionConfig # Standard compression (100x reduction) compression = CompressionConfig( method="topk_quantized", k_ratio=0.01, # Keep top 1% quantization_bits=8, # 8-bit quantization error_feedback=True # Accumulate errors ) # Aggressive compression (200x reduction) aggressive = CompressionConfig( method="topk_quantized", k_ratio=0.005, # Keep top 0.5% quantization_bits=4, # 4-bit quantization error_feedback=True ) # Light compression (10x reduction) light = CompressionConfig( method="topk", k_ratio=0.1, # Keep top 10% error_feedback=True ) ``` ```typescript Node.js theme={null} import { CompressionConfig } from '@rotastellar/distributed'; const compression = new CompressionConfig({ method: 'topk_quantized', kRatio: 0.01, quantizationBits: 8, errorFeedback: true }); ``` ```rust Rust theme={null} use rotastellar_distributed::{CompressionConfig, CompressionMethod}; let compression = CompressionConfig::new() .method(CompressionMethod::TopKQuantized) .k_ratio(0.01) .quantization_bits(8) .error_feedback(true); ``` ## Federated Client The `FederatedClient` runs on each participating node (Earth or orbital): ```python Python theme={null} from rotastellar_distributed import FederatedClient, CompressionConfig, CompressionMethod # Initialize client client = FederatedClient( node_id="orbital-3", node_type="orbital", # "orbital" or "ground" compression=CompressionConfig( method=CompressionMethod.TOP_K_QUANTIZED, k_ratio=0.01, quantization_bits=8, error_feedback=True ) ) # Training loop for epoch in range(num_epochs): for batch in dataloader: # Compute local gradients gradients = client.compute_gradients(model_params, batch) # Compress gradients for transmission compressed = client.compress(gradients) # Send to aggregator (implementation-specific) send_to_aggregator(compressed) # Apply received global update client.apply_update(global_update) # Get compression statistics stats = client.get_stats() print(f"Compression ratio: {stats['compression_ratio']}x") ``` ```typescript Node.js theme={null} import { FederatedClient, CompressionConfig, CompressionMethod } from '@rotastellar/distributed'; const compression: CompressionConfig = { method: CompressionMethod.TOP_K_QUANTIZED, kRatio: 0.01, quantizationBits: 8, errorFeedback: true }; const client = new FederatedClient({ nodeId: 'orbital-3', nodeType: 'orbital', compression }); // Training loop for (const batch of dataloader) { const gradients = client.computeGradients(modelParams, batch); const compressed = client.compress(gradients); sendToAggregator(compressed); } // Apply received update client.applyUpdate(globalUpdate); ``` ```rust Rust theme={null} use rotastellar_distributed::{FederatedClient, CompressionConfig, Priority}; let client = FederatedClient::new("orbital-3", compression); for batch in dataloader { let gradients = client.train_step(&model, &batch); let compressed = client.compress(&gradients); client.queue_sync(compressed, Priority::Normal); } client.sync_now().await?; let global_weights = client.get_global_model().await?; ``` ## Gradient Aggregator The `GradientAggregator` runs on a ground station or cloud, coordinating updates from all nodes: ```python Python theme={null} from rotastellar_distributed import GradientAggregator # Initialize aggregator aggregator = GradientAggregator( api_key="rs_...", strategy="async_fedavg", # Async Federated Averaging min_nodes=3, # Wait for at least 3 nodes staleness_limit=5 # Accept updates up to 5 rounds old ) # Register callback for incoming gradients @aggregator.on_gradient_received def handle_gradient(node_id, gradients, metadata): print(f"Received from {node_id}: {metadata['compression_ratio']}x compressed") # Start aggregation loop aggregator.start() # Periodically get global model update while training: if aggregator.has_new_update(): global_update = aggregator.get_update() broadcast_to_nodes(global_update) ``` ```typescript Node.js theme={null} import { GradientAggregator } from '@rotastellar/distributed'; const aggregator = new GradientAggregator({ apiKey: 'rs_...', strategy: 'async_fedavg', minNodes: 3, stalenessLimit: 5 }); aggregator.onGradientReceived((nodeId, gradients, metadata) => { console.log(`Received from ${nodeId}`); }); aggregator.start(); // Get updates const globalUpdate = await aggregator.getUpdate(); ``` ## Aggregation Strategies | Strategy | Description | Best For | | ----------------- | ------------------------------------- | ------------------------- | | `sync_fedavg` | Wait for all nodes before aggregating | Reliable connectivity | | `async_fedavg` | Aggregate as updates arrive | Intermittent connectivity | | `weighted_fedavg` | Weight by dataset size | Heterogeneous data | | `momentum_fedavg` | Add momentum to updates | Faster convergence | ## Handling Connectivity Orbital nodes experience intermittent connectivity. The client handles this automatically: ```python theme={null} # The FederatedClient handles: # 1. Gradient compression for bandwidth-limited links # 2. Error feedback for lossless compression over time # 3. Statistics tracking for monitoring from rotastellar_distributed import FederatedClient, CompressionConfig, CompressionMethod client = FederatedClient( node_id="orbital-3", node_type="orbital", compression=CompressionConfig( method=CompressionMethod.TOP_K_QUANTIZED, k_ratio=0.01, quantization_bits=8, error_feedback=True # Accumulate dropped gradients ) ) ``` ## Convergence Guarantees Despite compression and async updates, training converges to the same solution as centralized training: | Property | Guarantee | | ---------------- | ----------------------------------------------- | | Compression loss | Under 0.5% final accuracy vs uncompressed | | Staleness impact | Under 1% accuracy loss with staleness\_limit=10 | | Error feedback | Mathematically lossless over time | | Convergence rate | 1.2-1.5x more rounds than centralized | ## Example: Training LLaMA-70B ```python theme={null} from rotastellar_distributed import FederatedClient, CompressionConfig, CompressionMethod # Configure compression for LLaMA-70B gradients compression = CompressionConfig( method=CompressionMethod.TOP_K_QUANTIZED, k_ratio=0.01, # Keep top 1% quantization_bits=8, # 8-bit quantization error_feedback=True # Lossless over time ) # Initialize orbital node client client = FederatedClient( node_id="orbital-3", node_type="orbital", compression=compression ) # Training loop with gradient compression gradients = client.compute_gradients(model_params, local_batch) compressed = client.compress(gradients) # Check compression stats stats = client.get_stats() print(f"Compression ratio: {stats['compression_ratio']}x") print(f"Total compressed: {stats['total_compressed']}") # Training metrics for 8-node setup: # - 100x gradient compression # - ~40% energy savings vs all-terrestrial # - +18% training time vs centralized ``` ## Next Steps Split models across nodes for inference Optimize ground station pass utilization # Model Partitioning Source: https://docs.rotastellar.com/distributed/model-partitioning Optimal layer placement across Earth and space infrastructure # Model Partitioning **Coming Q1 2026** — This feature is in development. [Request early access](https://rotastellar.com/developers) to be notified when available. ## Overview Large neural networks can be split across Earth and orbital nodes to optimize for latency, bandwidth, or energy efficiency. The Model Partitioning system finds optimal cut points based on your infrastructure topology. ## Key Components Finds optimal model split points Analyzes model layer characteristics Specifies ground vs orbital assignment Predicts end-to-end inference latency ## Why Partition Models? | Scenario | Benefit | | ------------------------------------ | --------------------------------------------------- | | Large models, limited orbital memory | Run embedding layers on ground, attention in orbit | | Latency-sensitive inference | Place early layers close to data source | | Energy optimization | Compute-heavy layers on solar-powered orbital nodes | | Bandwidth constraints | Minimize activation transfer between nodes | ## How It Works Input tokens are received at a ground node where the **Embedding Layer** (150M params) and **Layers 0-10** (2.8B params) process the initial representation. Compressed activations (12 MB) are transmitted to the orbital node via ground-to-space link. **Layers 11-60** (35B params) run on the orbital node - the most compute-intensive portion of the model, powered by solar energy. Output activations (12 MB) are transmitted back to a ground node. **Layers 61-80** (14B params) and the **Output Head** generate the final output tokens. The partition optimizer automatically finds cut points that minimize total latency while respecting memory constraints on each node type. ## Model Profile First, analyze your model to understand layer characteristics: ```python Python theme={null} from rotastellar_distributed import ModelProfile # From PyTorch model profile = ModelProfile.from_pytorch(model) # From TensorFlow/Keras profile = ModelProfile.from_tensorflow(model) # From ONNX file profile = ModelProfile.from_onnx("model.onnx") # Inspect profile print(f"Total parameters: {profile.total_params:,}") print(f"Total layers: {profile.num_layers}") print(f"Memory footprint: {profile.memory_mb:.1f} MB") # Per-layer analysis for layer in profile.layers: print(f"{layer.name}: {layer.params:,} params, " f"{layer.flops:,} FLOPs, " f"{layer.activation_size_mb:.1f} MB activations") ``` ```typescript Node.js theme={null} import { ModelProfile } from '@rotastellar/distributed'; const profile = ModelProfile.fromOnnx('model.onnx'); console.log(`Total parameters: ${profile.totalParams}`); console.log(`Total layers: ${profile.numLayers}`); for (const layer of profile.layers) { console.log(`${layer.name}: ${layer.params} params`); } ``` ```rust Rust theme={null} use rotastellar_distributed::ModelProfile; let profile = ModelProfile::from_onnx("model.onnx")?; println!("Total parameters: {}", profile.total_params()); println!("Total layers: {}", profile.num_layers()); for layer in profile.layers() { println!("{}: {} params", layer.name, layer.params); } ``` ## Partition Optimizer Find optimal cut points based on your topology: ```python Python theme={null} from rotastellar_distributed import PartitionOptimizer, ModelProfile # Define your infrastructure topology = { "ground_nodes": 2, "orbital_nodes": 4, "ground_flops": 100e12, # 100 TFLOPS per ground node "orbital_flops": 20e12, # 20 TFLOPS per orbital node "uplink_bandwidth": 100e6, # 100 Mbps ground→orbit "downlink_bandwidth": 500e6, # 500 Mbps orbit→ground "isl_bandwidth": 10e9, # 10 Gbps inter-satellite "ground_orbit_latency_ms": 25 # LEO latency } # Profile your model profile = ModelProfile.from_pytorch(model) # Find optimal partition optimizer = PartitionOptimizer(api_key="rs_...") partition = optimizer.optimize( model=profile, topology=topology, objective="minimize_latency" # or "minimize_bandwidth", "balance" ) # View results print(f"Optimal cut points: {partition.cut_points}") print(f"Ground layers: {partition.ground_layers}") print(f"Orbital layers: {partition.orbital_layers}") print(f"Estimated latency: {partition.estimated_latency_ms:.1f} ms") print(f"Activation transfer: {partition.transfer_size_mb:.1f} MB") ``` ```typescript Node.js theme={null} import { PartitionOptimizer, ModelProfile } from '@rotastellar/distributed'; const profile = ModelProfile.fromOnnx('model.onnx'); const optimizer = new PartitionOptimizer({ apiKey: 'rs_...' }); const partition = await optimizer.optimize({ model: profile, topology: { groundNodes: 2, orbitalNodes: 4, groundFlops: 100e12, orbitalFlops: 20e12, uplinkBandwidth: 100e6, downlinkBandwidth: 500e6 }, objective: 'minimize_latency' }); console.log(`Cut points: ${partition.cutPoints}`); console.log(`Estimated latency: ${partition.estimatedLatencyMs} ms`); ``` ```rust Rust theme={null} use rotastellar_distributed::{PartitionOptimizer, ModelProfile, Topology, Objective}; let profile = ModelProfile::from_onnx("model.onnx")?; let topology = Topology::new() .ground_nodes(2) .orbital_nodes(4) .ground_flops(100e12) .orbital_flops(20e12); let optimizer = PartitionOptimizer::new(); let partition = optimizer.optimize(&profile, &topology, Objective::MinimizeLatency)?; println!("Cut points: {:?}", partition.cut_points()); println!("Estimated latency: {} ms", partition.estimated_latency_ms()); ``` ## Optimization Objectives | Objective | Optimizes For | Best When | | -------------------- | --------------------------- | ------------------------- | | `minimize_latency` | End-to-end inference time | Real-time applications | | `minimize_bandwidth` | Data transfer between nodes | Limited connectivity | | `minimize_energy` | Total energy consumption | Battery/solar constraints | | `balance` | Weighted combination | General purpose | ## Layer Placement Manually specify or adjust layer placement: ```python theme={null} from rotastellar_distributed import LayerPlacement # Manual placement placement = LayerPlacement() placement.assign_ground(layers=[0, 1, 2, 3, 4]) # First 5 layers placement.assign_orbital(layers=range(5, 75)) # Middle layers placement.assign_ground(layers=[75, 76, 77, 78, 79]) # Last 5 layers # Validate placement validation = placement.validate(profile, topology) if not validation.is_valid: print(f"Issues: {validation.issues}") # Or refine optimizer result partition = optimizer.optimize(model=profile, topology=topology) partition.move_layer(15, to="ground") # Manual adjustment partition.recalculate() ``` ## Latency Estimation Predict inference latency for a given partition: ```python theme={null} from rotastellar_distributed import LatencyEstimator estimator = LatencyEstimator(topology=topology) # Estimate for a partition estimate = estimator.estimate(partition) print(f"Total latency: {estimate.total_ms:.1f} ms") print(f" Ground compute: {estimate.ground_compute_ms:.1f} ms") print(f" Orbital compute: {estimate.orbital_compute_ms:.1f} ms") print(f" Uplink transfer: {estimate.uplink_ms:.1f} ms") print(f" Downlink transfer: {estimate.downlink_ms:.1f} ms") print(f" Propagation: {estimate.propagation_ms:.1f} ms") # Breakdown by layer for layer_est in estimate.by_layer: print(f" {layer_est.name}: {layer_est.total_ms:.1f} ms on {layer_est.node}") ``` ## Example: LLaMA-70B Partitioning ```python theme={null} from rotastellar_distributed import PartitionOptimizer, ModelProfile # LLaMA-70B architecture profile = ModelProfile.from_pytorch(llama_70b) # 80 transformer layers, ~70B parameters topology = { "ground_nodes": 3, "orbital_nodes": 5, "ground_flops": 200e12, # A100 equivalent "orbital_flops": 50e12, # Space-qualified GPU "uplink_bandwidth": 200e6, "downlink_bandwidth": 1e9, "isl_bandwidth": 25e9 } partition = optimizer.optimize( model=profile, topology=topology, objective="minimize_latency" ) # Result for LLaMA-70B: # - Layers 0-8: Ground (embeddings + early attention) # - Layers 9-72: Orbital (bulk computation) # - Layers 73-79 + head: Ground (final layers) # - Activation transfer: 24 MB per inference # - Estimated latency: 180 ms (vs 400 ms all-ground) ``` ## Next Steps Schedule data transfer during ground passes Route between orbital nodes via ISL # Distributed Compute Overview Source: https://docs.rotastellar.com/distributed/overview Coordinate AI workloads across Earth and orbital infrastructure # Distributed Compute **Coming Q1 2026** — Distributed Compute is currently in development. This documentation is a design preview. [Request early access](https://rotastellar.com/developers) to be notified when it's available. ## Overview Distributed Compute enables AI training and inference across hybrid Earth-space infrastructure. Coordinate federated learning, partition models optimally, and synchronize through bandwidth-constrained orbital links. Train models across Earth and orbital nodes with gradient compression Optimal layer placement across Earth and space infrastructure Ground station pass planning and priority-based queuing ISL routing for orbital node communication ## Why Earth-Space Distributed Compute? Large AI models don't fit on any single node. Training and inference must span infrastructure. But space introduces unique constraints: | Challenge | Solution | | ------------------------------------------- | ---------------------------------------------------- | | Bandwidth is scarce (limited ground passes) | 100x gradient compression with TopK + quantization | | Latency varies wildly (5ms to 500ms+) | Async aggregation and intelligent model partitioning | | Connectivity is intermittent | Priority-based sync scheduling across passes | | Topology is dynamic | ISL mesh routing adapts to orbital geometry | ## Architecture Your training job connects to RotaStellar Distributed Compute, which coordinates workloads across ground and orbital infrastructure: The core coordination layer includes **Federated Learning** (gradient compression and aggregation), **Model Partitioning** (optimal layer placement), and **Sync Scheduler** (ground pass planning). Inter-Satellite Link (ISL) routing enables orbital nodes to communicate with each other and relay data to ground stations. **Ground Nodes** provide high-bandwidth terrestrial compute. **LEO Nodes** run solar-powered orbital compute, connected via ISL and synchronized during ground passes. ## Key Capabilities ### Gradient Compression Reduce bandwidth by 100x with minimal accuracy loss: ```python theme={null} from rotastellar_distributed import CompressionConfig compression = CompressionConfig( method="topk_quantized", k_ratio=0.01, # Keep top 1% of gradients quantization_bits=8, # 8-bit quantization error_feedback=True # Accumulate compression error ) # 4.2 MB gradient → 42 KB compressed # Under 0.5% accuracy loss ``` ### Async Aggregation Handle intermittent connectivity with async federated averaging: * Nodes train independently during eclipse/no-contact periods * Gradients sync during ground station passes * Central aggregator handles out-of-order updates * Convergence guaranteed despite variable latency ### Intelligent Partitioning Split models optimally across Earth and orbital nodes: * Minimize data transfer at cut points * Account for per-node compute capacity * Adapt to changing orbital geometry * Balance latency vs throughput ## Quick Start ```python Python theme={null} from rotastellar_distributed import FederatedClient, CompressionConfig # Configure compression compression = CompressionConfig( method="topk_quantized", k_ratio=0.01, quantization_bits=8 ) # Initialize federated client client = FederatedClient( api_key="rs_...", node_id="orbital-3", node_type="orbital", compression=compression ) # Train locally gradients = client.train_step(model, batch) # Sync during ground pass client.sync(gradients, priority="high") ``` ```typescript Node.js theme={null} import { FederatedClient, CompressionConfig } from '@rotastellar/distributed'; const compression = new CompressionConfig({ method: 'topk_quantized', kRatio: 0.01, quantizationBits: 8 }); const client = new FederatedClient({ apiKey: 'rs_...', nodeId: 'orbital-3', nodeType: 'orbital', compression }); const gradients = client.trainStep(model, batch); client.sync(gradients, { priority: 'high' }); ``` ```rust Rust theme={null} use rotastellar_distributed::{FederatedClient, CompressionConfig, CompressionMethod}; let compression = CompressionConfig::new() .method(CompressionMethod::TopKQuantized) .k_ratio(0.01) .quantization_bits(8); let client = FederatedClient::new("orbital-3", compression); let gradients = client.train_step(&model, &batch); client.sync(gradients, Priority::High); ``` ## Performance | Metric | Value | | -------------------- | --------------------------- | | Gradient compression | 100x (4.2 MB → 42 KB) | | Accuracy loss | Under 0.5% vs uncompressed | | Sync efficiency | +45% bandwidth utilization | | Training overhead | +15-20% time vs centralized | | Energy savings | 35-45% vs terrestrial-only | ## Timeline | Milestone | Target | | ------------------------- | ------- | | Design preview (this doc) | Now | | SDK with simulators | Q1 2026 | | Beta with partners | Q2 2026 | | General availability | Q3 2026 | ## Get Notified Be the first to know when Distributed Compute is available. # Space Mesh Source: https://docs.rotastellar.com/distributed/space-mesh ISL routing for orbital node communication # Space Mesh **Coming Q1 2026** — This feature is in development. [Request early access](https://rotastellar.com/developers) to be notified when available. ## Overview Space Mesh enables communication between orbital nodes via Inter-Satellite Links (ISL). When direct ground contact isn't available, data can be routed through neighboring satellites to reach a ground station. ## Key Components ISL network topology manager Path between source and destination Orbital node with ISL capability ISL connection between nodes ## Why ISL Routing? Without ISL, each orbital node must wait for its own ground pass. With ISL, data can relay through neighboring satellites: Each satellite waits independently for ground contact. Long gaps between sync opportunities. | Satellite | Sync Pattern | | --------- | ------------------------------------- | | Sat-1 | Sync - Wait 90min - Sync - Wait 90min | | Sat-2 | Wait 30min - Sync - Wait 90min - Sync | | Sat-3 | Wait 60min - Sync - Wait 90min - Sync | Any satellite can relay through neighbors to reach ground. Continuous sync capability. **Example route:** Sat-1 → Sat-2 → Sat-3 → Ground Station All nodes can sync continuously via mesh routing. ## Mesh Topology ### Constellation Layout The mesh connects orbital nodes via high-bandwidth Inter-Satellite Links (ISL): **Sat-1, Sat-2, Sat-3, Sat-4** in LEO orbit, connected via 10 Gbps optical ISL links Ground stations receive data from any satellite with line-of-sight | Link Type | Bandwidth | Latency | | ------------------------------ | ------------ | ------- | | ISL (satellite to satellite) | 10 Gbps | 3-15 ms | | Downlink (satellite to ground) | 1 Gbps | 5-25 ms | | Uplink (ground to satellite) | 100-500 Mbps | 5-25 ms | ## Basic Usage ```python Python theme={null} from rotastellar_distributed import SpaceMesh # Initialize mesh mesh = SpaceMesh(api_key="rs_...") # Add orbital nodes mesh.add_node("sat-1", orbit_alt=550, isl_range=5000) mesh.add_node("sat-2", orbit_alt=550, isl_range=5000) mesh.add_node("sat-3", orbit_alt=550, isl_range=5000) mesh.add_node("sat-4", orbit_alt=550, isl_range=5000) # Add ground stations mesh.add_ground_station("svalbard", lat=78.2, lon=15.6) mesh.add_ground_station("singapore", lat=1.3, lon=103.8) # Find route route = mesh.find_route( source="sat-1", destination="ground-svalbard", data_size=100e6, # 100 MB max_hops=3 ) print(f"Path: {' → '.join(route.path)}") print(f"Hops: {route.num_hops}") print(f"Total latency: {route.latency_ms:.1f} ms") print(f"Bottleneck: {route.bottleneck_link}") print(f"Available bandwidth: {route.bandwidth / 1e6:.0f} Mbps") ``` ```typescript Node.js theme={null} import { SpaceMesh } from '@rotastellar/distributed'; const mesh = new SpaceMesh({ apiKey: 'rs_...' }); mesh.addNode('sat-1', { orbitAlt: 550, islRange: 5000 }); mesh.addNode('sat-2', { orbitAlt: 550, islRange: 5000 }); mesh.addNode('sat-3', { orbitAlt: 550, islRange: 5000 }); mesh.addGroundStation('svalbard', { lat: 78.2, lon: 15.6 }); const route = await mesh.findRoute({ source: 'sat-1', destination: 'ground-svalbard', dataSize: 100e6, maxHops: 3 }); console.log(`Path: ${route.path.join(' → ')}`); console.log(`Latency: ${route.latencyMs} ms`); ``` ```rust Rust theme={null} use rotastellar_distributed::SpaceMesh; let mut mesh = SpaceMesh::new(); mesh.add_node("sat-1", 550.0, 5000.0); mesh.add_node("sat-2", 550.0, 5000.0); mesh.add_node("sat-3", 550.0, 5000.0); mesh.add_ground_station("svalbard", 78.2, 15.6); let route = mesh.find_route("sat-1", "ground-svalbard", 100e6, 3)?; println!("Path: {:?}", route.path()); println!("Latency: {} ms", route.latency_ms()); ``` ## Link Configuration Configure ISL characteristics: ```python theme={null} # Add node with detailed ISL config mesh.add_node( "sat-1", orbit_alt=550, # km orbit_inc=53, # degrees inclination isl_config={ "range_km": 5000, # Max ISL range "bandwidth": 10e9, # 10 Gbps "latency_per_km": 0.003, # ms per km "max_connections": 4, # Max simultaneous links "optical": True # Optical vs RF } ) # View current links links = mesh.get_links("sat-1") for link in links: print(f"{link.source} ↔ {link.target}") print(f" Distance: {link.distance_km:.0f} km") print(f" Bandwidth: {link.bandwidth / 1e9:.0f} Gbps") print(f" Latency: {link.latency_ms:.1f} ms") print(f" Status: {link.status}") ``` ## Routing Algorithms | Algorithm | Description | Best For | | --------------- | ----------------------- | ---------------- | | `shortest_path` | Minimum hops | Low latency | | `max_bandwidth` | Highest capacity path | Large transfers | | `min_latency` | Lowest total delay | Real-time | | `load_balanced` | Distribute across paths | High utilization | ```python theme={null} # Shortest path (default) route = mesh.find_route(source, dest, algorithm="shortest_path") # Maximum bandwidth route = mesh.find_route(source, dest, algorithm="max_bandwidth") # Minimum latency route = mesh.find_route(source, dest, algorithm="min_latency") # Load balanced route = mesh.find_route(source, dest, algorithm="load_balanced") ``` ## Dynamic Topology The mesh adapts as satellites move: ```python theme={null} # Update positions (typically from TLE) mesh.update_positions(epoch=datetime.now()) # Or subscribe to position updates @mesh.on_topology_change def handle_change(event): if event.type == "link_lost": print(f"Link lost: {event.source} ↔ {event.target}") # Routes using this link are automatically rerouted elif event.type == "link_established": print(f"New link: {event.source} ↔ {event.target}") # Get current network state state = mesh.get_state() print(f"Active nodes: {state.active_nodes}") print(f"Active links: {state.active_links}") print(f"Network diameter: {state.diameter} hops") print(f"Avg path length: {state.avg_path_length:.1f} hops") ``` ## Multi-Path Routing For reliability, use multiple paths: ```python theme={null} # Find multiple disjoint paths paths = mesh.find_paths( source="sat-1", destination="ground-svalbard", num_paths=3, disjoint=True # No shared links ) for i, path in enumerate(paths): print(f"Path {i+1}: {' → '.join(path.nodes)}") print(f" Bandwidth: {path.bandwidth / 1e6:.0f} Mbps") # Split data across paths transfers = mesh.split_transfer( data_size=1e9, # 1 GB paths=paths, strategy="proportional" # By bandwidth ) ``` ## Traffic Shaping Manage bandwidth allocation: ```python theme={null} # Reserve bandwidth for critical traffic reservation = mesh.reserve_bandwidth( source="sat-1", destination="ground-svalbard", bandwidth=100e6, # 100 Mbps duration_seconds=300, priority="critical" ) # Monitor traffic traffic = mesh.get_traffic() for link in traffic.links: print(f"{link.id}: {link.utilization:.1%} utilized") print(f" Current: {link.current_throughput / 1e6:.0f} Mbps") print(f" Peak: {link.peak_throughput / 1e6:.0f} Mbps") ``` ## Example: Global Coverage ```python theme={null} from rotastellar_distributed import SpaceMesh # Create mesh for a Walker constellation mesh = SpaceMesh(api_key="rs_...") # Add 40 satellites in polar orbit for plane in range(8): for sat in range(5): mesh.add_node( f"sat-{plane}-{sat}", orbit_alt=550, orbit_inc=97.5, raan=plane * 45, # Right ascension true_anomaly=sat * 72, # Position in plane isl_range=5000 ) # Add global ground stations stations = [ ("svalbard", 78.2, 15.6), ("hawaii", 19.8, -155.5), ("singapore", 1.3, 103.8), ("chile", -33.4, -70.6), ("south-africa", -33.9, 18.4), ] for name, lat, lon in stations: mesh.add_ground_station(name, lat, lon) # Network stats state = mesh.get_state() print(f"Satellites: {state.active_nodes}") print(f"ISL links: {state.active_links}") print(f"Ground stations: {state.ground_stations}") print(f"Global coverage: {state.coverage:.1%}") # Any satellite can reach ground within 2 hops for sat in mesh.nodes: routes = mesh.find_paths(sat, "any-ground", max_hops=2) assert len(routes) > 0, f"{sat} has no route to ground!" ``` ## Integration with Sync Scheduler Space Mesh integrates with the Sync Scheduler for optimal routing: ```python theme={null} from rotastellar_distributed import SyncScheduler, SpaceMesh # Initialize both mesh = SpaceMesh(api_key="rs_...") scheduler = SyncScheduler( api_key="rs_...", mesh=mesh # Enable ISL routing ) # Schedule sync - will use ISL if direct pass unavailable sync = scheduler.schedule_sync( node="sat-1", data_size=100e6, priority="critical", allow_relay=True # Allow ISL relay ) # Sync might go: sat-1 → sat-2 → ground-svalbard print(f"Route: {' → '.join(sync.route.path)}") ``` ## Next Steps Schedule syncs with mesh routing Train models across the mesh # Sync Scheduler Source: https://docs.rotastellar.com/distributed/sync-scheduler Ground station pass planning and priority-based queuing # Sync Scheduler **Coming Q1 2026** — This feature is in development. [Request early access](https://rotastellar.com/developers) to be notified when available. ## Overview Orbital nodes can only sync with ground during ground station passes. The Sync Scheduler optimizes data transfer across these limited windows, ensuring critical updates are prioritized and bandwidth is fully utilized. ## Key Components Main scheduler for pass planning Ground station configuration Bandwidth-aware priority queuing Pass window with bandwidth estimate ## The Synchronization Challenge Ground station passes are intermittent - each satellite only has line-of-sight to a ground station for a portion of each orbit. | Ground Station | Location | Typical Pass Pattern | | -------------- | -------- | ------------------------------- | | Svalbard | 78°N | 8-10 passes/day, 10-15 min each | | Singapore | 1°N | 4-6 passes/day, 8-12 min each | **Combined coverage** from multiple ground stations reduces gaps but doesn't eliminate them. The Sync Scheduler optimizes data transfer across these limited windows. ## Ground Station Configuration ```python Python theme={null} from rotastellar_distributed import SyncScheduler, GroundStation # Define your ground stations stations = [ GroundStation( name="svalbard", lat=78.2, lon=15.6, bandwidth=1e9, # 1 Gbps elevation_min=10 # Minimum elevation angle ), GroundStation( name="singapore", lat=1.3, lon=103.8, bandwidth=500e6 # 500 Mbps ), GroundStation( name="santiago", lat=-33.4, lon=-70.6, bandwidth=500e6 ) ] # Initialize scheduler scheduler = SyncScheduler( api_key="rs_...", ground_stations=stations, orbital_nodes=["orbital-1", "orbital-2", "orbital-3"] ) ``` ```typescript Node.js theme={null} import { SyncScheduler, GroundStation } from '@rotastellar/distributed'; const stations = [ new GroundStation('svalbard', { lat: 78.2, lon: 15.6, bandwidth: 1e9 }), new GroundStation('singapore', { lat: 1.3, lon: 103.8, bandwidth: 500e6 }), new GroundStation('santiago', { lat: -33.4, lon: -70.6, bandwidth: 500e6 }) ]; const scheduler = new SyncScheduler({ apiKey: 'rs_...', groundStations: stations, orbitalNodes: ['orbital-1', 'orbital-2', 'orbital-3'] }); ``` ```rust Rust theme={null} use rotastellar_distributed::{SyncScheduler, GroundStation}; let stations = vec![ GroundStation::new("svalbard", 78.2, 15.6).bandwidth(1e9), GroundStation::new("singapore", 1.3, 103.8).bandwidth(500e6), GroundStation::new("santiago", -33.4, -70.6).bandwidth(500e6), ]; let scheduler = SyncScheduler::new() .ground_stations(stations) .orbital_nodes(vec!["orbital-1", "orbital-2", "orbital-3"]); ``` ## Getting Sync Windows Query upcoming sync opportunities: ```python Python theme={null} from datetime import datetime, timedelta # Get next 24 hours of sync windows windows = scheduler.get_windows(hours=24) for window in windows: print(f"Node: {window.orbital_node}") print(f"Station: {window.ground_station}") print(f"Start: {window.start}") print(f"Duration: {window.duration_seconds}s") print(f"Max elevation: {window.max_elevation}°") print(f"Bandwidth: {window.bandwidth / 1e6:.0f} Mbps") print(f"Capacity: {window.capacity_mb:.0f} MB") print() # Filter for specific node orbital_1_windows = scheduler.get_windows( hours=24, node="orbital-1" ) # Filter for specific station svalbard_windows = scheduler.get_windows( hours=24, station="svalbard" ) ``` ```typescript Node.js theme={null} const windows = await scheduler.getWindows({ hours: 24 }); for (const window of windows) { console.log(`${window.orbitalNode} → ${window.groundStation}`); console.log(`Start: ${window.start}, Duration: ${window.durationSeconds}s`); console.log(`Capacity: ${window.capacityMb} MB`); } ``` ```rust Rust theme={null} let windows = scheduler.get_windows(24).await?; for window in windows { println!("{} → {}", window.orbital_node, window.ground_station); println!("Capacity: {} MB", window.capacity_mb); } ``` ## Scheduling Sync Operations Schedule data transfers with priority: ```python Python theme={null} from datetime import datetime, timedelta # Schedule a sync operation sync = scheduler.schedule_sync( node="orbital-1", data_size=50e6, # 50 MB priority="critical", # "critical", "high", "normal", "low" deadline=datetime.now() + timedelta(hours=2), data_type="gradients" ) print(f"Sync ID: {sync.id}") print(f"Scheduled window: {sync.window.start}") print(f"Estimated completion: {sync.estimated_completion}") # Schedule multiple operations syncs = scheduler.schedule_batch([ {"node": "orbital-1", "data_size": 50e6, "priority": "critical"}, {"node": "orbital-2", "data_size": 30e6, "priority": "high"}, {"node": "orbital-3", "data_size": 100e6, "priority": "normal"}, ]) ``` ```typescript Node.js theme={null} const sync = await scheduler.scheduleSync({ node: 'orbital-1', dataSize: 50e6, priority: 'critical', deadline: new Date(Date.now() + 2 * 60 * 60 * 1000) }); console.log(`Scheduled for: ${sync.window.start}`); ``` ## Priority Queue The scheduler maintains a priority queue for each orbital node: ```python theme={null} # View queue for a node queue = scheduler.get_queue("orbital-1") for item in queue.items: print(f"ID: {item.id}") print(f"Priority: {item.priority}") print(f"Size: {item.data_size / 1e6:.1f} MB") print(f"Deadline: {item.deadline}") print(f"Status: {item.status}") print() # Queue statistics print(f"Total queued: {queue.total_size / 1e6:.1f} MB") print(f"Critical items: {queue.critical_count}") print(f"Estimated clear time: {queue.estimated_clear_time}") ``` ### Priority Levels | Priority | Description | Preemption | | ---------- | --------------------------------------- | --------------------- | | `critical` | Safety-critical or time-sensitive | Preempts all others | | `high` | Important updates (e.g., model weights) | Preempts normal/low | | `normal` | Standard sync (e.g., gradients) | No preemption | | `low` | Background sync (e.g., telemetry) | Fills unused capacity | ## Optimization Optimize sync schedule across all nodes and stations: ```python theme={null} # Generate optimized schedule plan = scheduler.optimize( horizon_hours=24, objectives={ "minimize_latency": 0.5, # Weight for latency "maximize_throughput": 0.3, # Weight for throughput "balance_load": 0.2 # Weight for load balancing } ) print(f"Scheduled {len(plan.operations)} sync operations") print(f"Total data: {plan.total_data_mb:.0f} MB") print(f"Bandwidth utilization: {plan.utilization:.1%}") print(f"Average wait time: {plan.avg_wait_minutes:.1f} min") # View schedule for op in plan.operations: print(f"{op.time}: {op.node} → {op.station} ({op.data_mb:.0f} MB)") # Apply the optimized schedule scheduler.apply(plan) ``` ## Monitoring Track sync operations in real-time: ```python theme={null} # Get current sync status status = scheduler.get_status() print(f"Active syncs: {status.active_count}") print(f"Queued: {status.queued_count}") print(f"Completed (24h): {status.completed_24h}") print(f"Failed (24h): {status.failed_24h}") # Monitor specific operation sync_status = scheduler.get_sync_status(sync_id) print(f"Progress: {sync_status.progress:.1%}") print(f"Bytes transferred: {sync_status.bytes_transferred}") print(f"Current rate: {sync_status.rate_mbps:.1f} Mbps") # Set up callbacks @scheduler.on_sync_complete def handle_complete(sync): print(f"Sync {sync.id} completed: {sync.data_size / 1e6:.1f} MB") @scheduler.on_sync_failed def handle_failed(sync, error): print(f"Sync {sync.id} failed: {error}") # Auto-reschedule critical syncs if sync.priority == "critical": scheduler.reschedule(sync.id) ``` ## Example: 24-Hour Sync Plan ```python theme={null} from rotastellar_distributed import SyncScheduler, GroundStation # Setup scheduler = SyncScheduler( api_key="rs_...", ground_stations=[ GroundStation("svalbard", lat=78.2, lon=15.6, bandwidth=1e9), GroundStation("singapore", lat=1.3, lon=103.8, bandwidth=500e6), GroundStation("chile", lat=-33.4, lon=-70.6, bandwidth=500e6), ], orbital_nodes=["sat-1", "sat-2", "sat-3", "sat-4", "sat-5"] ) # Queue gradient syncs for all nodes for i in range(1, 6): scheduler.schedule_sync( node=f"sat-{i}", data_size=100e6, # 100 MB gradients per node priority="high", data_type="gradients" ) # Optimize plan = scheduler.optimize(horizon_hours=24) # Results: # - 5 nodes × 100 MB = 500 MB total # - 12 ground passes utilized # - Average wait time: 45 minutes # - Bandwidth utilization: 78% # - All syncs complete within 6 hours ``` ## Next Steps Route between orbital nodes via ISL Train models with sync scheduler # Conjunction Analysis Source: https://docs.rotastellar.com/intelligence/conjunctions Collision probability and avoidance recommendations # Conjunction Analysis Analyze potential collisions between space objects and receive recommendations for avoidance maneuvers. **Status:** Early Access — [Request API key](https://rotastellar.com/developers) ## Overview Conjunction analysis evaluates: * **Time of Closest Approach (TCA)** — When objects will be nearest * **Miss Distance** — Predicted separation at TCA * **Collision Probability** — Statistical likelihood of collision * **Avoidance Options** — Maneuver recommendations if needed ## Quick Start ```python Python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient(api_key="rs_...") # Get conjunctions for a satellite conjunctions = client.list_conjunctions( satellite_id="STARLINK-1234", threshold_km=5.0, limit=10 ) for conj in conjunctions: print(f"TCA: {conj['tca']}") print(f"Miss distance: {conj['miss_distance_km']} km") print(f"Probability: {conj['collision_probability']:.2e}") print() ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); const conjunctions = await client.listConjunctions({ satelliteId: 'STARLINK-1234', thresholdKm: 5.0, limit: 10 }); for (const conj of conjunctions) { console.log(`TCA: ${conj.tca}`); console.log(`Miss: ${conj.miss_distance_km} km`); console.log(`Probability: ${conj.collision_probability}`); } ``` ```rust Rust theme={null} // Rust SDK provides types only (HTTP client coming soon) // Use Python or Node.js SDK for full API access // See /sdks/rust for available types ``` ```bash cURL theme={null} curl "https://api.rotastellar.com/v1/conjunctions?satellite=STARLINK-1234&threshold_km=5&days_ahead=7" \ -H "Authorization: Bearer rs_your_api_key" ``` ## Get Conjunctions ``` GET /v1/conjunctions ``` Primary satellite (NORAD ID or name) Maximum miss distance to report (km) Prediction window (1-14 days) Minimum collision probability to report (e.g., 1e-6) ### Response ```json theme={null} { "conjunctions": [ { "id": "conj_abc123", "tca": "2026-01-23T14:32:15Z", "primary": { "id": "12345", "name": "STARLINK-1234", "operator": "SpaceX" }, "secondary": { "id": "45678", "name": "COSMOS 2251 DEB", "type": "DEBRIS" }, "miss_km": 0.45, "probability": 2.3e-5, "risk_level": "HIGH", "relative_velocity_km_s": 14.2, "geometry": { "radial_km": 0.12, "in_track_km": 0.38, "cross_track_km": 0.18 }, "covariance_available": true, "data_quality": "GOOD" } ], "screening_window": { "start": "2026-01-21T00:00:00Z", "end": "2026-01-28T00:00:00Z" }, "total_count": 12 } ``` ## Risk Levels | Level | Probability Range | Recommended Action | | ---------- | ----------------- | ------------------------- | | `LOW` | \< 1e-5 | Monitor | | `MEDIUM` | 1e-5 to 1e-4 | Review, consider maneuver | | `HIGH` | 1e-4 to 1e-3 | Plan maneuver | | `CRITICAL` | > 1e-3 | Execute maneuver | ## Conjunction Details Get detailed information about a specific conjunction: ``` GET /v1/conjunctions/{conjunction_id} ``` ```python Python theme={null} # Get conjunction details via REST API import requests response = requests.get( "https://api.rotastellar.com/v1/conjunctions/conj_abc123", headers={"Authorization": "Bearer rs_your_api_key"} ) conj = response.json() print(f"TCA: {conj['tca']}") print(f"Miss: {conj['miss_km']} km") print(f"Radial: {conj['geometry']['radial_km']} km") print(f"In-track: {conj['geometry']['in_track_km']} km") print(f"Cross-track: {conj['geometry']['cross_track_km']} km") # Check avoidance options if conj['risk_level'] in ["HIGH", "CRITICAL"]: for opt in conj.get('avoidance_options', []): print(f"Maneuver: {opt['delta_v_m_s']} m/s at {opt['burn_time']}") print(f"New miss distance: {opt['resulting_miss_km']} km") ``` ```bash cURL theme={null} curl https://api.rotastellar.com/v1/conjunctions/conj_abc123 \ -H "Authorization: Bearer rs_your_api_key" ``` ### Detailed Response ```json theme={null} { "id": "conj_abc123", "tca": "2026-01-23T14:32:15Z", "miss_km": 0.45, "probability": 2.3e-5, "risk_level": "HIGH", "primary": { "id": "12345", "name": "STARLINK-1234", "position_at_tca": { "lat": 45.2, "lon": -122.5, "altitude_km": 550 } }, "secondary": { "id": "45678", "name": "COSMOS 2251 DEB", "position_at_tca": { "lat": 45.3, "lon": -122.4, "altitude_km": 550.3 } }, "geometry": { "radial_km": 0.12, "in_track_km": 0.38, "cross_track_km": 0.18 }, "covariance": { "primary_sigma_r_km": 0.05, "primary_sigma_t_km": 0.15, "primary_sigma_n_km": 0.02, "secondary_sigma_r_km": 0.50, "secondary_sigma_t_km": 1.50, "secondary_sigma_n_km": 0.30 }, "avoidance_options": [ { "type": "in_track", "delta_v_m_s": 0.5, "burn_time": "2026-01-23T10:00:00Z", "resulting_miss_km": 5.2, "fuel_cost_kg": 0.02 }, { "type": "radial", "delta_v_m_s": 0.3, "burn_time": "2026-01-23T08:00:00Z", "resulting_miss_km": 3.8, "fuel_cost_kg": 0.012 } ], "updates": [ { "timestamp": "2026-01-21T12:00:00Z", "miss_km": 0.52, "probability": 1.8e-5 }, { "timestamp": "2026-01-22T00:00:00Z", "miss_km": 0.45, "probability": 2.3e-5 } ] } ``` ## Monitoring Conjunctions Set up continuous monitoring for your satellites: ```python Python theme={null} # Create a watch for conjunction alerts via REST API import requests response = requests.post( "https://api.rotastellar.com/v1/conjunctions/watch", headers={ "Authorization": "Bearer rs_your_api_key", "Content-Type": "application/json" }, json={ "satellites": ["SAT-001", "SAT-002", "SAT-003"], "threshold_km": 5.0, "min_probability": 1e-6, "webhook_url": "https://your-app.com/conjunction-alerts" } ) watch = response.json() print(f"Watch ID: {watch['id']}") print(f"Status: {watch['status']}") ``` ```bash cURL theme={null} curl -X POST https://api.rotastellar.com/v1/conjunctions/watch \ -H "Authorization: Bearer rs_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "satellites": ["SAT-001", "SAT-002", "SAT-003"], "threshold_km": 5.0, "min_probability": 1e-6, "webhook_url": "https://your-app.com/conjunction-alerts" }' ``` ## Fleet Screening Screen multiple satellites at once: ```python theme={null} # Screen entire constellation satellites = ["SAT-001", "SAT-002", "SAT-003", "SAT-004"] results = {} for sat_id in satellites: conjunctions = client.list_conjunctions( satellite_id=sat_id, threshold_km=5.0, limit=50 ) results[sat_id] = conjunctions for sat_id, conjunctions in results.items(): print(f"\n{sat_id}: {len(conjunctions)} conjunctions") for conj in conjunctions: print(f" - Miss: {conj['miss_distance_km']}km") ``` ## Next Steps Detect anomalies and maneuvers Set up real-time alerts # Orbital Intelligence Overview Source: https://docs.rotastellar.com/intelligence/overview Track, analyze, and understand objects in Earth orbit # Orbital Intelligence **Status:** Early Access — [Request API key](https://rotastellar.com/developers) Orbital Intelligence provides real-time situational awareness for objects in Earth orbit. Track satellites, analyze conjunction risks, and detect anomalous behavior. ## Capabilities Real-time positions for 10,000+ active satellites Collision probability and avoidance recommendations Detect anomalies and maneuvers in satellite behavior Real-time alerts for events of interest ## Quick Start ```python Python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient(api_key="rs_...") # Track the International Space Station iss = client.get_satellite("25544") # ISS NORAD ID print(f"Location: {iss.position.latitude}, {iss.position.longitude}") print(f"Altitude: {iss.position.altitude_km} km") # Check for upcoming conjunctions conjunctions = client.list_conjunctions( satellite_id="25544", threshold_km=5.0, limit=10 ) for conj in conjunctions: print(f"TCA: {conj['tca']}") print(f"Miss distance: {conj['miss_distance_km']} km") print(f"Probability: {conj['collision_probability']}") ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); // Track ISS const iss = await client.getSatellite('25544'); console.log(`Location: ${iss.position?.latitude}, ${iss.position?.longitude}`); console.log(`Altitude: ${iss.position?.altitudeKm} km`); // Check conjunctions const conjunctions = await client.listConjunctions({ satelliteId: '25544', thresholdKm: 5.0, limit: 10 }); for (const conj of conjunctions) { console.log(`TCA: ${conj.tca}, Miss: ${conj.miss_distance_km} km`); } ``` ```bash cURL theme={null} # Get ISS position curl https://api.rotastellar.com/v1/satellites/ISS \ -H "Authorization: Bearer rs_your_api_key" # Check conjunctions curl "https://api.rotastellar.com/v1/conjunctions?satellite=ISS&threshold_km=5&days_ahead=7" \ -H "Authorization: Bearer rs_your_api_key" ``` ## Data Sources | Source | Coverage | Update Frequency | | ----------- | ----------------- | ---------------- | | Space-Track | Global catalog | Every 8 hours | | Commercial | Active satellites | Real-time | | Proprietary | Enhanced accuracy | Continuous | ## Catalog Coverage * **10,000+** active satellites * **35,000+** debris objects tracked * **45,000+** total tracked objects * **Global** coverage from multiple sensor networks ## Use Cases ### Fleet Management Track your entire satellite constellation and monitor health: ```python theme={null} # Get all satellites in your constellation constellation = client.list_satellites( operator="YourCompany", constellation="YourConstellation" ) for sat in constellation: print(f"{sat.name}: {sat.position.altitude_km}km") ``` ### Collision Avoidance Get alerts when conjunction risks exceed thresholds: ```python theme={null} # Set up conjunction monitoring via webhook # See /intelligence/webhooks for full setup import requests requests.post( "https://api.rotastellar.com/v1/conjunctions/watch", headers={"Authorization": "Bearer rs_your_api_key"}, json={ "satellites": ["SAT-001", "SAT-002", "SAT-003"], "threshold_km": 1.0, "webhook_url": "https://your-app.com/alerts" } ) ``` ### Anomaly Detection Detect unexpected maneuvers or behavior changes: ```python theme={null} anomalies = client.list_patterns( satellite_id="TARGET-SAT", type="anomaly", lookback_days=30 ) for anomaly in anomalies: print(f"{anomaly['timestamp']}: {anomaly['type']}") print(f"Description: {anomaly['description']}") ``` ## Rate Limits | Endpoint | Free | Pro | Enterprise | | --------------- | ------ | ------- | ---------- | | Get Satellite | 10/min | 100/min | Custom | | List Satellites | 5/min | 50/min | Custom | | Conjunctions | 5/min | 50/min | Custom | | Patterns | 2/min | 20/min | Custom | ## Next Steps Deep dive into satellite tracking API Learn about collision risk assessment # Pattern Detection Source: https://docs.rotastellar.com/intelligence/patterns Detect anomalies and maneuvers in satellite behavior # Pattern Detection Detect unusual behavior, maneuvers, and anomalies in satellite operations using AI-powered pattern analysis. **Status:** Early Access — [Request API key](https://rotastellar.com/developers) ## Overview Pattern detection identifies: * **Maneuvers** — Orbit-raising, lowering, plane changes * **Anomalies** — Unexpected behavior deviations * **Operational changes** — Mode changes, activation/deactivation * **Proximity operations** — Rendezvous and docking ## Quick Start ```python Python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient(api_key="rs_...") # Get detected patterns for a satellite patterns = client.list_patterns( satellite_id="44832", # COSMOS-2542 lookback_days=30 ) for pattern in patterns: print(f"Type: {pattern['type']}") print(f"Time: {pattern['timestamp']}") print(f"Confidence: {pattern['confidence']}") print(f"Description: {pattern['description']}") print() ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); const patterns = await client.listPatterns({ satelliteId: '44832', // COSMOS-2542 lookbackDays: 30 }); for (const pattern of patterns) { console.log(`${pattern.type}: ${pattern.description}`); console.log(`Confidence: ${pattern.confidence}`); } ``` ```bash cURL theme={null} curl "https://api.rotastellar.com/v1/patterns?satellite=COSMOS-2542&lookback_days=30" \ -H "Authorization: Bearer rs_your_api_key" ``` ## Get Patterns ``` GET /v1/patterns ``` Satellite ID or name Analysis window (1-365 days) Filter by pattern type: `maneuver`, `anomaly`, `proximity`, `operational` Minimum confidence threshold (0-1) ### Response ```json theme={null} { "satellite": { "id": "44832", "name": "COSMOS-2542" }, "patterns": [ { "id": "pat_xyz789", "type": "maneuver", "subtype": "orbit_raise", "timestamp": "2026-01-15T08:23:00Z", "confidence": 0.95, "description": "Orbit raising maneuver detected, altitude increased by 12km", "details": { "delta_altitude_km": 12.3, "delta_v_estimated_m_s": 2.1, "pre_altitude_km": 538, "post_altitude_km": 550.3 } }, { "id": "pat_abc456", "type": "proximity", "subtype": "approach", "timestamp": "2026-01-10T14:45:00Z", "confidence": 0.88, "description": "Approached USA-245 within 50km, maintained position for 6 hours", "details": { "target": "USA-245", "min_distance_km": 48.2, "duration_hours": 6.2 } }, { "id": "pat_def123", "type": "anomaly", "subtype": "attitude_change", "timestamp": "2026-01-05T22:10:00Z", "confidence": 0.72, "description": "Unusual attitude variation detected, possible sensor reorientation", "details": { "magnitude_deg": 15.3, "duration_min": 45 } } ], "analysis_window": { "start": "2025-12-22T00:00:00Z", "end": "2026-01-21T00:00:00Z" } } ``` ## Pattern Types ### Maneuvers Detected orbital changes: | Subtype | Description | | ----------------- | ------------------------------- | | `orbit_raise` | Altitude increase | | `orbit_lower` | Altitude decrease | | `plane_change` | Inclination adjustment | | `phasing` | Along-track position adjustment | | `station_keeping` | Maintenance maneuver | | `deorbit` | End-of-life maneuver | ```python theme={null} # Get only maneuvers maneuvers = client.list_patterns( satellite_id="STARLINK-1234", type="maneuver", lookback_days=90 ) for m in maneuvers: print(f"{m['timestamp']}: {m['subtype']}") print(f" Delta-V: {m['details']['delta_v_estimated_m_s']} m/s") ``` ### Anomalies Unexpected behavior deviations: | Subtype | Description | | ---------------------- | ----------------------------- | | `attitude_change` | Unexpected orientation change | | `tumbling` | Loss of attitude control | | `fragmentation` | Debris generation event | | `signal_loss` | Communication anomaly | | `trajectory_deviation` | Unexpected position change | ```python theme={null} # Get anomalies anomalies = client.list_patterns( satellite_id="DEBRIS-12345", type="anomaly", lookback_days=7 ) for a in anomalies: if a['subtype'] == "fragmentation": print(f"ALERT: Possible fragmentation at {a['timestamp']}") ``` ### Proximity Operations Close approaches and rendezvous: ```python theme={null} # Detect proximity operations proximity = client.list_patterns( satellite_id="INSPECTOR-SAT", type="proximity", lookback_days=60 ) for p in proximity: print(f"Approached {p['details']['target']}") print(f" Min distance: {p['details']['min_distance_km']} km") print(f" Duration: {p['details']['duration_hours']} hours") ``` ## Real-Time Anomaly Detection Get immediate alerts for anomalies: ```python Python theme={null} # Set up anomaly monitoring via webhook # See /intelligence/webhooks for full webhook setup import requests requests.post( "https://api.rotastellar.com/v1/patterns/monitor", headers={"Authorization": "Bearer rs_your_api_key"}, json={ "satellites": ["CRITICAL-SAT-1", "CRITICAL-SAT-2"], "types": ["anomaly", "proximity"], "min_confidence": 0.8, "webhook_url": "https://your-app.com/pattern-alerts" } ) ``` ```bash cURL theme={null} curl -X POST https://api.rotastellar.com/v1/patterns/monitor \ -H "Authorization: Bearer rs_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "satellites": ["CRITICAL-SAT-1", "CRITICAL-SAT-2"], "types": ["anomaly", "proximity"], "min_confidence": 0.8, "webhook_url": "https://your-app.com/pattern-alerts" }' ``` ## Historical Analysis Analyze long-term behavioral patterns: ```python theme={null} # Get 1-year pattern history history = client.list_patterns( satellite_id="GEO-SAT-1", lookback_days=365 ) # Analyze maneuver frequency maneuvers = [p for p in history if p['type'] == "maneuver"] print(f"Total maneuvers: {len(maneuvers)}") print(f"Station-keeping: {sum(1 for m in maneuvers if m['subtype'] == 'station_keeping')}") ``` ## Batch Analysis Analyze patterns across multiple satellites: ```python theme={null} # Analyze entire constellation satellites = ["SAT-001", "SAT-002", "SAT-003"] results = {} for sat_id in satellites: patterns = client.list_patterns(satellite_id=sat_id, lookback_days=30) results[sat_id] = patterns for sat_id, patterns in results.items(): anomalies = [p for p in patterns if p['type'] == "anomaly"] if anomalies: print(f"{sat_id}: {len(anomalies)} anomalies detected") ``` ## Next Steps Set up real-time pattern alerts Track satellite positions # Satellite Tracking Source: https://docs.rotastellar.com/intelligence/satellites Real-time positions for 10,000+ active satellites # Satellite Tracking Track any satellite in Earth orbit with real-time position data, orbital parameters, and historical trajectories. **Status:** Early Access — [Request API key](https://rotastellar.com/developers) ## Overview The Satellite Tracking API provides: * **Real-time positions** — Current lat/lon/altitude for any tracked object * **Orbital parameters** — Keplerian elements, period, inclination * **Propagation** — Future position predictions * **Historical data** — Past trajectory archive ## Catalog Coverage | Category | Count | Sources | | ----------------- | ------- | ----------------------- | | Active satellites | 10,000+ | Space-Track, commercial | | Debris objects | 35,000+ | Space-Track | | Total tracked | 45,000+ | Multiple sources | ## Quick Start ```python Python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient(api_key="rs_...") # Get satellite by NORAD ID iss = client.get_satellite("25544") # ISS # Current position print(f"Location: {iss.position.latitude}, {iss.position.longitude}") print(f"Altitude: {iss.position.altitude_km} km") # Orbital parameters print(f"Period: {iss.orbit.orbital_period_minutes} minutes") print(f"Inclination: {iss.orbit.inclination_deg} deg") ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); // Get satellite const iss = await client.getSatellite('25544'); // ISS // Current position console.log(`Location: ${iss.position?.latitude}, ${iss.position?.longitude}`); console.log(`Altitude: ${iss.position?.altitudeKm} km`); // Orbital parameters console.log(`Period: ${iss.orbit?.periodMin} minutes`); ``` ```rust Rust theme={null} use rotastellar::types::{Position, Orbit}; fn main() -> Result<(), Box> { // Rust SDK provides types only (HTTP client coming soon) // Use Python or Node.js SDK for full API access let pos = Position::new(41.264, -95.123, 420.5)?; println!("Location: {}, {}", pos.latitude, pos.longitude); println!("Altitude: {} km", pos.altitude_km); Ok(()) } ``` ```bash cURL theme={null} curl https://api.rotastellar.com/v1/satellites/ISS \ -H "Authorization: Bearer rs_your_api_key" ``` ## Get Satellite Retrieve information about a specific satellite. ``` GET /v1/satellites/{satellite_id} ``` NORAD catalog ID or common name (e.g., "25544" or "ISS") ### Response ```json theme={null} { "id": "25544", "name": "ISS (ZARYA)", "names": ["ISS", "ZARYA", "INTERNATIONAL SPACE STATION"], "type": "PAYLOAD", "operator": "NASA/Roscosmos", "launch_date": "1998-11-20", "position": { "lat": 41.264, "lon": -95.123, "altitude_km": 420.5, "velocity_km_s": 7.66, "timestamp": "2026-01-21T12:00:00Z" }, "orbit": { "period_min": 92.9, "inclination_deg": 51.64, "apogee_km": 422, "perigee_km": 418, "eccentricity": 0.0002 } } ``` ## List Satellites Query the satellite catalog with filters. ``` GET /v1/satellites ``` Filter by object type: `PAYLOAD`, `ROCKET_BODY`, `DEBRIS` Filter by operator (e.g., "SpaceX", "OneWeb") Filter by constellation (e.g., "Starlink", "OneWeb") Maximum results (1-1000) Pagination cursor for next page ### Example: List Starlink Satellites ```python Python theme={null} starlinks = client.list_satellites( constellation="Starlink", limit=100 ) for sat in starlinks: print(f"{sat.name}: {sat.position.altitude_km} km") ``` ```bash cURL theme={null} curl "https://api.rotastellar.com/v1/satellites?constellation=Starlink&limit=100" \ -H "Authorization: Bearer rs_your_api_key" ``` ## Get Position Get current or predicted position. ``` GET /v1/satellites/{satellite_id}/position ``` ISO 8601 timestamp for prediction (default: now) ### Example: Predict Future Position ```python Python theme={null} from datetime import datetime, timedelta # Where will ISS be in 2 hours? future = (datetime.utcnow() + timedelta(hours=2)).isoformat() pos = client.get_satellite_position("25544", at=future) print(f"Predicted: {pos.latitude}, {pos.longitude}") ``` ```bash cURL theme={null} curl "https://api.rotastellar.com/v1/satellites/ISS/position?at=2026-01-21T14:00:00Z" \ -H "Authorization: Bearer rs_your_api_key" ``` ## Get Trajectory Get position history or predictions over a time range. ``` GET /v1/satellites/{satellite_id}/trajectory ``` Start time (ISO 8601) End time (ISO 8601) Time between points in seconds ### Example: Get 24-hour Trajectory ```python Python theme={null} from datetime import datetime, timedelta trajectory = client.get_trajectory( satellite_id="25544", start=datetime.utcnow().isoformat(), end=(datetime.utcnow() + timedelta(hours=24)).isoformat(), interval_sec=300 # Every 5 minutes ) for point in trajectory: print(f"{point['timestamp']}: {point['lat']}, {point['lon']}") ``` ```bash cURL theme={null} curl "https://api.rotastellar.com/v1/satellites/ISS/trajectory?start=2026-01-21T00:00:00Z&end=2026-01-22T00:00:00Z&interval_sec=300" \ -H "Authorization: Bearer rs_your_api_key" ``` ## Data Formats ### Position Object ```json theme={null} { "lat": 41.264, "lon": -95.123, "altitude_km": 420.5, "velocity_km_s": 7.66, "timestamp": "2026-01-21T12:00:00Z" } ``` ### Orbit Object ```json theme={null} { "epoch": "2026-01-21T00:00:00Z", "period_min": 92.9, "inclination_deg": 51.64, "raan_deg": 123.45, "arg_perigee_deg": 234.56, "eccentricity": 0.0002, "mean_anomaly_deg": 45.67, "apogee_km": 422, "perigee_km": 418 } ``` ## Rate Limits | Endpoint | Free | Pro | Enterprise | | --------------- | ------ | ------- | ---------- | | Get Satellite | 10/min | 100/min | Custom | | List Satellites | 5/min | 50/min | Custom | | Get Trajectory | 2/min | 20/min | Custom | ## Next Steps Analyze collision risks between objects Detect anomalies in satellite behavior # Webhooks Source: https://docs.rotastellar.com/intelligence/webhooks Real-time alerts for orbital events # Webhooks Receive real-time notifications when orbital events occur, including conjunctions, anomalies, and pattern detections. **Status:** Coming Q1 2026 — [Request early access](https://rotastellar.com/developers) to be notified when available. ## Overview Webhooks deliver events to your application in real-time: * **Conjunction alerts** — New conjunctions or risk level changes * **Pattern detections** — Maneuvers, anomalies, proximity events * **Satellite updates** — Status changes, new TLE data * **System events** — API maintenance, data source updates ## Quick Start ```python Python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient(api_key="rs_...") # Create a webhook endpoint webhook = client.webhooks.create( url="https://your-app.com/rotastellar-events", events=["conjunction.created", "conjunction.risk_changed", "pattern.detected"], secret="your-webhook-secret" ) print(f"Webhook ID: {webhook.id}") print(f"Status: {webhook.status}") ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); const webhook = await client.webhooks.create({ url: 'https://your-app.com/rotastellar-events', events: ['conjunction.created', 'conjunction.risk_changed', 'pattern.detected'], secret: 'your-webhook-secret' }); console.log(`Webhook ID: ${webhook.id}`); ``` ```bash cURL theme={null} curl -X POST https://api.rotastellar.com/v1/webhooks \ -H "Authorization: Bearer rs_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "url": "https://your-app.com/rotastellar-events", "events": ["conjunction.created", "conjunction.risk_changed", "pattern.detected"], "secret": "your-webhook-secret" }' ``` ## Event Types ### Conjunction Events | Event | Description | | -------------------------- | --------------------------------------- | | `conjunction.created` | New conjunction detected | | `conjunction.updated` | Conjunction parameters updated | | `conjunction.risk_changed` | Risk level changed | | `conjunction.resolved` | Conjunction passed or maneuver executed | ### Pattern Events | Event | Description | | ------------------- | ------------------------------ | | `pattern.detected` | New pattern identified | | `pattern.maneuver` | Maneuver specifically detected | | `pattern.anomaly` | Anomaly specifically detected | | `pattern.proximity` | Proximity operation detected | ### Satellite Events | Event | Description | | -------------------------- | ------------------------------ | | `satellite.tle_updated` | New orbital elements available | | `satellite.status_changed` | Operational status changed | | `satellite.decay_warning` | Reentry prediction issued | ## Webhook Payload All webhook payloads follow this structure: ```json theme={null} { "id": "evt_abc123", "type": "conjunction.created", "timestamp": "2026-01-21T12:00:00Z", "data": { "conjunction": { "id": "conj_xyz789", "tca": "2026-01-23T14:32:15Z", "primary": { "id": "12345", "name": "STARLINK-1234" }, "secondary": { "id": "45678", "name": "COSMOS 2251 DEB" }, "miss_km": 0.45, "probability": 2.3e-5, "risk_level": "HIGH" } } } ``` ## Verifying Webhooks Verify webhook signatures to ensure authenticity: ```python Python theme={null} import hmac import hashlib def verify_webhook(payload: bytes, signature: str, secret: str) -> bool: expected = hmac.new( secret.encode(), payload, hashlib.sha256 ).hexdigest() return hmac.compare_digest(f"sha256={expected}", signature) # In your webhook handler @app.post("/rotastellar-events") def handle_webhook(request): signature = request.headers.get("X-RotaStellar-Signature") payload = request.body if not verify_webhook(payload, signature, "your-webhook-secret"): return {"error": "Invalid signature"}, 401 event = json.loads(payload) print(f"Received event: {event['type']}") return {"status": "ok"} ``` ```typescript Node.js theme={null} import crypto from 'crypto'; function verifyWebhook(payload: string, signature: string, secret: string): boolean { const expected = crypto .createHmac('sha256', secret) .update(payload) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(`sha256=${expected}`), Buffer.from(signature) ); } // In your webhook handler app.post('/rotastellar-events', (req, res) => { const signature = req.headers['x-rotastellar-signature']; if (!verifyWebhook(req.rawBody, signature, 'your-webhook-secret')) { return res.status(401).json({ error: 'Invalid signature' }); } const event = req.body; console.log(`Received event: ${event.type}`); res.json({ status: 'ok' }); }); ``` ## Managing Webhooks ### List Webhooks ```python theme={null} webhooks = client.webhooks.list() for wh in webhooks: print(f"{wh.id}: {wh.url}") print(f" Events: {', '.join(wh.events)}") print(f" Status: {wh.status}") ``` ### Update Webhook ```python theme={null} webhook = client.webhooks.update( id="wh_abc123", events=["conjunction.created", "pattern.anomaly"], # Change events enabled=True ) ``` ### Delete Webhook ```python theme={null} client.webhooks.delete("wh_abc123") ``` ### Test Webhook Send a test event to verify your endpoint: ```python theme={null} result = client.webhooks.test("wh_abc123") print(f"Test result: {result.status}") print(f"Response time: {result.response_time_ms}ms") ``` ## Filtering Events Filter events to specific satellites: ```python theme={null} # Only receive events for specific satellites webhook = client.webhooks.create( url="https://your-app.com/events", events=["conjunction.created", "pattern.detected"], filters={ "satellites": ["SAT-001", "SAT-002", "SAT-003"] } ) ``` Filter by risk level: ```python theme={null} # Only receive HIGH and CRITICAL conjunctions webhook = client.webhooks.create( url="https://your-app.com/alerts", events=["conjunction.created", "conjunction.risk_changed"], filters={ "risk_levels": ["HIGH", "CRITICAL"] } ) ``` ## Retry Policy Failed webhook deliveries are retried with exponential backoff: | Attempt | Delay | | ------- | ---------- | | 1 | Immediate | | 2 | 1 minute | | 3 | 5 minutes | | 4 | 30 minutes | | 5 | 2 hours | | 6 | 8 hours | After 6 failed attempts, the webhook is disabled and you'll receive an email notification. ## Best Practices Return a 2xx response within 30 seconds. Process events asynchronously if needed. Events may be delivered more than once. Use the event `id` to deduplicate. Always verify the `X-RotaStellar-Signature` header to ensure authenticity. Webhook endpoints must use HTTPS for security. ## Next Steps Learn about conjunction events Learn about pattern events # Introduction Source: https://docs.rotastellar.com/introduction The API for computing beyond Earth # RotaStellar API The RotaStellar API provides programmatic access to orbital compute infrastructure — from planning tools to runtime execution. **Early Access** — The API is currently in early access. [Request an API key](https://rotastellar.com/developers) to get started. ## Platform Overview The API is organized around four product layers: Feasibility analysis, thermal modeling, latency simulation Satellite tracking, conjunction analysis, pattern detection Constraint-aware execution planning for orbital workloads Orbit-aware scheduling, adaptive inference, resilient compute ## API Status | Product | Status | Availability | | -------------------- | -------------- | ------------ | | Planning Tools | Early Access | Now | | Orbital Intelligence | Early Access | Now | | CAE | Available | Now | | Orbital Runtime | Design Preview | Q2 2026 | ## Quick Example ```python Python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient(api_key="rs_...") # Check feasibility of orbital compute result = client.planning.analyze( workload="ai_inference", compute_tflops=100 ) print(f"Recommended orbit: {result.orbit}") print(f"Estimated cost: ${result.cost_monthly}/mo") ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); // Check feasibility of orbital compute const result = await client.planning.analyze({ workload: 'ai_inference', computeTflops: 100 }); console.log(`Recommended orbit: ${result.orbit}`); console.log(`Estimated cost: $${result.costMonthly}/mo`); ``` ```rust Rust theme={null} use rotastellar::RotaStellar; #[tokio::main] async fn main() -> Result<(), Box> { let client = RotaStellar::new("rs_...")?; let result = client.planning().analyze( "ai_inference", 100.0 // compute_tflops ).await?; println!("Recommended orbit: {}", result.orbit); println!("Estimated cost: ${}/mo", result.cost_monthly); Ok(()) } ``` ```bash cURL theme={null} curl https://api.rotastellar.com/v1/planning/analyze \ -H "Authorization: Bearer rs_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "workload": "ai_inference", "compute_tflops": 100 }' ``` ## Base URL All API requests should be made to: ``` https://api.rotastellar.com/v1 ``` ## Authentication The API uses Bearer token authentication. Include your API key in the `Authorization` header: ```bash theme={null} curl https://api.rotastellar.com/v1/satellites \ -H "Authorization: Bearer rs_your_api_key" ``` Request early access to receive your API credentials. # Feasibility Analysis Source: https://docs.rotastellar.com/planning/feasibility Evaluate orbital compute viability for your workload # Feasibility Analysis Determine whether your workload is suitable for orbital deployment and get recommendations for optimal configuration. **Status:** Early Access — [Request API key](https://rotastellar.com/developers) ## Overview Feasibility analysis evaluates: * **Technical viability** — Can this workload run in space? * **Optimal orbit** — Which orbital regime best fits your requirements? * **Cost estimation** — What will deployment and operation cost? * **Risk assessment** — What are the key challenges? ## Quick Start ```python Python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient(api_key="rs_...") result = client.planning.analyze( workload="ai_inference", compute_tflops=100, storage_tb=10, bandwidth_gbps=1, latency_sla_ms=50 ) print(f"Viable: {result.viable}") print(f"Recommendation: {result.recommendation}") print(f"Orbit: {result.orbit}") print(f"Cost: ${result.cost_monthly}/mo") ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); const result = await client.planning.analyze({ workload: 'ai_inference', computeTflops: 100, storageTb: 10, bandwidthGbps: 1, latencySlams: 50 }); console.log(`Viable: ${result.viable}`); console.log(`Orbit: ${result.orbit}`); ``` ```rust Rust theme={null} use rotastellar::RotaStellar; #[tokio::main] async fn main() -> Result<(), Box> { let client = RotaStellar::new("rs_...")?; let result = client.planning().analyze(AnalyzeRequest { workload: "ai_inference".to_string(), compute_tflops: 100.0, storage_tb: Some(10.0), bandwidth_gbps: Some(1.0), latency_sla_ms: Some(50), }).await?; println!("Viable: {}", result.viable); println!("Orbit: {}", result.orbit); Ok(()) } ``` ```bash cURL theme={null} curl https://api.rotastellar.com/v1/planning/analyze \ -H "Authorization: Bearer rs_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "workload": "ai_inference", "compute_tflops": 100, "storage_tb": 10, "bandwidth_gbps": 1, "latency_sla_ms": 50 }' ``` ## Parameters ### Required Type of workload. Options: * `ai_inference` — ML model inference * `ai_training` — ML model training * `data_processing` — General data processing * `edge_compute` — Edge computing workloads * `storage` — Data storage and retrieval Required compute capacity in TFLOPS (FP16 equivalent) ### Optional Required storage in terabytes Required bandwidth to/from ground in Gbps Maximum acceptable latency in milliseconds Required availability (e.g., 0.999 for 99.9%) Geographic region for ground connectivity. Options: `global`, `north-america`, `europe`, `asia-pacific` ## Response ```json theme={null} { "viable": true, "recommendation": "LEO constellation with 6 satellites provides optimal balance of latency and cost", "orbit": { "type": "LEO", "altitude_km": 550, "inclination_deg": 53, "constellation_size": 6 }, "cost": { "monthly": 125000, "setup": 2500000, "currency": "USD" }, "power": { "required_kw": 15.5, "solar_array_m2": 45, "battery_kwh": 120 }, "latency": { "p50_ms": 25, "p95_ms": 45, "p99_ms": 65 }, "risks": [ { "category": "thermal", "severity": "medium", "description": "Eclipse periods require thermal management" } ], "alternatives": [ { "orbit": "MEO", "tradeoff": "Higher latency (80ms) but 40% lower cost" } ] } ``` ## Workload Types ### AI Inference Best for models that need low-latency inference close to data sources. ```python theme={null} result = client.planning.analyze( workload="ai_inference", compute_tflops=100, latency_sla_ms=50 ) ``` ### AI Training For training models on orbital data (e.g., Earth observation). ```python theme={null} result = client.planning.analyze( workload="ai_training", compute_tflops=500, storage_tb=100 ) ``` ### Data Processing General-purpose compute for data transformation and analysis. ```python theme={null} result = client.planning.analyze( workload="data_processing", compute_tflops=50, bandwidth_gbps=10 ) ``` ## Cost Factors | Factor | Impact | | ------------------ | ---------------------------------------------- | | Orbit altitude | Higher = cheaper launch, more latency | | Constellation size | More satellites = better coverage, higher cost | | Power requirements | Higher power = larger solar arrays | | Bandwidth | More bandwidth = more ground stations | | Redundancy | Higher availability = more satellites | ## Next Steps Model heat management for your configuration Detailed latency modeling for your use case # Latency Simulation Source: https://docs.rotastellar.com/planning/latency Predict network latency based on orbital geometry # Latency Simulation Model end-to-end latency for orbital compute deployments, including propagation delay, ground station handovers, and inter-satellite links. **Status:** Early Access — [Request API key](https://rotastellar.com/developers) ## Overview Latency in orbital systems depends on: * **Propagation delay** — Speed of light distance * **Ground station availability** — Coverage and handover * **Inter-satellite links (ISL)** — Routing through constellation * **Processing delay** — On-board and ground processing ## Quick Start ```python Python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient(api_key="rs_...") latency = client.planning.latency( orbit="LEO-550", ground_stations=["us-west", "us-east", "europe", "asia"], include_isl=True ) print(f"P50 latency: {latency.p50_ms}ms") print(f"P95 latency: {latency.p95_ms}ms") print(f"P99 latency: {latency.p99_ms}ms") print(f"Coverage: {latency.coverage_percent}%") ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); const latency = await client.planning.latency({ orbit: 'LEO-550', groundStations: ['us-west', 'us-east', 'europe', 'asia'], includeIsl: true }); console.log(`P50: ${latency.p50Ms}ms`); console.log(`P99: ${latency.p99Ms}ms`); ``` ```bash cURL theme={null} curl https://api.rotastellar.com/v1/planning/latency \ -H "Authorization: Bearer rs_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "orbit": "LEO-550", "ground_stations": ["us-west", "us-east", "europe", "asia"], "include_isl": true }' ``` ## Parameters Orbit specification (e.g., `LEO-550`, `MEO-8000`, `GEO`) List of ground station regions: * `us-west`, `us-east`, `us-central` * `europe`, `europe-north` * `asia`, `asia-south` * `australia` * `south-america` Include inter-satellite link routing Number of satellites (affects ISL routing options) Specific user location for point-to-point latency: ```json theme={null} {"lat": 37.7749, "lon": -122.4194} ``` ## Response ```json theme={null} { "p50_ms": 25, "p95_ms": 48, "p99_ms": 72, "min_ms": 12, "max_ms": 145, "coverage_percent": 98.5, "breakdown": { "propagation_ms": 8, "processing_ms": 5, "handover_ms": 12, "isl_hops_avg": 1.3 }, "ground_station_stats": [ { "station": "us-west", "contact_percent": 35, "avg_elevation_deg": 42 }, { "station": "europe", "contact_percent": 28, "avg_elevation_deg": 38 } ], "gaps": [ { "start_min": 23, "duration_min": 4, "region": "pacific" } ] } ``` ## Latency by Orbit Type | Orbit | Altitude | One-way Propagation | RTT (typical) | | ----- | --------- | ------------------- | ------------- | | LEO | 550 km | 1.8 ms | 20-50 ms | | MEO | 8,000 km | 27 ms | 80-150 ms | | GEO | 35,786 km | 120 ms | 480-600 ms | ## Latency Optimization ### With Inter-Satellite Links ISLs can reduce latency by routing traffic through space instead of bouncing to ground: ```python theme={null} # Without ISL - must wait for ground station contact latency_no_isl = client.planning.latency( orbit="LEO-550", ground_stations=["us-west"], include_isl=False ) # With ISL - can route through constellation latency_with_isl = client.planning.latency( orbit="LEO-550", ground_stations=["us-west"], include_isl=True, constellation_size=100 ) print(f"Without ISL: P99 = {latency_no_isl.p99_ms}ms") print(f"With ISL: P99 = {latency_with_isl.p99_ms}ms") ``` ### Geographic Coverage Analysis Analyze latency from specific user locations: ```python theme={null} # Latency from San Francisco to orbital compute latency = client.planning.latency( orbit="LEO-550", ground_stations=["us-west", "us-east"], user_location={"lat": 37.7749, "lon": -122.4194} ) print(f"SF to orbit P50: {latency.p50_ms}ms") ``` ## Coverage Gaps LEO satellites don't provide continuous coverage. The API identifies gaps: ```python theme={null} latency = client.planning.latency( orbit="LEO-550", ground_stations=["us-west"] ) for gap in latency.gaps: print(f"Gap at {gap.start_min}min, duration {gap.duration_min}min") ``` To eliminate gaps, add more ground stations or enable ISL: ```python theme={null} # Add more ground stations latency = client.planning.latency( orbit="LEO-550", ground_stations=["us-west", "us-east", "europe", "asia"], include_isl=True ) print(f"Coverage: {latency.coverage_percent}%") # ~99%+ ``` ## Next Steps Plan power for your orbital deployment Complete feasibility assessment # Planning Tools Overview Source: https://docs.rotastellar.com/planning/overview Answer 'should we?' before 'how?' # Planning Tools **Status:** Early Access — [Request API key](https://rotastellar.com/developers) Planning Tools help you evaluate the feasibility of orbital compute deployments before committing resources. Answer critical questions about thermal management, latency, power, and cost. ## Capabilities Evaluate whether your workload is suitable for orbital compute Model heat rejection and thermal cycles in orbit Predict network latency based on orbital geometry Plan power generation and consumption across orbit ## Quick Start ```python Python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient(api_key="rs_...") # Comprehensive feasibility analysis result = client.planning.analyze( workload="ai_inference", compute_tflops=100, storage_tb=10, bandwidth_gbps=1 ) print(f"Recommendation: {result.recommendation}") print(f"Optimal orbit: {result.orbit}") print(f"Monthly cost: ${result.cost_monthly}") print(f"Power required: {result.power_kw} kW") ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); const result = await client.planning.analyze({ workload: 'ai_inference', computeTflops: 100, storageTb: 10, bandwidthGbps: 1 }); console.log(`Recommendation: ${result.recommendation}`); console.log(`Optimal orbit: ${result.orbit}`); console.log(`Monthly cost: $${result.costMonthly}`); ``` ```bash cURL theme={null} curl https://api.rotastellar.com/v1/planning/analyze \ -H "Authorization: Bearer rs_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "workload": "ai_inference", "compute_tflops": 100, "storage_tb": 10, "bandwidth_gbps": 1 }' ``` ## Workflow A typical planning workflow: ```mermaid theme={null} flowchart LR A[Define Requirements] --> B[Feasibility Analysis] B --> C{Viable?} C -->|Yes| D[Thermal Simulation] C -->|No| E[Adjust Requirements] E --> B D --> F[Latency Modeling] F --> G[Power Budgeting] G --> H[Deployment Plan] ``` ## Orbit Options | Orbit Type | Altitude | Period | Use Cases | | ---------- | --------------- | ---------- | -------------------------------- | | LEO | 300-600 km | 90-100 min | Low latency, Earth observation | | MEO | 2,000-35,000 km | 2-24 hr | Navigation, regional coverage | | GEO | 35,786 km | 24 hr | Fixed coverage, broadcasting | | HEO | Variable | Variable | Polar coverage, specific regions | ## Next Steps Start with a comprehensive feasibility check View the full API specification # Power Budgeting Source: https://docs.rotastellar.com/planning/power Plan power generation and consumption across orbit # Power Budgeting Model power generation, storage, and consumption for orbital compute systems across the full orbital cycle. **Status:** Early Access — [Request API key](https://rotastellar.com/developers) ## Overview Power in orbit is fundamentally different from Earth: * **Solar only** — Primary power source is photovoltaic * **Eclipse periods** — No generation during Earth shadow * **Battery cycling** — Must store enough for eclipse * **Degradation** — Solar cells degrade over mission life ## Quick Start ```python Python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient(api_key="rs_...") power = client.planning.power( orbit="LEO-550", compute_load_w=500, duty_cycle=0.8, mission_life_years=5 ) print(f"Solar array: {power.solar_array_m2} m2") print(f"Battery: {power.battery_kwh} kWh") print(f"Available during eclipse: {power.eclipse_power_w}W") print(f"EOL margin: {power.eol_margin_percent}%") ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); const power = await client.planning.power({ orbit: 'LEO-550', computeLoadW: 500, dutyCycle: 0.8, missionLifeYears: 5 }); console.log(`Solar array: ${power.solarArrayM2} m2`); console.log(`Battery: ${power.batteryKwh} kWh`); ``` ```bash cURL theme={null} curl https://api.rotastellar.com/v1/planning/power \ -H "Authorization: Bearer rs_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "orbit": "LEO-550", "compute_load_w": 500, "duty_cycle": 0.8, "mission_life_years": 5 }' ``` ## Parameters Orbit specification (e.g., `LEO-550`, `GEO`) Peak compute power consumption in watts Fraction of time compute is active (0-1) Mission duration for degradation calculations Non-compute power (thermal, comms, ADCS) Maximum battery depth of discharge (0-1) ## Response ```json theme={null} { "solar_array": { "area_m2": 3.2, "power_bol_w": 960, "power_eol_w": 768, "degradation_percent_per_year": 2.5 }, "battery": { "capacity_kwh": 0.85, "cycles_per_day": 15.5, "eol_capacity_percent": 80 }, "power_profile": { "sunlit_available_w": 680, "eclipse_available_w": 420, "average_available_w": 580 }, "margins": { "bol_margin_percent": 25, "eol_margin_percent": 12 }, "recommendations": [ "Consider 10% larger array for operational margin", "Battery supports 5-year mission with 80% EOL capacity" ], "orbit_profile": [ {"phase": "sunlit", "duration_min": 57, "power_w": 680}, {"phase": "eclipse", "duration_min": 35, "power_w": 420} ] } ``` ## Power Budget Breakdown ### Typical LEO Power Budget | Subsystem | Power (W) | Notes | | -------------- | --------- | ---------------------- | | Compute (peak) | 500 | GPU/TPU workloads | | Compute (idle) | 50 | Standby mode | | Thermal | 30-100 | Heaters during eclipse | | Communications | 20-50 | Varies with data rate | | ADCS | 10-20 | Attitude control | | Housekeeping | 20-30 | Avionics, sensors | ### Power Modes ```python theme={null} # Model different operating modes power = client.planning.power( orbit="LEO-550", modes=[ {"name": "full_compute", "power_w": 500, "duration_percent": 60}, {"name": "reduced", "power_w": 200, "duration_percent": 30}, {"name": "idle", "power_w": 50, "duration_percent": 10} ], mission_life_years=5 ) ``` ## Eclipse Operations During eclipse, power is limited to battery capacity: ```python theme={null} power = client.planning.power( orbit="LEO-550", compute_load_w=500, eclipse_strategy="reduced" # or "full", "suspend" ) # Check eclipse power availability if power.eclipse_available_w < 500: print(f"Must reduce to {power.eclipse_available_w}W during eclipse") ``` ### Eclipse Strategies | Strategy | Description | Use Case | | --------- | ---------------------------------- | ---------------------------- | | `full` | Maintain full power | Large battery, short eclipse | | `reduced` | Reduce compute during eclipse | Balanced approach | | `suspend` | Suspend compute, housekeeping only | Minimal battery | ## Degradation Over Mission Life Solar arrays and batteries degrade over time: ```python theme={null} # Compare BOL vs EOL power power = client.planning.power( orbit="LEO-550", compute_load_w=500, mission_life_years=7 ) print(f"Year 1 available: {power.solar_array.power_bol_w}W") print(f"Year 7 available: {power.solar_array.power_eol_w}W") print(f"Degradation: {power.solar_array.degradation_percent_per_year}%/year") ``` ## Design Recommendations Size for end-of-life (EOL) power needs plus 10-20% margin. Account for degradation: \~2.5%/year in LEO due to radiation. Size for eclipse duration + margin. Limit depth of discharge to 30-40% for long cycle life. Design for multiple power modes. Ability to reduce compute load extends operational flexibility. ## Next Steps Ensure thermal design matches power budget Complete system feasibility check # Thermal Simulation Source: https://docs.rotastellar.com/planning/thermal Model heat rejection and thermal cycles in orbit # Thermal Simulation Simulate thermal behavior of compute hardware in orbital environments, including eclipse cycles and varying solar flux. **Status:** Early Access — [Request API key](https://rotastellar.com/developers) ## Overview Space presents unique thermal challenges: * **No convection** — Heat can only be rejected via radiation * **Eclipse cycles** — Periodic loss of solar heating * **Solar flux variation** — Changes with orbit and season * **Internal heat** — Compute generates significant waste heat ## Quick Start ```python Python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient(api_key="rs_...") thermal = client.planning.thermal( orbit="LEO-550", power_dissipation_w=500, radiator_area_m2=2.0, internal_mass_kg=100 ) print(f"Steady state: {thermal.steady_state_c}C") print(f"Max (sunlit): {thermal.max_temp_c}C") print(f"Min (eclipse): {thermal.min_temp_c}C") print(f"Thermal margin: {thermal.margin_c}C") ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); const thermal = await client.planning.thermal({ orbit: 'LEO-550', powerDissipationW: 500, radiatorAreaM2: 2.0, internalMassKg: 100 }); console.log(`Steady state: ${thermal.steadyStateC}C`); console.log(`Max temp: ${thermal.maxTempC}C`); ``` ```bash cURL theme={null} curl https://api.rotastellar.com/v1/planning/thermal \ -H "Authorization: Bearer rs_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "orbit": "LEO-550", "power_dissipation_w": 500, "radiator_area_m2": 2.0, "internal_mass_kg": 100 }' ``` ## Parameters Orbit specification. Options: * `LEO-400` to `LEO-600` — Low Earth Orbit at specified altitude * `MEO-2000` to `MEO-20000` — Medium Earth Orbit * `GEO` — Geostationary orbit * Custom: `{"altitude_km": 550, "inclination_deg": 53}` Internal heat generation in watts Radiator surface area in square meters Internal thermal mass in kg (affects transient response) Radiator emissivity (0-1) Solar absorptivity (0-1) ## Response ```json theme={null} { "steady_state_c": 35.2, "max_temp_c": 52.8, "min_temp_c": 12.4, "margin_c": 17.2, "eclipse_duration_min": 35.5, "sunlit_duration_min": 57.3, "cooling_rate_c_per_min": 0.65, "heating_rate_c_per_min": 0.48, "thermal_profile": [ {"time_min": 0, "temp_c": 35.2, "phase": "sunlit"}, {"time_min": 57, "temp_c": 52.8, "phase": "eclipse_start"}, {"time_min": 92, "temp_c": 12.4, "phase": "eclipse_end"} ], "recommendations": [ "Consider active thermal control for tighter bounds", "Heaters recommended for eclipse survival" ] } ``` ## Thermal Profiles ### LEO Thermal Cycle ``` Temperature (C) 60 | ____ | / \ 40 | / \____ | / \ 20 |/ \ +-----------------> Time Sunlit Eclipse ``` ### Operating Limits | Component | Min (C) | Max (C) | | --------- | ------- | ------- | | GPU/TPU | 0 | 85 | | CPU | -20 | 100 | | Memory | -40 | 85 | | Storage | -40 | 70 | | Battery | 0 | 45 | ## Advanced: Time-Series Simulation Get detailed thermal behavior over multiple orbits: ```python theme={null} thermal = client.planning.thermal( orbit="LEO-550", power_dissipation_w=500, radiator_area_m2=2.0, simulation={ "duration_orbits": 10, "time_step_sec": 60 } ) # Plot thermal profile for point in thermal.time_series: print(f"{point.time_min}: {point.temp_c}C ({point.phase})") ``` ## Design Considerations Larger radiators = lower steady-state temperature but more mass and cost. Rule of thumb: 0.1-0.2 m² per 100W dissipation for LEO. Ensure minimum temperature stays above component limits. May require heaters or thermal mass. Consider worst-case solar flux (perihelion + beta angle = 0). Add 10-15% margin to maximum temperature. ## Next Steps Model network latency for your orbit Plan power generation and storage # Quickstart Source: https://docs.rotastellar.com/quickstart Get up and running in 5 minutes # Quickstart This guide will get you from zero to your first API call in under 5 minutes. ## 1. Get an API Key Sign up to receive your API credentials. ## 2. Install the SDK ```bash Python theme={null} pip install rotastellar ``` ```bash Node.js theme={null} npm install @rotastellar/sdk ``` ```bash Rust theme={null} cargo add rotastellar ``` ## 3. Make Your First Request ```python Python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient(api_key="rs_your_api_key") # Get ISS position iss = client.get_satellite("25544") # ISS NORAD ID print(f"ISS Location: {iss.position.latitude}, {iss.position.longitude}") print(f"Altitude: {iss.position.altitude_km} km") ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_your_api_key' }); // Get ISS position const iss = await client.getSatellite('25544'); // ISS NORAD ID console.log(`ISS Location: ${iss.position?.latitude}, ${iss.position?.longitude}`); console.log(`Altitude: ${iss.position?.altitudeKm} km`); ``` ```rust Rust theme={null} use rotastellar::types::{Position, Orbit}; fn main() -> Result<(), Box> { // Rust SDK provides types only (HTTP client coming soon) // Use Python or Node.js SDK for full API access // Create a position type for ISS-like coordinates let pos = Position::new(41.264, -95.123, 420.5)?; println!("Location: {}, {}", pos.latitude, pos.longitude); println!("Altitude: {} km", pos.altitude_km); Ok(()) } ``` ```bash cURL theme={null} curl https://api.rotastellar.com/v1/satellites/ISS \ -H "Authorization: Bearer rs_your_api_key" ``` ## 4. Explore the API Now that you're set up, explore what you can build: Real-time positions for 10,000+ active satellites Collision probability and avoidance recommendations Feasibility analysis for space-based workloads Heat rejection modeling for orbital hardware ## Rate Limits | Tier | Requests/minute | Requests/day | | ---------- | --------------- | ------------ | | Free | 10 | 1,000 | | Pro | 100 | 100,000 | | Enterprise | Custom | Custom | ## Need Help? * [API Reference](/api-reference) — Full endpoint documentation * [GitHub Issues](https://github.com/rotastellar/rotastellar-python/issues) — Bug reports and feature requests * [Contact Us](https://rotastellar.com/contact/) — Enterprise support # Adaptive Runtime Source: https://docs.rotastellar.com/runtime/adaptive Energy and thermal-aware inference execution # Adaptive Runtime **Coming Q2 2026** — This is a design preview. [Request early access](https://rotastellar.com/developers) to be notified when available. ## Overview The Adaptive Runtime dynamically adjusts inference execution to stay within energy and thermal constraints. Instead of failing when resources are limited, it gracefully degrades while maintaining output quality bounds. ## Key Capabilities * **Dynamic precision** — Switch between FP16/INT8/INT4 based on power * **Layer skipping** — Skip non-critical layers when energy-constrained * **Context adaptation** — Reduce context window under pressure * **Thermal throttling** — Automatic frequency scaling near thermal limits * **Quality guarantees** — Bounded degradation with quality metrics ## How It Works Your inference request arrives with energy/thermal constraints specified. **Energy Monitor** tracks battery level, solar input, and power draw. **Thermal Monitor** tracks CPU/GPU temperatures and cooling capacity. Based on current constraints and monitor data, the controller makes decisions: * Precision selection (FP16/INT8/INT4) * Layer skip decisions * Context window sizing * Batch size adjustment Executes the model with the selected adaptations applied. Returns the response along with a detailed report of what adaptations were applied. ## API Preview ### Submit with Energy Constraints ```python Python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient(api_key="rs_...") result = client.runtime.generate( model="llama-70b", prompt="Summarize this document...", constraints={ "energy_budget_wh": 0.5, # Max energy for this request "thermal_limit_c": 75, # Throttle above this temp "quality": "best_effort" # or "exact" } ) print(f"Response: {result.text}") print(f"Energy used: {result.energy_wh} Wh") print(f"Adaptations applied: {result.adaptations}") ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); const result = await client.runtime.generate({ model: 'llama-70b', prompt: 'Summarize this document...', constraints: { energyBudgetWh: 0.5, thermalLimitC: 75, quality: 'best_effort' } }); console.log(`Response: ${result.text}`); console.log(`Adaptations: ${JSON.stringify(result.adaptations)}`); ``` ```bash cURL theme={null} curl -X POST https://api.rotastellar.com/v1/runtime/generate \ -H "Authorization: Bearer rs_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "model": "llama-70b", "prompt": "Summarize this document...", "constraints": { "energy_budget_wh": 0.5, "thermal_limit_c": 75, "quality": "best_effort" } }' ``` ### Adaptation Report Every response includes what adaptations were applied: ```json theme={null} { "text": "The document discusses...", "energy_wh": 0.42, "latency_ms": 156, "adaptations": { "precision": "int8", // Reduced from FP16 "layers_skipped": 4, // Out of 80 total "context_used": 4096, // Reduced from 8192 "batch_size": 1 // No batching }, "quality_metrics": { "estimated_perplexity_delta": 0.02, "confidence": 0.94 } } ``` ### Configure Adaptation Policies Set global adaptation preferences: ```python theme={null} client.runtime.configure( adaptive={ # Precision bounds "precision_floor": "int8", # Never go below INT8 "precision_ceiling": "fp16", # Start at FP16 # Layer skipping "layer_skip_max": 0.2, # Skip up to 20% of layers "skip_strategy": "importance", # or "uniform", "early", "late" # Context management "context_min": 2048, # Minimum context window "context_strategy": "truncate", # or "summarize", "slide" # Thermal management "thermal_threshold_c": 70, # Start throttling "thermal_critical_c": 85, # Hard limit # Quality guarantees "quality_floor": 0.9 # Minimum acceptable quality score } ) ``` ## Adaptation Strategies ### Precision Scaling | Precision | Relative Energy | Relative Quality | | --------- | --------------- | ---------------- | | FP16 | 1.0x | 1.0 | | INT8 | 0.5x | 0.98 | | INT4 | 0.3x | 0.92 | ```python theme={null} # Force specific precision result = client.runtime.generate( model="llama-70b", prompt="...", constraints={ "precision": "int8" # Fixed precision } ) ``` ### Layer Skipping Skip less important layers to save energy: ```python theme={null} # Allow aggressive layer skipping result = client.runtime.generate( model="llama-70b", prompt="...", constraints={ "layer_skip_max": 0.3, # Up to 30% "skip_strategy": "importance" # Skip least important } ) print(f"Layers skipped: {result.adaptations['layers_skipped']}") ``` ### Context Adaptation Reduce context window under constraints: ```python theme={null} result = client.runtime.generate( model="llama-70b", prompt="...", context=long_document, # 32k tokens constraints={ "context_max": 8192, # Limit context "context_strategy": "summarize" # Summarize overflow } ) ``` ## Quality Modes ### Best Effort Maximize quality within constraints, may degrade: ```python theme={null} result = client.runtime.generate( model="llama-70b", prompt="...", constraints={ "energy_budget_wh": 0.3, "quality": "best_effort" } ) # Will adapt to fit energy budget ``` ### Exact Fail if constraints can't be met at full quality: ```python theme={null} result = client.runtime.generate( model="llama-70b", prompt="...", constraints={ "energy_budget_wh": 0.3, "quality": "exact" } ) # Will fail if 0.3 Wh isn't enough for full precision ``` ### Bounded Degrade only within specified bounds: ```python theme={null} result = client.runtime.generate( model="llama-70b", prompt="...", constraints={ "energy_budget_wh": 0.3, "quality": "bounded", "quality_floor": 0.95 # Must maintain 95% quality } ) # Will adapt but not below 95% quality ``` ## Monitoring Track adaptation patterns over time: ```python theme={null} # Get adaptation statistics stats = client.runtime.adaptation_stats( period="24h" ) print(f"Total requests: {stats.total_requests}") print(f"Adapted requests: {stats.adapted_requests}") print(f"Average energy savings: {stats.avg_energy_savings_percent}%") print(f"Average quality maintained: {stats.avg_quality_maintained}") ``` ## Next Steps Learn about fault tolerance Learn about workload placement # Orbital Runtime Overview Source: https://docs.rotastellar.com/runtime/overview Execution primitives for computing beyond Earth # Orbital Runtime **Coming Q2 2026** — The Orbital Runtime is currently in development. This documentation is a design preview. [Request early access](https://rotastellar.com/developers) to be notified when it's available. ## Overview The Orbital Runtime provides execution primitives designed for the unique constraints of space: Workload orchestration across Earth and orbital nodes Energy and thermal-aware inference execution Fault-tolerant ML for radiation environments ## Why a New Runtime? Standard cloud runtimes assume: | Assumption | Reality in Space | | ------------------- | ----------------------------- | | Always-on network | Intermittent connectivity | | Stable power | Variable solar/eclipse cycles | | Predictable latency | Orbital geometry dependent | | Reliable hardware | Radiation-induced faults | The Orbital Runtime is built from first principles for these constraints. ## Architecture Preview Your application connects to the RotaStellar Orbital Runtime, which orchestrates workloads across Earth and orbital infrastructure. Routes jobs to optimal nodes based on latency, energy, and availability Adjusts precision, layer execution, and context based on constraints Radiation-tolerant execution with checksums and redundancy **Infrastructure Layer:** | Node Type | Location | Characteristics | | --------- | ---------------- | -------------------------------------------------------- | | Earth DC | Terrestrial | High bandwidth, stable power, lowest latency to users | | LEO Node | 400-600 km orbit | Solar powered, 25ms latency, intermittent ground contact | | GEO Node | 35,786 km orbit | Continuous coverage, 250ms latency, limited power | ## API Preview This API is subject to change before release. ### Submit a Job ```python Python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient(api_key="rs_...") # Submit inference job with constraints job = client.runtime.submit( model="llama-70b", prompt="Analyze this satellite telemetry...", constraints={ "latency_sla_ms": 200, "energy_budget_wh": 0.5, "quality": "best_effort" # or "exact" } ) # Job is routed to optimal node (Earth or orbit) print(f"Job ID: {job.id}") print(f"Routed to: {job.node}") # e.g., "orbital-leo-1" print(f"Estimated completion: {job.eta}") # Get result result = job.result(timeout=30) print(f"Response: {result.text}") print(f"Adaptations: {result.adaptations}") print(f"Energy used: {result.energy_wh} Wh") ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); const job = await client.runtime.submit({ model: 'llama-70b', prompt: 'Analyze this satellite telemetry...', constraints: { latencySlams: 200, energyBudgetWh: 0.5, quality: 'best_effort' } }); console.log(`Job ID: ${job.id}`); console.log(`Routed to: ${job.node}`); const result = await job.result({ timeout: 30000 }); console.log(`Response: ${result.text}`); ``` ```rust Rust theme={null} use rotastellar::RotaStellar; #[tokio::main] async fn main() -> Result<(), Box> { let client = RotaStellar::new("rs_...")?; let job = client.runtime().submit(JobRequest { model: "llama-70b".to_string(), prompt: "Analyze this satellite telemetry...".to_string(), constraints: Constraints { latency_sla_ms: Some(200), energy_budget_wh: Some(0.5), quality: Quality::BestEffort, }, }).await?; println!("Job ID: {}", job.id); println!("Routed to: {}", job.node); let result = job.result(30).await?; println!("Response: {}", result.text); Ok(()) } ``` ```bash cURL theme={null} curl -X POST https://api.rotastellar.com/v1/runtime/jobs \ -H "Authorization: Bearer rs_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "model": "llama-70b", "prompt": "Analyze this satellite telemetry...", "constraints": { "latency_sla_ms": 200, "energy_budget_wh": 0.5, "quality": "best_effort" } }' ``` ### Configure Adaptive Behavior ```python theme={null} # Set global adaptation preferences client.runtime.configure( adaptive={ "precision_floor": "int8", # Don't go below INT8 "layer_skip_max": 0.2, # Skip up to 20% of layers "context_min": 2048, # Minimum context window "thermal_threshold_c": 75 # Throttle above 75C }, resilience={ "checksum_layers": True, "redundant_attention": True, "max_reexecute": 3 } ) ``` ## Timeline | Milestone | Target | | ------------------------- | ------- | | Design preview (this doc) | Now | | Simulator SDK | Q2 2026 | | Beta with early partners | Q4 2026 | | General availability | 2027 | ## Get Notified Be the first to know when Orbital Runtime is available. # Resilient Compute Source: https://docs.rotastellar.com/runtime/resilient Fault-tolerant ML for radiation environments # Resilient Compute **Coming Q2 2026** — This is a design preview. [Request early access](https://rotastellar.com/developers) to be notified when available. ## Overview Resilient Compute provides fault-tolerant ML execution for radiation environments. Space radiation causes Single Event Upsets (SEUs) that flip bits in memory and computation. Instead of ignoring this reality, we build detection and recovery directly into the inference pipeline. ## The Problem In LEO, a typical compute system experiences: * **\~10-100 SEUs per day** in unshielded memory * **Silent data corruption** in weights and activations * **Accumulated errors** that compound through layers * **Unpredictable failures** in traditional ML pipelines ## Our Approach Verify integrity of model weights and input data before processing. Execute each layer with optional redundancy for critical computations (e.g., attention). Compare checksums and redundant outputs to detect bit flips or corruption. When errors are detected, the system either: * **Bounded Error Propagation** - Contains errors to prevent cascading through layers * **Selective Re-execution** - Re-runs only the affected computation Final validation ensures output integrity before returning results. ## Key Capabilities * **Error detection** — Checksums and redundancy catch corruption * **Bounded propagation** — Prevent errors from cascading * **Selective re-execution** — Only re-run affected computation * **Graceful degradation** — Maintain service despite faults * **Transparency** — Report what happened and confidence level ## API Preview ### Enable Resilience Features ```python Python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient(api_key="rs_...") result = client.runtime.generate( model="llama-70b", prompt="Critical analysis of...", resilience={ "checksum_layers": True, # Verify layer outputs "redundant_attention": True, # Duplicate attention computation "max_reexecute": 3, # Max re-executions per layer "error_threshold": 0.01 # Max acceptable error rate } ) print(f"Response: {result.text}") print(f"Errors detected: {result.resilience.errors_detected}") print(f"Errors corrected: {result.resilience.errors_corrected}") print(f"Confidence: {result.resilience.confidence}") ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); const result = await client.runtime.generate({ model: 'llama-70b', prompt: 'Critical analysis of...', resilience: { checksumLayers: true, redundantAttention: true, maxReexecute: 3, errorThreshold: 0.01 } }); console.log(`Confidence: ${result.resilience.confidence}`); ``` ```bash cURL theme={null} curl -X POST https://api.rotastellar.com/v1/runtime/generate \ -H "Authorization: Bearer rs_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "model": "llama-70b", "prompt": "Critical analysis of...", "resilience": { "checksum_layers": true, "redundant_attention": true, "max_reexecute": 3, "error_threshold": 0.01 } }' ``` ### Resilience Report Every response includes a resilience report: ```json theme={null} { "text": "The analysis shows...", "resilience": { "errors_detected": 2, "errors_corrected": 2, "reexecutions": 1, "confidence": 0.998, "layers_validated": 80, "checksum_failures": 0, "details": [ { "layer": 42, "type": "activation_corruption", "action": "reexecuted", "resolved": true }, { "layer": 67, "type": "weight_bitflip", "action": "corrected_ecc", "resolved": true } ] } } ``` ### Configure Resilience Globally ```python theme={null} client.runtime.configure( resilience={ # Detection methods "checksum_layers": True, # Checksum layer outputs "redundant_attention": True, # Duplicate attention "weight_verification": "periodic", # or "continuous", "none" # Recovery behavior "max_reexecute": 3, # Max retries per layer "reexecute_strategy": "selective", # or "full_layer" "fallback_precision": "fp32", # Higher precision for re-exec # Error bounds "error_threshold": 0.01, # Max error rate before fail "confidence_floor": 0.95 # Min acceptable confidence } ) ``` ## Detection Methods ### Layer Checksums Verify outputs match expected ranges: ```python theme={null} result = client.runtime.generate( model="llama-70b", prompt="...", resilience={ "checksum_layers": True, "checksum_granularity": "per_head" # or "per_layer" } ) ``` ### Redundant Computation Run critical computations twice: ```python theme={null} result = client.runtime.generate( model="llama-70b", prompt="...", resilience={ "redundant_attention": True, # Duplicate attention "redundant_ffn": False # Don't duplicate FFN (too expensive) } ) ``` ### ECC Memory Use error-correcting memory when available: ```python theme={null} result = client.runtime.generate( model="llama-70b", prompt="...", resilience={ "require_ecc": True # Fail if ECC not available } ) ``` ## Recovery Strategies ### Selective Re-execution Only re-run affected computation: ```python theme={null} # If layer 42 has a checksum failure, only re-run layer 42 result = client.runtime.generate( model="llama-70b", prompt="...", resilience={ "reexecute_strategy": "selective", "max_reexecute": 3 } ) ``` ### Full Restart Re-run entire inference if errors exceed threshold: ```python theme={null} result = client.runtime.generate( model="llama-70b", prompt="...", resilience={ "reexecute_strategy": "full", "error_threshold": 0.05 # Restart if >5% layers affected } ) ``` ## Resilience Modes | Mode | Overhead | Protection | Use Case | | ---------- | -------- | --------------------------- | --------------- | | `minimal` | 5% | Basic detection | Low-criticality | | `standard` | 15% | Full detection + correction | Default | | `high` | 30% | Redundant execution | Safety-critical | | `paranoid` | 100% | Triple redundancy | Life-critical | ```python theme={null} result = client.runtime.generate( model="llama-70b", prompt="...", resilience={"mode": "high"} ) ``` ## Monitoring Radiation Effects Track SEU rates and their impact: ```python theme={null} # Get radiation statistics stats = client.runtime.radiation_stats( node="orbital-leo-1", period="24h" ) print(f"SEUs detected: {stats.seus_detected}") print(f"SEUs corrected: {stats.seus_corrected}") print(f"Inference impact: {stats.inference_impact_percent}%") print(f"Current flux: {stats.current_flux}") ``` ## Best Practices Use `standard` mode for most workloads. Reserve `high` and `paranoid` for safety-critical applications. Track confidence over time. Degrading confidence may indicate increasing radiation or hardware issues. During solar events, radiation spikes. Consider pausing non-critical workloads during high-flux periods. ## Next Steps Learn about energy-aware inference Learn about workload placement # Orbit Scheduler Source: https://docs.rotastellar.com/runtime/scheduler Workload orchestration across Earth and orbital nodes # Orbit Scheduler **Coming Q2 2026** — This is a design preview. [Request early access](https://rotastellar.com/developers) to be notified when available. ## Overview The Orbit Scheduler orchestrates workloads across heterogeneous compute nodes spanning Earth datacenters and orbital infrastructure. It understands orbital mechanics, energy availability, and network topology to make optimal placement decisions. ## Key Capabilities * **Orbit-aware scheduling** — Accounts for orbital position, eclipse periods, ground contacts * **Energy optimization** — Routes work based on power availability * **Latency-aware routing** — Minimizes round-trip time based on geometry * **Fault tolerance** — Automatic failover between nodes * **Workload splitting** — Distribute work across Earth + orbit ## Architecture The Orbit Scheduler uses three models to make placement decisions: Decides which node should handle each workload based on constraints and current state Predicts satellite positions, ground contacts, and eclipse periods Tracks power availability, battery state, and solar input across all nodes **Available Nodes:** | Node | Location | Characteristics | | ------------------ | ------------ | ------------------------------------------ | | Earth DC (us-west) | Terrestrial | Always available, lowest latency to US | | LEO-1 | 550 km orbit | Solar-powered, intermittent ground contact | | LEO-2 | 550 km orbit | Solar-powered, different orbital plane | ## API Preview ### Submit Job with Placement Hints ```python Python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient(api_key="rs_...") job = client.runtime.submit( model="llama-70b", prompt="...", placement={ "prefer": "orbital", # Prefer orbital nodes "fallback": "earth", # Fall back to Earth if needed "region_affinity": "europe", # Prefer nodes with Europe visibility "max_hops": 2 # Max ISL hops }, constraints={ "latency_sla_ms": 100, "energy_budget_wh": 0.5 } ) print(f"Placed on: {job.node}") print(f"Reason: {job.placement_reason}") ``` ```typescript Node.js theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); const job = await client.runtime.submit({ model: 'llama-70b', prompt: '...', placement: { prefer: 'orbital', fallback: 'earth', regionAffinity: 'europe', maxHops: 2 }, constraints: { latencySlams: 100, energyBudgetWh: 0.5 } }); ``` ```bash cURL theme={null} curl -X POST https://api.rotastellar.com/v1/runtime/jobs \ -H "Authorization: Bearer rs_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "model": "llama-70b", "prompt": "...", "placement": { "prefer": "orbital", "fallback": "earth", "region_affinity": "europe", "max_hops": 2 }, "constraints": { "latency_sla_ms": 100, "energy_budget_wh": 0.5 } }' ``` ### Query Node Status ```python theme={null} # Get current node availability nodes = client.runtime.nodes() for node in nodes: print(f"{node.id}: {node.type}") print(f" Location: {node.location}") print(f" Status: {node.status}") print(f" Available power: {node.available_power_w}W") print(f" Queue depth: {node.queue_depth}") if node.type == "orbital": print(f" In eclipse: {node.in_eclipse}") print(f" Ground contact: {node.has_ground_contact}") ``` ### Schedule Future Work Schedule jobs to run at optimal times: ```python theme={null} # Schedule for optimal conditions scheduled_job = client.runtime.schedule( model="llama-70b", prompt="...", schedule={ "window_start": "2026-01-22T00:00:00Z", "window_end": "2026-01-22T12:00:00Z", "optimize_for": "energy" # or "latency", "cost" } ) print(f"Scheduled for: {scheduled_job.scheduled_time}") print(f"Expected node: {scheduled_job.expected_node}") print(f"Energy savings: {scheduled_job.energy_savings_percent}%") ``` ## Placement Strategies ### Orbital-First Prefer orbital nodes, fall back to Earth: ```python theme={null} job = client.runtime.submit( model="...", prompt="...", placement={"prefer": "orbital", "fallback": "earth"} ) ``` ### Earth-First Prefer Earth, use orbital for overflow: ```python theme={null} job = client.runtime.submit( model="...", prompt="...", placement={"prefer": "earth", "fallback": "orbital"} ) ``` ### Latency-Optimized Route to minimize latency to specific region: ```python theme={null} job = client.runtime.submit( model="...", prompt="...", placement={ "optimize_for": "latency", "user_location": {"lat": 51.5, "lon": -0.1} # London } ) ``` ### Energy-Optimized Route to nodes with best energy availability: ```python theme={null} job = client.runtime.submit( model="...", prompt="...", placement={"optimize_for": "energy"} ) ``` ## Scheduling Factors The scheduler considers: | Factor | Weight | Description | | ------------------- | ------ | --------------------------- | | Energy availability | High | Current and predicted power | | Latency | High | Network path to user | | Queue depth | Medium | Current load on node | | Thermal headroom | Medium | Temperature margin | | Eclipse status | Medium | Upcoming power constraints | | Ground contact | Low | Communication availability | ## Node Types | Type | Location | Characteristics | | ------- | ------------------ | ------------------------------------------- | | `earth` | Terrestrial DC | Unlimited power, stable network | | `leo` | Low Earth Orbit | Variable power, intermittent ground contact | | `meo` | Medium Earth Orbit | Stable power, higher latency | | `geo` | Geostationary | Continuous visibility, 240ms+ latency | ## Next Steps Learn about energy-aware inference Learn about fault tolerance # Node.js SDK Source: https://docs.rotastellar.com/sdks/node Official Node.js/TypeScript SDK for the RotaStellar API # Node.js SDK The official Node.js SDK for RotaStellar with full TypeScript support, providing access to Planning, Intelligence, and Runtime APIs. **Status:** Early Access — [Request API key](https://rotastellar.com/developers) ## Installation ```bash theme={null} npm install @rotastellar/sdk ``` Or with other package managers: ```bash theme={null} # Yarn yarn add @rotastellar/sdk # pnpm pnpm add @rotastellar/sdk # Bun bun add @rotastellar/sdk ``` ### Requirements * Node.js 18+ or Bun * TypeScript 4.7+ (optional, but recommended) ## Quick Start ```typescript theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; // Initialize client const client = new RotaStellarClient({ apiKey: 'rs_your_api_key' }); // Or use environment variable // export ROTASTELLAR_API_KEY=rs_your_api_key const client = new RotaStellarClient(); // Track a satellite const iss = await client.getSatellite('25544'); console.log(`ISS: ${iss.position?.latitude}, ${iss.position?.longitude}`); ``` ## Client Configuration ```typescript theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...', baseUrl: 'https://api.rotastellar.com/v1', // Default timeout: 30000, // Request timeout in ms maxRetries: 3, // Retry failed requests debug: false // Enable debug logging }); ``` ## Intelligence API ### Get Satellite ```typescript theme={null} // Get satellite by NORAD ID const sat = await client.getSatellite('25544'); // ISS console.log(`Name: ${sat.name}`); console.log(`Position: ${sat.position?.latitude}, ${sat.position?.longitude}`); console.log(`Altitude: ${sat.position?.altitudeKm} km`); // Get position only const pos = await client.getSatellitePosition('25544'); console.log(`Position: ${pos.latitude}, ${pos.longitude} at ${pos.altitudeKm} km`); ``` ### List Satellites ```typescript theme={null} // List satellites with filters const satellites = await client.listSatellites({ constellation: 'Starlink', limit: 100 }); for (const sat of satellites) { console.log(`${sat.name}: ${sat.noradId}`); } // Filter by operator const spacexSats = await client.listSatellites({ operator: 'SpaceX', limit: 50 }); ``` ### Conjunction Analysis ```typescript theme={null} import { TimeRange } from '@rotastellar/sdk'; // Get conjunction risks for a satellite const conjunctions = await client.listConjunctions({ satelliteId: '25544', thresholdKm: 5.0, limit: 10 }); for (const conj of conjunctions) { console.log(`TCA: ${conj.tca}`); console.log(`Miss distance: ${conj.miss_distance_km.toFixed(3)} km`); console.log(`Probability: ${conj.collision_probability.toExponential(2)}`); } ``` ### Pattern Detection ```typescript theme={null} // Detect maneuvers and anomalies const patterns = await client.listPatterns({ satelliteId: '44832', // COSMOS-2542 lookbackDays: 30 }); for (const pattern of patterns) { console.log(`${pattern.type}: ${pattern.description}`); console.log(`Confidence: ${(pattern.confidence * 100).toFixed(1)}%`); } ``` ### Trajectory Prediction ```typescript theme={null} // Get predicted trajectory const trajectory = await client.getTrajectory({ satelliteId: '25544', start: new Date(), end: new Date(Date.now() + 2 * 60 * 60 * 1000), // +2 hours intervalSec: 60 }); for (const point of trajectory) { console.log(`${point.timestamp}: ${point.latitude.toFixed(2)}, ${point.longitude.toFixed(2)}`); } ``` ## Planning API ### Feasibility Analysis ```typescript theme={null} // Analyze if orbital compute is viable for your workload const result = await client.analyzeFeasibility({ workloadType: 'inference', computeTflops: 10, dataGb: 1.5, latencyRequirementMs: 100, orbitAltitudeKm: 550 }); console.log(`Feasible: ${result.feasible}`); console.log(`Recommendation: ${result.recommendation}`); ``` ### Thermal Simulation ```typescript theme={null} // Model heat rejection in orbit const thermal = await client.simulateThermal({ powerWatts: 500, orbitAltitudeKm: 550, radiatorAreaM2: 2.0, durationHours: 24 }); console.log(`Max temp: ${thermal.max_temperature_c}°C`); console.log(`Min temp: ${thermal.min_temperature_c}°C`); ``` ### Latency Simulation ```typescript theme={null} import { Position } from '@rotastellar/sdk'; // Model end-to-end latency const source = new Position(37.7749, -122.4194); // San Francisco const dest = new Position(51.5074, -0.1278); // London const latency = await client.simulateLatency({ source, destination: dest, orbitAltitudeKm: 550, relayCount: 2 }); console.log(`Total latency: ${latency.total_latency_ms?.toFixed(1)} ms`); ``` ## Runtime API (Coming Q2 2026) ```typescript theme={null} // Submit inference job to orbital compute const job = await client.submitJob({ model: 'llama-70b', prompt: '...', constraints: { latencySlams: 200, energyBudgetWh: 0.5 } }); // Get result const result = await client.getJobResult(job.id, { timeout: 30000 }); console.log(result.text); ``` ## Pagination Handle large result sets with the `PaginatedResponse` class: ```typescript theme={null} import { PaginatedResponse } from '@rotastellar/sdk'; // Manual pagination let page = await client.listSatellites({ constellation: 'Starlink', limit: 100 }); console.log(`Page has ${page.items.length} items, hasMore=${page.hasMore}`); for (const sat of page.items) { console.log(sat.name); } if (page.hasMore) { page = await page.nextPage(); } // Automatic pagination with async iteration for await (const sat of client.listSatellites({ constellation: 'Starlink' })) { console.log(sat.name); } ``` ### PaginatedResponse Properties | Property | Type | Description | | --------- | --------------------- | -------------------------- | | `items` | `T[]` | Current page of items | | `hasMore` | `boolean` | Whether more pages exist | | `total` | `number \| undefined` | Total count (if available) | | `limit` | `number` | Page size | | `offset` | `number` | Current offset | ## TypeScript Support Full TypeScript definitions are included: ```typescript theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; import type { Satellite, Position, Orbit, Conjunction, Pattern } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); const sat: Satellite = await client.getSatellite('25544'); const pos: Position = sat.position!; const orbit: Orbit = sat.orbit!; // Full autocomplete and type checking console.log(pos.latitude); // number console.log(pos.longitude); // number console.log(pos.altitudeKm); // number console.log(orbit.periodMin); // number ``` ## Error Handling ```typescript theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; import { AuthenticationError, RateLimitError, NotFoundError, ValidationError, APIError } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...' }); try { const sat = await client.getSatellite('INVALID-ID'); } catch (error) { if (error instanceof NotFoundError) { console.log('Satellite not found'); } else if (error instanceof RateLimitError) { console.log(`Rate limited. Retry after ${error.retryAfter}s`); } else if (error instanceof AuthenticationError) { console.log('Invalid API key'); } else if (error instanceof ValidationError) { console.log(`Invalid request: ${error.message}`); } else if (error instanceof APIError) { console.log(`API error: ${error.message}`); } } ``` ## Request Cancellation Cancel long-running requests: ```typescript theme={null} const controller = new AbortController(); // Cancel after 5 seconds setTimeout(() => controller.abort(), 5000); try { const result = await client.analyzeFeasibility({ workloadType: 'inference', computeTflops: 100 }, { signal: controller.signal }); } catch (error) { if (error.name === 'AbortError') { console.log('Request cancelled'); } } ``` ## Distributed Compute API (Coming Q1 2026) The `@rotastellar/distributed` package enables Earth-space AI coordination: ```bash theme={null} npm install @rotastellar/distributed ``` ### Federated Learning ```typescript theme={null} import { FederatedClient, CompressionConfig, CompressionMethod } from '@rotastellar/distributed'; // Configure gradient compression (100x reduction) const compression: CompressionConfig = { method: CompressionMethod.TOP_K_QUANTIZED, kRatio: 0.01, quantizationBits: 8, errorFeedback: true }; // Initialize client on orbital node const client = new FederatedClient({ nodeId: 'orbital-3', nodeType: 'orbital', compression }); // Compute and compress gradients for transmission const gradients = client.computeGradients(modelParams, localData); const compressed = client.compress(gradients); ``` See the [Distributed Compute documentation](/distributed/overview) for full API reference. ## Logging Enable debug logging: ```typescript theme={null} import { RotaStellarClient } from '@rotastellar/sdk'; const client = new RotaStellarClient({ apiKey: 'rs_...', debug: true // Logs all requests/responses }); // Or use custom logger const client = new RotaStellarClient({ apiKey: 'rs_...', logger: { debug: console.debug, info: console.info, warn: console.warn, error: console.error } }); ``` ## Source Code View source, report issues, and contribute. Package page and version history. # Python SDK Source: https://docs.rotastellar.com/sdks/python Official Python SDK for the RotaStellar API # Python SDK The official Python SDK for RotaStellar, providing full access to Planning, Intelligence, and Runtime APIs. **Status:** Early Access — [Request API key](https://rotastellar.com/developers) ## Installation ```bash theme={null} pip install rotastellar ``` ### Requirements * Python 3.9+ * httpx (for HTTP requests) ### Optional Dependencies ```bash theme={null} # For async support pip install rotastellar[async] # For data analysis utilities pip install rotastellar[pandas] # All optional dependencies pip install rotastellar[all] ``` ## Quick Start ```python theme={null} from rotastellar import RotaStellarClient # Initialize client client = RotaStellarClient(api_key="rs_your_api_key") # Or use environment variable # export ROTASTELLAR_API_KEY=rs_your_api_key client = RotaStellarClient() # Track a satellite iss = client.get_satellite("25544") print(f"ISS: {iss.position.latitude}, {iss.position.longitude}") ``` ## Client Configuration ```python theme={null} from rotastellar import RotaStellarClient client = RotaStellarClient( api_key="rs_...", base_url="https://api.rotastellar.com/v1", # Default timeout=30.0, # Request timeout in seconds max_retries=3, # Retry failed requests debug=False # Enable debug logging ) ``` ## Intelligence API ### Get Satellite ```python theme={null} # Get satellite by NORAD ID sat = client.get_satellite("25544") # ISS print(f"Name: {sat.name}") print(f"Position: {sat.position.latitude}, {sat.position.longitude}") print(f"Altitude: {sat.position.altitude_km} km") # Get position only pos = client.get_satellite_position("25544") print(f"Position: {pos.latitude}, {pos.longitude} at {pos.altitude_km} km") ``` ### List Satellites ```python theme={null} # List satellites with filters satellites = client.list_satellites( constellation="Starlink", limit=100 ) for sat in satellites: print(f"{sat.name}: {sat.norad_id}") # Filter by operator spacex_sats = client.list_satellites(operator="SpaceX", limit=50) ``` ### Conjunction Analysis ```python theme={null} from rotastellar.types import TimeRange # Get conjunction risks for a satellite conjunctions = client.list_conjunctions( satellite_id="25544", threshold_km=5.0, limit=10 ) for conj in conjunctions: print(f"TCA: {conj['tca']}") print(f"Miss distance: {conj['miss_distance_km']:.3f} km") print(f"Probability: {conj['collision_probability']:.2e}") ``` ### Pattern Detection ```python theme={null} # Detect maneuvers and anomalies patterns = client.list_patterns( satellite_id="44832", # COSMOS-2542 lookback_days=30 ) for pattern in patterns: print(f"{pattern['type']}: {pattern['description']}") print(f"Confidence: {pattern['confidence']:.1%}") ``` ### Trajectory Prediction ```python theme={null} from datetime import datetime, timedelta # Get predicted trajectory (start/end are ISO 8601 strings) trajectory = client.get_trajectory( satellite_id="25544", start=datetime.utcnow().isoformat(), end=(datetime.utcnow() + timedelta(hours=2)).isoformat(), interval_sec=60 ) for point in trajectory: print(f"{point['timestamp']}: {point['lat']:.2f}, {point['lon']:.2f}") ``` ## Planning API ### Feasibility Analysis ```python theme={null} # Analyze if orbital compute is viable for your workload result = client.analyze_feasibility( workload_type="inference", compute_tflops=10, data_gb=1.5, latency_requirement_ms=100, orbit_altitude_km=550 ) print(f"Feasible: {result['feasible']}") print(f"Recommendation: {result['recommendation']}") ``` ### Thermal Simulation ```python theme={null} # Model heat rejection in orbit thermal = client.simulate_thermal( power_watts=500, orbit_altitude_km=550, radiator_area_m2=2.0, duration_hours=24 ) print(f"Max temp: {thermal['max_temperature_c']}°C") print(f"Min temp: {thermal['min_temperature_c']}°C") ``` ### Latency Simulation ```python theme={null} from rotastellar.types import Position # Model end-to-end latency source = Position(latitude=37.7749, longitude=-122.4194) # San Francisco dest = Position(latitude=51.5074, longitude=-0.1278) # London latency = client.simulate_latency( source=source, destination=dest, orbit_altitude_km=550, relay_count=2 ) print(f"Total latency: {latency['total_latency_ms']:.1f} ms") ``` ## Runtime API (Coming Q2 2026) ```python theme={null} # Submit inference job to orbital compute job = client.submit_job( model="llama-70b", prompt="...", constraints={ "latency_sla_ms": 200, "energy_budget_wh": 0.5 } ) # Get result result = client.get_job_result(job['id'], timeout=30) print(result['text']) ``` ## Async Client For high-performance async applications: ```python theme={null} import asyncio from rotastellar import AsyncRotaStellarClient async def main(): client = AsyncRotaStellarClient(api_key="rs_...") # Async satellite tracking iss = await client.get_satellite("25544") print(f"ISS: {iss.position.latitude}, {iss.position.longitude}") # Concurrent requests satellites = ["25544", "43013", "20580"] tasks = [client.get_satellite(s) for s in satellites] results = await asyncio.gather(*tasks) for sat in results: print(f"{sat.name}: {sat.position.altitude_km} km") asyncio.run(main()) ``` ## Pagination Handle large result sets with the `PaginatedResponse` class: ```python theme={null} from rotastellar import PaginatedResponse # Manual pagination page = client.list_satellites(constellation="Starlink", limit=100) print(f"Page has {len(page.items)} items, has_more={page.has_more}") for sat in page.items: print(sat.name) if page.has_more: next_page = page.next_page() # Automatic iteration (auto-fetches next pages) for sat in client.list_satellites(constellation="Starlink"): print(sat.name) # Async auto-pagination async for sat in async_client.list_satellites(constellation="Starlink"): print(sat.name) ``` ### PaginatedResponse Properties | Property | Type | Description | | ---------- | ------------- | -------------------------- | | `items` | `List[T]` | Current page of items | | `has_more` | `bool` | Whether more pages exist | | `total` | `int \| None` | Total count (if available) | | `limit` | `int` | Page size | | `offset` | `int` | Current offset | ## Distributed Compute API (Coming Q1 2026) The `rotastellar-distributed` package enables Earth-space AI coordination: ```bash theme={null} pip install rotastellar-distributed ``` ### Federated Learning ```python theme={null} from rotastellar_distributed import FederatedClient, CompressionConfig, CompressionMethod # Configure gradient compression (100x reduction) compression = CompressionConfig( method=CompressionMethod.TOP_K_QUANTIZED, k_ratio=0.01, quantization_bits=8, error_feedback=True ) # Initialize client on orbital node client = FederatedClient( node_id="orbital-3", compression=compression, node_type="orbital" ) # Compute and compress gradients for transmission gradients = client.compute_gradients(model_params, local_data) compressed = client.compress(gradients) ``` See the [Distributed Compute documentation](/distributed/overview) for full API reference. ## Error Handling ```python theme={null} from rotastellar import RotaStellarClient from rotastellar.errors import ( AuthenticationError, RateLimitError, NotFoundError, ValidationError, APIError ) client = RotaStellarClient(api_key="rs_...") try: sat = client.get_satellite("INVALID-ID") except NotFoundError: print("Satellite not found") except RateLimitError as e: print(f"Rate limited. Retry after {e.retry_after}s") except AuthenticationError: print("Invalid API key") except ValidationError as e: print(f"Invalid request: {e.message}") except APIError as e: print(f"API error: {e.message}") ``` ## Type Hints The SDK includes full type annotations for IDE support: ```python theme={null} from rotastellar import RotaStellarClient from rotastellar.types import Position, Orbit, Satellite client = RotaStellarClient(api_key="rs_...") sat: Satellite = client.get_satellite("25544") pos: Position = sat.position orbit: Orbit = sat.orbit # IDE will provide autocomplete for all fields print(pos.latitude) # float print(pos.longitude) # float print(pos.altitude_km) # float print(orbit.orbital_period_minutes) # float ``` ## Logging Enable debug logging: ```python theme={null} import logging logging.basicConfig(level=logging.DEBUG) # Or configure specific logger logger = logging.getLogger("rotastellar") logger.setLevel(logging.DEBUG) ``` ## Source Code View source, report issues, and contribute. Package page and version history. # Rust SDK Source: https://docs.rotastellar.com/sdks/rust Official Rust SDK for the RotaStellar API # Rust SDK The official Rust SDK for RotaStellar, providing type-safe primitives for orbital compute and space intelligence applications. **Status:** Early Access — [Request API key](https://rotastellar.com/developers) The Rust SDK currently provides **types only**. The HTTP client is coming in a future release. For full API access, use the [Python SDK](/sdks/python) or [Node.js SDK](/sdks/node). ## Installation Add to your `Cargo.toml`: ```toml theme={null} [dependencies] rotastellar = "0.1" ``` Or use cargo: ```bash theme={null} cargo add rotastellar ``` ## Quick Start ```rust theme={null} use rotastellar::types::{Position, Orbit, Satellite}; fn main() -> Result<(), Box> { // Create a position (e.g., Kennedy Space Center) let pos = Position::new(28.5729, -80.6490, 0.0)?; println!("Position: {}, {}", pos.latitude, pos.longitude); // Create an ISS-like orbit let orbit = Orbit::new(6778.0, 0.0001, 51.6, 100.0, 90.0, 0.0)?; println!("Orbital period: {:.1} minutes", orbit.orbital_period_minutes()); println!("Apogee: {:.1} km, Perigee: {:.1} km", orbit.apogee_km(), orbit.perigee_km()); Ok(()) } ``` ## Available Types ### Position Geographic position with altitude: ```rust theme={null} use rotastellar::types::Position; // Create with validation let pos = Position::new(28.5729, -80.6490, 408.0)?; // Access fields println!("Latitude: {}", pos.latitude); println!("Longitude: {}", pos.longitude); println!("Altitude: {} km", pos.altitude_km); ``` | Field | Type | Description | | ------------- | ----- | ---------------------------------- | | `latitude` | `f64` | Latitude in degrees (-90 to 90) | | `longitude` | `f64` | Longitude in degrees (-180 to 180) | | `altitude_km` | `f64` | Altitude above sea level in km | ### Orbit Keplerian orbital elements: ```rust theme={null} use rotastellar::types::Orbit; // Create an orbit (ISS-like) let orbit = Orbit::new( 6778.0, // semi_major_axis_km 0.0001, // eccentricity 51.6, // inclination_deg 100.0, // raan_deg 90.0, // arg_periapsis_deg 0.0 // true_anomaly_deg )?; // Computed properties println!("Period: {:.1} minutes", orbit.orbital_period_minutes()); println!("Apogee: {:.1} km", orbit.apogee_km()); println!("Perigee: {:.1} km", orbit.perigee_km()); println!("Mean motion: {:.2} rev/day", orbit.mean_motion()); ``` | Field | Type | Description | | -------------------- | ----- | --------------------------------- | | `semi_major_axis_km` | `f64` | Semi-major axis in km | | `eccentricity` | `f64` | Orbital eccentricity (0-1) | | `inclination_deg` | `f64` | Inclination in degrees (0-180) | | `raan_deg` | `f64` | Right ascension of ascending node | | `arg_periapsis_deg` | `f64` | Argument of periapsis | | `true_anomaly_deg` | `f64` | True anomaly | ### Satellite Satellite information with optional orbit and position: ```rust theme={null} use rotastellar::types::{Satellite, Position, Orbit}; let sat = Satellite::new("sat_123", 25544, "ISS") .with_operator("NASA/Roscosmos") .with_constellation("Space Station") .with_position(Position::new(28.5729, -80.6490, 408.0)?) .with_orbit(orbit); println!("Name: {}", sat.name); println!("NORAD ID: {}", sat.norad_id); if let Some(pos) = &sat.position { println!("At: {}, {}", pos.latitude, pos.longitude); } ``` ### TimeRange Time range for queries: ```rust theme={null} use rotastellar::types::TimeRange; // Create a 24-hour time range starting now let range = TimeRange::next_hours(24.0); println!("Start: {}", range.start); println!("End: {}", range.end); ``` ## Configuration The SDK provides configuration utilities for when the HTTP client is available: ```rust theme={null} use rotastellar::{Config, ConfigBuilder}; let config = Config::default(); println!("Base URL: {}", config.base_url); println!("Timeout: {:?}", config.timeout); ``` ## Authentication Utilities Validate and mask API keys: ```rust theme={null} use rotastellar::{validate_api_key, mask_api_key, Environment}; // Validate an API key match validate_api_key(Some("rs_live_abc123")) { Ok(env) => println!("Valid key for {:?} environment", env), Err(e) => println!("Invalid: {}", e), } // Mask a key for logging let masked = mask_api_key("rs_live_abc123def456"); println!("Masked: {}", masked); // rs_live_abc... ``` ## Error Handling ```rust theme={null} use rotastellar::error::{RotaStellarError, ValidationError}; use rotastellar::types::Position; fn create_position() -> Result { // This will fail validation (latitude > 90) let pos = Position::new(91.0, 0.0, 0.0)?; Ok(pos) } match create_position() { Ok(pos) => println!("Created: {:?}", pos), Err(RotaStellarError::Validation(e)) => { println!("Validation error on '{}': {}", e.field, e.message); } Err(e) => println!("Error: {}", e), } ``` ### Error Types | Error | Description | | ---------------------------------- | --------------------------- | | `RotaStellarError::Validation` | Input validation failed | | `RotaStellarError::Authentication` | API key issues | | `RotaStellarError::Api` | API returned an error | | `RotaStellarError::Network` | Network connectivity issues | ## Constants ```rust theme={null} use rotastellar::{EARTH_RADIUS_KM, EARTH_MU}; println!("Earth radius: {} km", EARTH_RADIUS_KM); // 6378.137 println!("Earth GM: {} km³/s²", EARTH_MU); // 398600.4418 ``` ## Serde Support All types implement `Serialize` and `Deserialize`: ```rust theme={null} use rotastellar::types::Position; use serde_json; let pos = Position::new(28.5729, -80.6490, 408.0)?; // Serialize let json = serde_json::to_string(&pos)?; println!("{}", json); // Deserialize let parsed: Position = serde_json::from_str(&json)?; ``` ## Coming Soon The following features are planned for future releases: * **HTTP Client** — Full API client with async support * **Blocking Client** — Synchronous API for non-async contexts * **Streaming** — Real-time satellite position updates * **TLE Parsing** — Two-line element set parsing and propagation ## Source Code View source, report issues, and contribute. Package page and version history. # Orbital Sim Source: https://docs.rotastellar.com/sim/overview Stateless orbital computation for satellite digital twins The **Orbital Sim** service provides real-time satellite position computation, trajectory propagation, eclipse detection, and ground station pass prediction. It powers the RotaStellar agent constellation and planned asset live tracking. ## Base URL ``` https://sim.rotastellar.com ``` ## Capabilities | Capability | Endpoint | Description | | ----------------------- | --------------------------------- | ---------------------------------------------- | | Orbital state | `POST /v1/state` | Position, velocity, eclipse at any timestamp | | Batch state | `POST /v1/state/batch` | Up to 100 satellites in one call | | Trajectory | `POST /v1/propagate` | Full orbit path over up to 48 hours | | Ground passes | `POST /v1/passes` | AOS/LOS windows with elevation data | | Orbit templates | `GET /v1/templates` | Predefined orbit profiles (LEO, SSO, MEO, GEO) | | Constellation templates | `GET /v1/constellation-templates` | Walker Star, Polar Ring patterns | | Ground stations | `GET /v1/ground-stations` | 12-station global network | | Sessions | `POST /v1/sessions` | Stateful constellation simulation | | Tick simulation | `POST /v1/sessions/:id/tick` | Advance time with subsystem updates | | Fault injection | `POST /v1/sessions/:id/fault` | Inject hardware/environment faults | ## Quick Example ```bash theme={null} curl -X POST https://sim.rotastellar.com/v1/state \ -H "Content-Type: application/json" \ -d '{ "elements": { "altitude_km": 550, "inclination_deg": 53 } }' ``` ```json theme={null} { "lat": 42.15, "lon": -73.82, "altitude_km": 550.3, "velocity_km_s": 7.59, "in_eclipse": false, "orbit_fraction": 0.234, "timestamp": "2026-03-08T12:00:00Z" } ``` ## Orbital Elements All computation endpoints accept an `elements` object. You must provide either `mean_motion` (revolutions/day) or `altitude_km`. | Field | Type | Required | Default | Description | | ------------------ | ------ | -------- | ------- | --------------------------------------------- | | `altitude_km` | number | \* | — | Orbit altitude in km | | `mean_motion` | number | \* | — | Revolutions per day (alternative to altitude) | | `inclination_deg` | number | yes | — | Orbital inclination in degrees | | `eccentricity` | number | no | 0.0001 | Orbit eccentricity | | `raan_deg` | number | no | 0 | Right ascension of ascending node | | `arg_perigee_deg` | number | no | 90 | Argument of perigee | | `mean_anomaly_deg` | number | no | 0 | Mean anomaly at epoch | | `epoch` | string | no | now | ISO 8601 timestamp of elements | | `bstar` | number | no | 0.00003 | Atmospheric drag term | Either `altitude_km` or `mean_motion` is required, but not both. ## Access The Sim service uses CORS-based access control. Allowed origins include `rotastellar.com`, `console.rotastellar.com`, `runtime.rotastellar.com`, and `localhost:3000`. No API key is required. ## Simulation Sessions (v1.1.0) CAE v1.1.0 adds **stateful simulation sessions** for constellation-level testing with subsystem tracking, ISL link quality modeling, and fault injection. See [Simulation Sessions](/sim/sessions) for full documentation. ## API Reference See the full API reference for each endpoint: * [Service Index](/api-reference/sim/service-index) * [Get State](/api-reference/sim/get-state) * [Batch State](/api-reference/sim/batch-state) * [Propagate](/api-reference/sim/propagate) * [Ground Passes](/api-reference/sim/passes) * [Templates](/api-reference/sim/templates) * [Create Session](/api-reference/sim/create-session) * [Get Session State](/api-reference/sim/get-session) * [Tick Session](/api-reference/sim/tick-session) * [Inject Fault](/api-reference/sim/inject-fault) # Simulation Sessions Source: https://docs.rotastellar.com/sim/sessions Stateful satellite constellation simulation with subsystem tracking and fault injection # Simulation Sessions **Version:** 1.1.0 Simulation Sessions extend the Orbital Sim with **stateful, multi-satellite simulation**. Unlike the stateless propagation endpoints, sessions persist constellation state in KV and let you advance time step-by-step, track subsystem health, model inter-satellite link quality, and inject faults. Sessions are designed for integration testing of constellation workloads. They power the agent executor's simulated satellite mode and the CAE constellation planner's test harness. ## Base URL ``` https://sim.rotastellar.com ``` ## Concepts ### Session Lifecycle A session represents a constellation of up to 50 satellites. On creation, each satellite is initialized with orbital elements and default subsystem state. You advance the simulation by calling the **tick** endpoint, which propagates orbits, updates subsystems, checks for natural faults, and recalculates ISL links. Sessions are stored in the `SIM_STATE` KV binding with a **1-hour TTL**. If a session is not ticked within one hour, it is automatically evicted. ### Subsystem State Every satellite in a session tracks five subsystems: | Subsystem | Unit | Initial Value | Model | | ------------- | ---- | -------------------------- | ----------------------------------------------------------------------- | | `battery` | % | 100 | Charge in sunlight, discharge in eclipse. Rate depends on compute load. | | `solar_power` | W | 100 (sunlit) / 0 (eclipse) | Binary based on eclipse state. | | `temperature` | C | 20 | Rises under compute load, radiative cooling in eclipse. | | `memory` | MB | 0 (of 512) | Accumulates with data generation, freed on downlink. | | `cpu` | % | 0 | Set by active workload. Idle satellites report 0%. | ### ISL Link Quality Inter-satellite links (ISLs) are modeled between all satellite pairs within range: | Parameter | Value | | ------------------- | -------------------------------------------------- | | Max range | 5,000 km | | Distance factor | `1 - (distance / 5000) * 0.6` | | Eclipse penalty | `0.9` (applied when either endpoint is in eclipse) | | Effective bandwidth | `100 Mbps * quality` | A link quality of 0 means the satellites are out of range. Quality degrades linearly with distance and is further penalized during eclipse due to thermal effects on transponders. ### Natural Fault Detection Each tick evaluates three natural fault conditions: | Fault | Condition | Probability | | ------------------- | ---------------------------------------------------------- | --------------------- | | SAA radiation upset | Satellite passes through the South Atlantic Anomaly region | 2% per tick in region | | Thermal exceedance | Temperature exceeds 50C | Deterministic | | Power critical | Battery drops below 5% | Deterministic | When a natural fault triggers, it is included in the tick response as a `faults` array entry. ## Endpoints ### Create Session ``` POST /v1/sessions ``` Creates a new simulation session with the specified satellites. **Request body:** | Field | Type | Required | Description | | ----------------------- | ------ | -------- | ---------------------------------------------- | | `satellites` | array | yes | Array of satellite definitions (max 50) | | `satellites[].id` | string | yes | Unique satellite identifier within the session | | `satellites[].elements` | object | yes | Orbital elements (same schema as `/v1/state`) | ```bash theme={null} curl -X POST https://sim.rotastellar.com/v1/sessions \ -H "Content-Type: application/json" \ -d '{ "satellites": [ { "id": "sat-1", "elements": { "altitude_km": 550, "inclination_deg": 53, "raan_deg": 0, "mean_anomaly_deg": 0 } }, { "id": "sat-2", "elements": { "altitude_km": 550, "inclination_deg": 53, "raan_deg": 0, "mean_anomaly_deg": 120 } }, { "id": "sat-3", "elements": { "altitude_km": 550, "inclination_deg": 53, "raan_deg": 0, "mean_anomaly_deg": 240 } } ] }' ``` **Response (201):** ```json theme={null} { "session_id": "ses-a1b2c3d4", "satellite_count": 3, "created_at": "2026-03-10T12:00:00Z", "ttl_seconds": 3600 } ``` Sessions are limited to 50 satellites. Requests exceeding this limit return a 400 error. ### Get Session State ``` GET /v1/sessions/:id ``` Returns the full constellation state including all satellite positions, subsystems, and active ISL links. **Response (200):** ```json theme={null} { "session_id": "ses-a1b2c3d4", "tick": 5, "sim_time": "2026-03-10T12:25:00Z", "satellites": [ { "id": "sat-1", "position": { "lat": 42.15, "lon": -73.82, "altitude_km": 550.3 }, "in_eclipse": false, "subsystems": { "battery": 94.2, "solar_power": 100, "temperature": 22.5, "memory": 45.0, "cpu": 30 } } ], "isl_links": [ { "from": "sat-1", "to": "sat-2", "distance_km": 1823.4, "quality": 0.78, "bandwidth_mbps": 78.0, "eclipse_penalty_applied": false } ] } ``` ### Tick (Advance Simulation) ``` POST /v1/sessions/:id/tick ``` Advances the simulation by one time step. Each tick performs the following in order: 1. Propagate all satellite orbits forward 2. Detect eclipse transitions (sunlit/shadow) 3. Update subsystem state (battery, thermal, solar) 4. Check natural fault conditions 5. Recalculate all ISL links **Request body:** | Field | Type | Required | Default | Description | | ------------ | ------ | -------- | ------- | ----------------------------- | | `duration_s` | number | no | 300 | Time step duration in seconds | ```bash theme={null} curl -X POST https://sim.rotastellar.com/v1/sessions/ses-a1b2c3d4/tick \ -H "Content-Type: application/json" \ -d '{ "duration_s": 300 }' ``` **Response (200):** ```json theme={null} { "session_id": "ses-a1b2c3d4", "tick": 6, "sim_time": "2026-03-10T12:30:00Z", "duration_s": 300, "satellites": [ ... ], "isl_links": [ ... ], "eclipse_transitions": [ { "satellite_id": "sat-2", "transition": "entered_eclipse", "sim_time": "2026-03-10T12:27:14Z" } ], "faults": [] } ``` The `eclipse_transitions` array only contains satellites whose eclipse state changed during this tick. An empty array means no transitions occurred. ### Inject Fault ``` POST /v1/sessions/:id/fault ``` Injects a fault into a specific satellite. The fault takes effect immediately and is reflected in the session state. **Request body:** | Field | Type | Required | Description | | -------------- | ------ | -------- | ---------------------------- | | `satellite_id` | string | yes | Target satellite | | `fault_type` | string | yes | One of the fault types below | **Fault types and effects:** | Fault Type | Immediate Effect | | -------------------- | --------------------------------------------------- | | `power_loss` | Battery set to 0%, solar power disabled | | `thermal_exceedance` | Temperature set to 85C | | `radiation_upset` | CPU reset to 0%, memory corrupted (set to 0) | | `comms_failure` | All ISL links to/from this satellite removed | | `isl_degradation` | All ISL links to/from this satellite quality halved | ```bash theme={null} curl -X POST https://sim.rotastellar.com/v1/sessions/ses-a1b2c3d4/fault \ -H "Content-Type: application/json" \ -d '{ "satellite_id": "sat-2", "fault_type": "power_loss" }' ``` **Response (200):** ```json theme={null} { "session_id": "ses-a1b2c3d4", "satellite_id": "sat-2", "fault_type": "power_loss", "applied_at_tick": 6, "effects": { "battery": 0, "solar_power": 0 } } ``` Fault injection is irreversible within a session. To restore a satellite, create a new session. ## Storage Sessions are stored in the `SIM_STATE` KV binding. Each session is a single JSON document keyed by `session:{session_id}`. The 1-hour TTL ensures stale sessions are automatically cleaned up. | KV Binding | Key Pattern | TTL | | ----------- | ---------------------- | -------------- | | `SIM_STATE` | `session:{session_id}` | 3600s (1 hour) | ## Related Stateless propagation, eclipse detection, and pass prediction Full API reference for all Sim endpoints