Skip to content

Topology

Topology API

Retrieve the current network topology for visualization and analysis.

GET /api/v1/topology/

Get a snapshot of the network topology including all nodes and edges.

Request

GET /api/v1/topology/
Authorization: Bearer <token>

Example Request

Terminal window
curl -X GET "https://api.constellation-io.com/api/v1/topology/" \
-H "Authorization: Bearer $TOKEN"

Response

{
"timestamp": "2026-01-16T20:00:00Z",
"nodes": [
{
"id": "sat-001",
"type": "satellite",
"lat": 45.5,
"lon": -122.68,
"altitude_km": 550.0,
"utilization": 0.75,
"health": "nominal",
"capacity_gbps": 100.0,
"queue_depth_gb": 25.5,
"label": "Starlink-1234"
},
{
"id": "gs-001",
"type": "ground_station",
"lat": 37.7749,
"lon": -122.4194,
"altitude_km": 0.0,
"utilization": 0.45,
"health": "nominal",
"capacity_gbps": 500.0,
"queue_depth_gb": 10.2,
"label": "San Francisco GS"
}
],
"edges": [
{
"source": "sat-001",
"target": "gs-001",
"capacity_gbps": 50.0,
"latency_ms": 25.3,
"utilization": 0.65,
"is_active": true,
"reliability": 0.99,
"packet_loss_rate": 0.001
}
]
}

Node Schema

NameTypeDescription
idstringUnique node identifier
typestringsatellite, ground_station, or data_center
latnumberLatitude in degrees
lonnumberLongitude in degrees
altitude_kmnumberAltitude above ground in km
utilizationnumberResource utilization (0-1)
healthstringHealth status (see below)
capacity_gbpsnumberMaximum capacity in Gbps
queue_depth_gbnumberBuffered data in GB
labelstringHuman-readable display name

Health Status Values

ValueDescription
nominalOperating normally
degradedReduced performance
failedNot operational
maintenanceUnder scheduled maintenance

Edge Schema

NameTypeDescription
sourcestringSource node ID
targetstringDestination node ID
capacity_gbpsnumberLink capacity in Gbps
latency_msnumberNetwork latency in ms
utilizationnumberLink utilization (0-1)
is_activebooleanWhether link is operational
reliabilitynumberHistorical reliability (0-1)
packet_loss_ratenumberPacket loss ratio

Visualization

The topology response is designed for use with graph visualization libraries.

D3.js Example

const response = await fetch('/api/v1/topology/', {
headers: { 'Authorization': `Bearer ${token}` }
});
const topology = await response.json();
const simulation = d3.forceSimulation(topology.nodes)
.force('link', d3.forceLink(topology.edges).id(d => d.id))
.force('charge', d3.forceManyBody().strength(-300))
.force('center', d3.forceCenter(width / 2, height / 2));
// Render nodes
const nodes = svg.selectAll('circle')
.data(topology.nodes)
.enter()
.append('circle')
.attr('r', d => d.type === 'satellite' ? 5 : 10)
.attr('fill', d => d.health === 'nominal' ? '#10b981' : '#ef4444');
// Render edges
const edges = svg.selectAll('line')
.data(topology.edges)
.enter()
.append('line')
.attr('stroke', d => d.is_active ? '#64748b' : '#ef4444')
.attr('stroke-width', d => d.utilization * 3);

Cytoscape.js Example

const response = await fetch('/api/v1/topology/', {
headers: { 'Authorization': `Bearer ${token}` }
});
const topology = await response.json();
const cy = cytoscape({
container: document.getElementById('cy'),
elements: {
nodes: topology.nodes.map(n => ({
data: { id: n.id, label: n.label, ...n }
})),
edges: topology.edges.map(e => ({
data: { source: e.source, target: e.target, ...e }
}))
},
style: [
{
selector: 'node[type="satellite"]',
style: {
'background-color': '#3b82f6',
'width': 20,
'height': 20
}
},
{
selector: 'node[type="ground_station"]',
style: {
'background-color': '#10b981',
'width': 30,
'height': 30
}
},
{
selector: 'edge',
style: {
'width': 'data(utilization)',
'line-color': '#64748b'
}
}
]
});

Cesium.js (3D Globe)

const response = await fetch('/api/v1/topology/', {
headers: { 'Authorization': `Bearer ${token}` }
});
const topology = await response.json();
// Add satellites
topology.nodes
.filter(n => n.type === 'satellite')
.forEach(sat => {
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(sat.lon, sat.lat, sat.altitude_km * 1000),
point: {
pixelSize: 8,
color: sat.health === 'nominal' ? Cesium.Color.GREEN : Cesium.Color.RED
},
label: {
text: sat.label,
font: '12px sans-serif'
}
});
});
// Add links
topology.edges.forEach(edge => {
const source = topology.nodes.find(n => n.id === edge.source);
const target = topology.nodes.find(n => n.id === edge.target);
viewer.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArrayHeights([
source.lon, source.lat, source.altitude_km * 1000,
target.lon, target.lat, target.altitude_km * 1000
]),
width: edge.utilization * 5,
material: edge.is_active ? Cesium.Color.CYAN : Cesium.Color.RED
}
});
});

CLI Example

Terminal window
constellation topology get

Output:

Network Topology (2026-01-16T20:00:00Z)
Nodes: 125 total
- 100 satellites
- 20 ground stations
- 5 data centers
Edges: 342 links
- 320 active
- 22 inactive
Top nodes by utilization:
1. sat-042: 0.92 (degraded)
2. sat-018: 0.88 (nominal)
3. gs-007: 0.85 (nominal)

Python Example

import requests
response = requests.get(
"https://api.constellation-io.com/api/v1/topology/",
headers={"Authorization": f"Bearer {token}"},
)
topology = response.json()
print(f"Nodes: {len(topology['nodes'])}")
print(f"Edges: {len(topology['edges'])}")
# Find high-utilization links
critical_links = [
e for e in topology["edges"]
if e["utilization"] > 0.8 and e["is_active"]
]
print(f"\nCritical links ({len(critical_links)}):")
for link in critical_links[:5]:
print(f" {link['source']}{link['target']}: {link['utilization']:.0%}")

Filtering (Coming Soon)

Future versions will support filtering:

GET /api/v1/topology/?type=satellite&health=degraded
GET /api/v1/topology/?utilization_min=0.8
GET /api/v1/topology/?bbox=-130,30,-115,50