API Reference
Everything you need to integrate Heliora solar weather data into your systems. Real-time monitoring, webhooks, threshold profiles, and historical event archives.
Getting Started
Base URL
https://api.heliora.app/apiAuthentication
All authenticated endpoints require a Bearer token in the Authorization header. API keys are prefixed with hlr_ and are tied to your account tier.
Authorization: Bearer hlr_your_api_key_hereResponse envelope
Every response wraps the payload in a standard envelope with metadata about data freshness, source attribution, and the current system phase.
{
"data": { ... },
"meta": {
"timestamp": "2026-04-05T14:32:00Z",
"freshness_state": "LIVE",
"source": "SDO/HMI SHARP",
"phase": "NOMINAL"
}
}Freshness states
| State | Meaning |
|---|---|
LIVE | Data is current, within expected cadence |
LATEST | Most recent available, slightly behind cadence |
STALE | Data has aged beyond expected update interval |
OFFLINE | Source is unreachable or not reporting |
Error responses
{
"error": "Invalid API key"
}
// HTTP status codes:
// 400 - Bad request (invalid parameters)
// 401 - Invalid or missing API key
// 403 - Insufficient tier for this endpoint
// 404 - Resource not found
// 429 - Rate limit exceeded (check Retry-After header)Endpoints
Core endpoints are available to all tiers. Enterprise endpoints require an enterprise-tier API key.
Core
/api/statusCurrent dashboard status and banner phase
/api/regionsAll tracked active regions ranked by danger
/api/regions/{id}Full detail for a single active region
/api/regions/{id}/arcConfidence arc time series for a region
/api/transitAll CMEs currently in transit
/api/transit/{id}Detail for a single CME transit
/api/transit/{id}/shiftsArrival window revision history
/api/dscovrLatest DSCOVR solar wind parameters at L1
/api/chainFull sun-to-earth causal chain
/api/banner/historyPhase transition log with triggers
/api/sourcesHealth and freshness of all data sources
Enterprise
/api/webhooksRegister a webhook endpoint
/api/webhooksList webhook registrations
/api/webhooks/{id}Webhook detail with delivery log
/api/webhooks/{id}Unregister a webhook
/api/webhooks/{id}Test webhook (action=test)
/api/profilesCreate threshold profile
/api/profilesList threshold profiles
/api/profiles/{id}Single profile detail
/api/profiles/{id}Update threshold profile
/api/profiles/{id}Delete threshold profile
/api/archive/eventsHistorical events with filters and pagination
/api/archive/events/{id}Single historical event detail
/api/archive/events/{id}/timelineFull timeline snapshot for replay
Example: Get current status
curl -H "Authorization: Bearer hlr_your_key" \
https://api.heliora.app/api/status{
"data": {
"phase": "WATCH",
"label": "Active Region Developing",
"text": "AR 13664 showing increasing magnetic complexity.",
"evidence_type": "photospheric",
"timestamp": "2026-04-05T14:32:00Z",
"ar_count": 3
},
"meta": {
"timestamp": "2026-04-05T14:32:00Z",
"freshness_state": "LIVE",
"source": "Heliora Status Engine",
"phase": "WATCH"
}
}Example: List active regions
curl -H "Authorization: Bearer hlr_your_key" \
https://api.heliora.app/api/regions{
"data": [
{
"ar": 13664,
"danger_rank": 1,
"danger_score": 7.2,
"confidence": 68,
"trend": "rising",
"threat_band": "CRITICAL",
"shape_locked": true,
"rope_reorienting": false,
"severity_indicator": "X-class likely",
"hours_observed": 120,
"location": "S17W42",
"lifecycle_stage": "mature"
}
],
"meta": { ... }
}Webhooks
Webhooks push event notifications to your endpoints in real time. Register a URL, choose which event types to subscribe to, and Heliora will POST JSON payloads as events occur. Enterprise tier required.
Event types
| Type | Trigger |
|---|---|
phase_transition | System phase escalated or de-escalated |
score_threshold | Active region danger score crossed a profile threshold |
cme_detected | New CME observed in coronagraph imagery |
l1_crossing | Interplanetary shock detected at L1 by DSCOVR |
window_shift | CME arrival window revised beyond threshold |
source_state | Data source freshness changed (e.g. LIVE to STALE) |
Register a webhook
curl -X POST \
-H "Authorization: Bearer hlr_enterprise_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://ops.example.com/heliora/events",
"event_types": ["phase_transition", "cme_detected", "l1_crossing"],
"filters": { "min_g_level": "G3" }
}' \
https://api.heliora.app/api/webhooks{
"data": {
"id": "wh_1712345678_a1b2c3d4e5f6",
"url": "https://ops.example.com/heliora/events",
"event_types": ["phase_transition", "cme_detected", "l1_crossing"],
"filters": { "min_g_level": "G3" },
"secret": "whsec_...",
"created_at": "2026-04-05T14:32:00Z",
"active": true
}
}Payload format
{
"event_type": "phase_transition",
"timestamp": "2026-04-05T14:32:00Z",
"data": {
"from_phase": "WATCH",
"to_phase": "ADVISORY",
"trigger": "AR 13664 danger score crossed 7.0",
"evidence_type": "photospheric"
}
}HMAC verification
Every delivery includes an X-Heliora-Signature header containing an HMAC-SHA256 hex digest of the request body, signed with your webhook secret. Always verify this signature before processing payloads.
X-Heliora-Signature: a1b2c3d4e5f6... (HMAC-SHA256 hex)
X-Heliora-Event: phase_transition
X-Heliora-Delivery: dlv_1712345678_a1b2c3import hmac, hashlib
def verify_signature(body: bytes, secret: str, signature: str) -> bool:
expected = hmac.new(
secret.encode(), body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)import crypto from 'crypto';
function verifySignature(body, secret, signature) {
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected), Buffer.from(signature)
);
}Retry policy
Failed deliveries (non-2xx or network error) are retried up to 3 times with exponential backoff: 2 seconds, 8 seconds, 30 seconds. Each attempt is logged in the delivery history.
Threshold Profiles
Profiles let you define independent sets of alert triggers. Create an "ops" profile with a threshold of 70 for your operations team, and an "executive" profile at 90 that only fires for high-confidence events. Enterprise tier required.
Create a profile
curl -X POST \
-H "Authorization: Bearer hlr_enterprise_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Ops Team",
"triggers": [
{ "type": "score_rising", "threshold": 70, "enabled": true },
{ "type": "new_cme", "threshold": 0, "enabled": true },
{ "type": "phase_change", "threshold": 0, "enabled": true },
{ "type": "window_shift", "threshold": 4, "enabled": false }
]
}' \
https://api.heliora.app/api/profiles{
"data": {
"id": "prof_1712345678_a1b2c3d4e5f6",
"name": "Ops Team",
"triggers": [
{ "type": "score_rising", "threshold": 70, "enabled": true },
{ "type": "new_cme", "threshold": 0, "enabled": true },
{ "type": "phase_change", "threshold": 0, "enabled": true },
{ "type": "window_shift", "threshold": 4, "enabled": false }
]
}
}Update a profile
curl -X PUT \
-H "Authorization: Bearer hlr_enterprise_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Ops Team (updated)",
"triggers": [
{ "type": "score_rising", "threshold": 60, "enabled": true },
{ "type": "new_cme", "threshold": 0, "enabled": true }
]
}' \
https://api.heliora.app/api/profiles/{id}Trigger types
| Type | Threshold meaning |
|---|---|
score_rising | Fire when confidence exceeds this percentage (0-100) |
score_falling | Fire when confidence drops below this percentage |
new_cme | Threshold unused, fires on any new CME detection |
l1_crossing | Threshold unused, fires on shock detection |
phase_change | Threshold unused, fires on any phase transition |
window_shift | Fire when arrival window shifts by more than N hours |
Historical Data
Access archived geomagnetic storm events for analysis, backtesting, and reporting. Includes full timeline snapshots for event replay. Enterprise tier required.
List events
curl -H "Authorization: Bearer hlr_enterprise_key" \
"https://api.heliora.app/api/archive/events?start_after=2024-01-01&g_level=G3&limit=10"{
"data": [
{
"id": "evt-20250115-001",
"source_ar": 13955,
"flare_class": "X2.3",
"g_level": "G3",
"phase_reached": "WARNING",
"cme_speed": 1550,
"start_time": "2025-01-15T16:00:00Z",
"end_time": "2025-01-17T22:00:00Z",
"peak_dst": -210,
"peak_kp": 7
}
],
"pagination": {
"cursor": "evt-20250115-001",
"limit": 10,
"total": 5
}
}Query parameters
| Param | Type | Description |
|---|---|---|
start_after | ISO-8601 | Events starting after this date |
start_before | ISO-8601 | Events starting before this date |
g_level | string | Filter by geomagnetic storm level (G1-G5) |
phase | string | Filter by peak phase reached |
cursor | string | Event ID cursor for pagination |
limit | integer | Results per page (1-100, default 20) |
CSV export
Set the Accept: text/csv header to receive results as a downloadable CSV file.
curl -H "Authorization: Bearer hlr_enterprise_key" \
-H "Accept: text/csv" \
"https://api.heliora.app/api/archive/events?g_level=G3"Timeline replay
Retrieve timestamped snapshots of system state throughout an event for replay and analysis.
curl -H "Authorization: Bearer hlr_enterprise_key" \
https://api.heliora.app/api/archive/events/evt-20240510-001/timeline{
"data": [
{
"timestamp": "2024-05-10T06:00:00Z",
"phase": "WATCH",
"danger_score": 5.2,
"confidence": 45,
"bz": null,
"speed": null,
"dst": -12,
"note": "X5.8 flare detected from AR 13664"
},
{
"timestamp": "2024-05-11T16:37:00Z",
"phase": "EMERGENCY",
"danger_score": 9.6,
"confidence": 95,
"bz": -38,
"speed": 820,
"dst": -110,
"note": "Interplanetary shock detected at L1"
}
]
}SDKs
No official SDK packages yet. Below are usage examples for common languages. The API uses standard REST conventions, so any HTTP client works.
Python
import requests
API_KEY = "hlr_your_api_key"
BASE_URL = "https://api.heliora.app/api"
headers = {"Authorization": f"Bearer {API_KEY}"}
# Get current status
status = requests.get(f"{BASE_URL}/status", headers=headers).json()
print(f"Phase: {status['data']['phase']}")
# List active regions
regions = requests.get(f"{BASE_URL}/regions", headers=headers).json()
for ar in regions["data"]:
print(f"AR {ar['ar']}: score={ar['danger_score']}, trend={ar['trend']}")
# Get historical events as CSV
resp = requests.get(
f"{BASE_URL}/archive/events",
headers={**headers, "Accept": "text/csv"},
params={"g_level": "G3"}
)
with open("events.csv", "w") as f:
f.write(resp.text)
# Register a webhook
webhook = requests.post(
f"{BASE_URL}/webhooks",
headers=headers,
json={
"url": "https://ops.example.com/heliora",
"event_types": ["phase_transition", "l1_crossing"]
}
).json()
print(f"Webhook ID: {webhook['data']['id']}")
print(f"Secret: {webhook['data']['secret']}")JavaScript / TypeScript
const API_KEY = "hlr_your_api_key";
const BASE = "https://api.heliora.app/api";
const headers = { Authorization: `Bearer ${API_KEY}` };
// Get current status
const status = await fetch(`${BASE}/status`, { headers }).then(r => r.json());
console.log(`Phase: ${status.data.phase}`);
// List active regions
const regions = await fetch(`${BASE}/regions`, { headers }).then(r => r.json());
for (const ar of regions.data) {
console.log(`AR ${ar.ar}: score=${ar.danger_score}`);
}
// Register a webhook
const webhook = await fetch(`${BASE}/webhooks`, {
method: "POST",
headers: { ...headers, "Content-Type": "application/json" },
body: JSON.stringify({
url: "https://ops.example.com/heliora",
event_types: ["phase_transition", "l1_crossing"],
}),
}).then(r => r.json());
console.log(`Webhook: ${webhook.data.id}`);
console.log(`Secret: ${webhook.data.secret}`);
// Poll for transit data
const transit = await fetch(`${BASE}/transit`, { headers }).then(r => r.json());
for (const cme of transit.data) {
console.log(`CME ${cme.id}: ${cme.speed_km_s} km/s, ${cme.position_pct}% to Earth`);
}Rate Limits
Rate limits are enforced per API key using a 1-minute sliding window. When the limit is exceeded, the API returns 429 with a Retry-After header.
| Tier | Requests/min | Webhook registrations | Threshold profiles |
|---|---|---|---|
| Anonymous | 60 | -- | -- |
| Professional | 300 | -- | -- |
| Enterprise | 3,000 | 50 | 20 |
HTTP/1.1 429 Too Many Requests
Retry-After: 12
{
"error": "Rate limit exceeded"
}SLA
Enterprise tier. Measured monthly over calendar months. Excludes scheduled maintenance windows announced 72+ hours in advance.
Measurement methodology
- Synthetic health checks every 60 seconds from 3 geographic regions
- An endpoint is "down" if it returns non-2xx or response time exceeds 5 seconds
- Uptime = (total minutes - downtime minutes) / total minutes
- Data source outages (SDO, DSCOVR) are upstream and not counted against SLA
- The system continues to serve STALE-flagged data during source outages
Response time targets
| Endpoint class | p50 | p99 |
|---|---|---|
| Status / regions / transit | < 100ms | < 500ms |
| Archive queries | < 200ms | < 1s |
| Webhook dispatch | < 500ms | < 2s |
Incident communication
Incidents are posted to the status page and communicated via webhook (source_state event type) to registered enterprise endpoints. Post-incident reports are published within 48 hours.
Changelog
Phase 3 -- Enterprise API
- Webhook system with HMAC-SHA256 signatures and exponential retry
- Threshold profiles for independent trigger configurations
- Historical event archive with cursor-based pagination and CSV export
- Timeline replay endpoint for event post-analysis
- SLA monitoring and status page
- Enterprise tier auth with 3,000 req/min rate limit
Phase 2 -- Professional Features
- Configurable alert system with sound notifications
- Confidence arc time series with inflection annotations
- CME arrival window shift tracking
- Banner phase transition history
- Professional tier API keys (300 req/min)
Phase 1 -- Public Launch
- Real-time status banner with 5-level threat escalation
- Active region tracking with danger scoring
- CME transit corridor visualization
- DSCOVR solar wind parameters
- Sun-to-earth causal chain display
- Data source health monitoring