A monitor is one Starlink site in your organization. While the dish is connected, Orbimon stores roughly one sample per second, then serves coarser resolutions for longer ranges.
Discover monitors with Organizations → List monitors. Use a monitor API token (read access) for the endpoints below.
What’s in a monitor
Monitor
├── Metadata (id, name, starlink_id, status) → organization list
└── Metrics
├── raw (~1 s) short windows
├── hourly (1 h) days–weeks
├── daily (1 d) months
└── year (1 d) up to 365 days
| Endpoint | Resolution | Recommended end − start |
|---|---|---|
| Raw | ~1 second | Up to 12 hours |
| Hourly | 1 hour | Up to ~30 days |
| Daily | 1 day | Weeks to months |
| Year | 1 day | Up to 365 days |
If the range is too wide for that endpoint, you get 400 invalid_request — switch to a coarser resolution.
Common query parameters
All metrics routes:
| Param | Required | Description |
|---|---|---|
start | yes | Start time (ISO 8601), inclusive — e.g. 2026-10-06T00:00:00Z |
end | yes | End time (ISO 8601), inclusive |
hourly, daily, and year also accept:
| Param | Default | Description |
|---|---|---|
metric | avg | Aggregate to plot: avg | max | min | p95 |
p95 is most meaningful for latency; other fields follow avg/max/min as documented per backend.
Metric fields
Same field names across resolutions. Units are fixed.
Link quality
| Field | Type | Unit / notes |
|---|---|---|
timestamp | string | Sample or bucket time (ISO 8601) |
connected | 0 | 1 | Link up in this sample/bucket |
state | string | e.g. CONNECTED, SEARCHING, DISCONNECTED |
downlink_throughput_bps | number | Download, bits per second |
uplink_throughput_bps | number | Upload, bits per second |
pop_ping_latency_ms | number | Latency to Starlink POP (milliseconds) |
pop_ping_drop_rate | number | Packet loss ratio 0–1 (not percent) |
Obstructions
| Field | Type | Notes |
|---|---|---|
obstruction_percent | number | Obstruction percentage from the dish |
currently_obstructed | 0 | 1 | Obstructed at sample / in bucket |
obstruction_duration | number | Duration metric from the dish |
obstruction_interval | number | Interval metric from the dish |
Orientation & GPS
| Field | Type | Notes |
|---|---|---|
direction_azimuth | number | null | Degrees |
direction_elevation | number | null | Degrees |
tilt_angle_deg | number | null | Degrees |
gps_sats | number | null | GPS satellite count |
Power & alerts
| Field | Type | Notes |
|---|---|---|
power_watts | number | null | Power draw when available |
alerts | string[] | Dish alert codes in this sample/bucket |
Throughput is always bps (divide by 1_000_000 for Mbps in your client).
Get raw metrics
Per-second points for a short window.
GET /v1/monitors/:monitor_id/metrics/raw?start=2026-10-06T10:00:00Z&end=2026-10-06T12:00:00Z
Authorization: Bearer <monitor_token>
Constraints
end − startmust be less than 12 hours- Limited by your plan’s raw retention
Response 200
{
"data": [
{
"timestamp": "2026-10-06T10:00:01.000Z",
"connected": 1,
"state": "CONNECTED",
"downlink_throughput_bps": 152000000,
"uplink_throughput_bps": 21000000,
"pop_ping_latency_ms": 38.2,
"pop_ping_drop_rate": 0.002,
"obstruction_percent": 1.4,
"currently_obstructed": 0,
"obstruction_duration": 0,
"obstruction_interval": 0,
"direction_azimuth": 182.1,
"direction_elevation": 42.0,
"tilt_angle_deg": 1.2,
"gps_sats": 12,
"power_watts": 78.5,
"alerts": []
}
],
"meta": {
"monitor_id": "mon_1736...",
"resolution": "raw",
"start": "2026-10-06T10:00:00.000Z",
"end": "2026-10-06T12:00:00.000Z",
"count": 7200
}
}
Get hourly metrics
One point per hour. Empty hours may appear as disconnected / zero-filled buckets.
GET /v1/monitors/:monitor_id/metrics/hourly?start=2026-09-01T00:00:00Z&end=2026-09-07T23:59:59Z&metric=avg
Authorization: Bearer <monitor_token>
Constraints
- Best for ranges from about 1 day up to 30 days
metric:avg|max|min|p95
Response 200
Same series shape as raw (data + meta), for example:
"meta": {
"monitor_id": "mon_1736...",
"resolution": "hourly",
"metric": "avg",
"start": "2026-09-01T00:00:00.000Z",
"end": "2026-09-07T23:59:59.000Z",
"count": 168
}
Get daily metrics
One point per calendar day.
GET /v1/monitors/:monitor_id/metrics/daily?start=2026-01-01&end=2026-03-31&metric=avg
Authorization: Bearer <monitor_token>
Constraints
- Use for multi-week and multi-month ranges
start/endmay be a date (YYYY-MM-DD) or a full ISO datetimemetric:avg|max|min|p95
Response 200
"meta": {
"resolution": "daily",
"metric": "avg",
"count": 90
}
Field names match Metric fields.
Get year metrics
Trailing-year (or any ≤ 365 day) view at daily resolution.
GET /v1/monitors/:monitor_id/metrics/year?start=2025-10-06&end=2026-10-06&metric=avg
Authorization: Bearer <monitor_token>
Constraints
end − start≤ 365 daysmetric:avg|max|min|p95
Response 200
"meta": {
"resolution": "year",
"metric": "avg",
"count": 365
}
Which endpoint should I use?
| Goal | Call |
|---|---|
| Debug the last few hours | .../metrics/raw |
| Week or month charts | .../metrics/hourly |
| Quarter / multi-month | .../metrics/daily |
| Last year | .../metrics/year |
Avoid requesting weeks of raw data — at one sample per second that is tens of thousands of points per day per monitor.
Errors
| Status | error | When |
|---|---|---|
400 | invalid_request | Missing start/end, range too wide, bad metric |
401 | unauthorized | Invalid token |
403 | forbidden | Token belongs to another monitor |
404 | not_found | Unknown monitor_id |
502 | upstream_error | Temporary metrics issue |
No data in range → 200 with "data": [] and meta.count: 0.
Coming later
Not in the public API yet:
- Create / delete monitor (use the dashboard)
- Device ingest API (Orbimon OS only)
- Alerts history
- Dedicated “latest sample” shortcut