OrbitAlert API
REST · JSON · HTTPS · Get started in 5 minutes
Satellite pass predictions and proactive webhook alerts — delivered to any HTTPS endpoint minutes before a satellite rises above your horizon. One API key, three endpoints.
https://api.orbitalert.netAuthentication
Every request must include your API key in the X-API-Key header. Manage your keys from the API Keys page.
curl https://api.orbitalert.net/health \
-H "X-API-Key: sat_xk29mQpLvN3rT8wZ"Keep your key secret. Never commit it to version control or expose it in client-side code. Rotate it immediately from the dashboard if it is ever compromised.
GET /passes
Returns all predicted passes above the elevation threshold for the given observer and prediction window, sorted chronologically by AOS. Timing precision is ±10 seconds (10 s propagation steps, SGP4).
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
satelliterequired | string | — | Satellite name from the Celestrak catalog, e.g. "NOAA-20", "ISS (ZARYA)", "METOP-B", "TERRA" |
latrequired | float | — | Observer geodetic latitude in degrees, −90 to 90 |
lonrequired | float | — | Observer longitude in degrees, −180 to 180 |
hours | float | 24 | Prediction window in hours. Clamped to 0.1 – 72. |
min_elevation | float | 10 | Minimum peak elevation in degrees. Passes that never reach this angle are omitted. |
Request
curl "https://api.orbitalert.net/passes?satellite=NOAA-20&lat=37.92&lon=23.73&hours=24" \
-H "X-API-Key: sat_xk29mQpLvN3rT8wZ"Response 200 OK
[
{
"satellite": "NOAA-20",
"aos_utc": "2026-06-01T06:14:32Z",
"los_utc": "2026-06-01T06:23:17Z",
"tca_utc": "2026-06-01T06:18:54Z",
"max_elevation_deg": 67.3,
"duration_seconds": 525,
"azimuth_at_aos": 342.1,
"azimuth_at_los": 158.7
},
{
"satellite": "NOAA-20",
"aos_utc": "2026-06-01T14:53:08Z",
"los_utc": "2026-06-01T15:01:44Z",
"tca_utc": "2026-06-01T14:57:26Z",
"max_elevation_deg": 22.8,
"duration_seconds": 516,
"azimuth_at_aos": 315.4,
"azimuth_at_los": 197.2
}
]| Field | Description |
|---|---|
aos_utc | Acquisition of Signal — satellite rises above horizon (ISO 8601 UTC) |
los_utc | Loss of Signal — satellite drops below horizon (ISO 8601 UTC) |
tca_utc | Time of Closest Approach — moment of maximum elevation (ISO 8601 UTC) |
max_elevation_deg | Peak elevation angle in degrees (0–90). Higher = stronger signal. |
duration_seconds | Total pass duration in whole seconds (LOS − AOS) |
azimuth_at_aos | Satellite compass bearing at rise — 0° = North, clockwise |
azimuth_at_los | Satellite compass bearing at set — 0° = North, clockwise |
POST /alerts
Creates a persistent alert. OrbitAlert checks for upcoming passes every 5 minutes and fires a POST to your webhook the specified number of minutes before each qualifying pass. Alerts remain active until deleted.
Request body
| Parameter | Type | Default | Description |
|---|---|---|---|
satellite_namerequired | string | — | Satellite name matching the Celestrak catalog, e.g. "NOAA-20", "METOP-C" |
observer_latrequired | float | — | Observer geodetic latitude, −90 to 90 |
observer_lonrequired | float | — | Observer longitude, −180 to 180 |
webhook_urlrequired | string (HTTPS) | — | Destination for webhook POSTs. Must use HTTPS — HTTP URLs are rejected. |
minutes_before | integer | 10 | How many minutes before AOS to fire the webhook. Range: 1–60. |
min_elevation | float | 10.0 | Skip passes with a peak elevation below this threshold (degrees). |
Request
curl -X POST https://api.orbitalert.net/alerts \
-H "X-API-Key: sat_xk29mQpLvN3rT8wZ" \
-H "Content-Type: application/json" \
-d '{
"satellite_name": "NOAA-20",
"observer_lat": 37.9195,
"observer_lon": 23.7310,
"webhook_url": "https://your-server.com/hook",
"minutes_before": 10,
"min_elevation": 15.0
}'Response 201 Created
{
"id": "alert_8f3a12bc",
"satellite_name": "NOAA-20",
"observer_lat": 37.9195,
"observer_lon": 23.7310,
"webhook_url": "https://your-server.com/hook",
"minutes_before": 10,
"min_elevation": 15.0,
"created_at": "2026-05-31T14:22:07Z"
}Delivery & retry policy
If your endpoint returns a non-2xx status, OrbitAlert retries up to 3 times with exponential back-off: 30 s → 2 min → 8 min. Your endpoint must respond within 10 seconds or the attempt is counted as failed. All delivery attempts and their HTTP status codes are visible in the dashboard webhook log.
GET /space-weather
Returns the current NOAA planetary K-index (Kp), a 0–9 scale measuring geomagnetic disturbance. Useful for scheduling high-priority passes or adjusting receive parameters. Data is refreshed every 15 minutes from NOAA SWPC.
Request
curl https://api.orbitalert.net/space-weather \
-H "X-API-Key: sat_xk29mQpLvN3rT8wZ"Response 200 OK
{
"kp_index": 3.2,
"severity": "unsettled",
"description": "Minor geomagnetic disturbance. Enhanced auroral activity above 60°N/S. No impact on VHF/UHF satellite links.",
"updated_at": "2026-05-31T14:00:00Z"
}| severity | Kp range | What it means |
|---|---|---|
quiet | 0–2 | Nominal conditions. No impact on satellite operations or polar routes. |
unsettled | 3–4 | Minor disturbance. Enhanced auroral activity above 60°N/S. |
storm | 5–6 | Geomagnetic storm. HF radio degraded at polar latitudes. |
severe | 7–9 | Severe storm. Possible satellite drag increase and orientation effects. |
Webhook payload
When a pass is imminent, OrbitAlert POSTs the following JSON to your registered webhook_url. Respond with any 2xx status within 10 seconds to acknowledge delivery.
{
"event": "pass.upcoming",
"alert_id": "alert_8f3a12bc",
"satellite": "NOAA-20",
"aos_utc": "2026-06-01T06:14:32Z",
"los_utc": "2026-06-01T06:23:17Z",
"tca_utc": "2026-06-01T06:18:54Z",
"max_elevation_deg": 67.3,
"duration_seconds": 525,
"azimuth_at_aos": 342.1,
"azimuth_at_los": 158.7,
"kp_index": 3.2,
"minutes_until_aos": 9,
"observer": {
"lat": 37.9195,
"lon": 23.7310
},
"delivered_at": "2026-06-01T06:05:33Z"
}| Field | Description |
|---|---|
event | Always "pass.upcoming" in this version of the API |
alert_id | ID of the alert that triggered this delivery |
satellite | Satellite name from the Celestrak catalog |
aos_utc / los_utc / tca_utc | Pass window timestamps in ISO 8601 UTC |
max_elevation_deg | Predicted peak elevation above the horizon (degrees) |
duration_seconds | Total pass duration in seconds (LOS − AOS) |
azimuth_at_aos / azimuth_at_los | Compass bearing at rise and set — 0° = North, clockwise |
kp_index | Current NOAA Kp at the moment of delivery |
minutes_until_aos | Minutes remaining until the satellite clears the horizon |
observer | The lat/lon registered for this alert |
delivered_at | Server timestamp when this POST was dispatched (ISO 8601 UTC) |
Error codes
All errors return JSON with error (human-readable) and code (machine-readable) fields.
{
"error": "Invalid or missing API key.",
"code": "unauthorized"
}| Status | code | When it happens |
|---|---|---|
| 401 | unauthorized | Missing X-API-Key header, or the key has been revoked |
| 403 | forbidden | Your plan does not include this endpoint |
| 404 | not_found | Alert ID does not exist, or belongs to another account |
| 422 | validation_error | Request body failed schema validation — check field types and required fields |
| 422 | invalid_webhook_url | webhook_url must use HTTPS — http:// URLs are rejected |
| 429 | rate_limited | Too many requests. Free: 60 req/min · Starter: 300 req/min · Pro: unlimited |
| 500 | internal_error | Unexpected server error. Persistent occurrences should be reported. |
Complete quickstart
A self-contained Python script that starts a local webhook receiver, registers a NOAA-20 alert over Athens, and prints the full payload when the satellite is 10 minutes out. Zero dependencies beyond requests.
#!/usr/bin/env python3
"""
OrbitAlert quickstart — register an alert and print the webhook payload.
Run: pip install requests && python quickstart.py
"""
import time, threading, requests
from http.server import HTTPServer, BaseHTTPRequestHandler
API_KEY = "sat_xk29mQpLvN3rT8wZ" # replace with your key
WEBHOOK = "https://YOUR_NGROK_ID.ngrok.io/hook" # expose :9000 via ngrok
BASE = "https://api.orbitalert.net"
# 1. Local receiver — prints every incoming POST body
class Hook(BaseHTTPRequestHandler):
def do_POST(self):
n = int(self.headers["Content-Length"])
body = self.rfile.read(n).decode()
print(f"\n>>> Webhook received:\n{body}\n")
self.send_response(200)
self.end_headers()
def log_message(self, *_): pass
threading.Thread(
target=HTTPServer(("", 9000), Hook).serve_forever,
daemon=True,
).start()
print("Webhook receiver listening on :9000")
# 2. Register an alert — NOAA-20 over Athens, 10 min notice, ≥ 15° elevation
r = requests.post(f"{BASE}/alerts",
headers={"X-API-Key": API_KEY},
json={"satellite_name": "NOAA-20",
"observer_lat": 37.9195, "observer_lon": 23.7310,
"webhook_url": WEBHOOK,
"minutes_before": 10, "min_elevation": 15.0})
r.raise_for_status()
print(f"Alert registered: {r.json()['id']}")
print("Waiting for the next NOAA-20 pass… (Ctrl-C to quit)")
time.sleep(86400)For local development, expose port 9000 with ngrok (ngrok http 9000) and replace YOUR_NGROK_ID with the subdomain it assigns. The first qualifying pass typically fires within a few hours, depending on your location.
OrbitAlert API · Dashboard
Get an API key →