API Reference
EVE Emptiness exposes a read-only JSON API over the same origin as the web app. All endpoints are public — no authentication required. Data refreshes hourly from the EVE ESI. Historical data covers a rolling 30-day window stored in PostgreSQL.
https://jumps.tovdc.com/api
Notes
avg_daily_jumps_30d
is computed by this service: hourly readings are summed per day, then averaged across the 30-day window.
Live Data
Returns k-space systems ranked by activity score (or weighted recent activity), enriched with 30-day trend metrics, topology data, and ESI flags. Default limit is 50 systems.
| Name | Type | Default | Description |
|---|---|---|---|
| maxJumps | integer | — | Exclude systems with live jumps above this value |
| maxKills | integer | — | Exclude systems with live ship+pod+NPC kills above this value |
| securityMin | float | -1.0 | Minimum security status (-1.0 to 1.0) |
| securityMax | float | 1.0 | Maximum security status (-1.0 to 1.0) |
| region | string | — | Filter to a single region by name (e.g. Delve) |
| constellation | string | — | Filter to a single constellation by name |
| limit | integer | 50 | Max results to return (capped server-side) |
| sortBy | string | activity | activity (P95-normalized score) or weighted (exponential-decay recent activity) |
| minConsistency | integer | 0 | Minimum consistency score 0–100 (% of last 30 days that were quiet) |
| excludeIncursions | boolean | false | Exclude systems in active incursions |
| excludeSovCampaigns | boolean | false | Exclude systems with active sovereignty campaigns |
| excludeFW | boolean | false | Exclude faction warfare systems |
| excludeHighway | boolean | false | Exclude pipe/hub topology systems (high traffic chokepoints) |
| excludePochven | boolean | true | Exclude Pochven systems |
| excludeWormholeAccess | boolean | false | Exclude systems with active Thera wormhole connections |
| includeNPCStation | boolean | false | When true, return only systems that have a permanent NPC station |
| includeQuietNow | boolean | false | When true, return only systems currently in a quiet window (current UTC hour below 30% of the system's circadian peak) |
| maxFWOccupancy | float | — | Max FW occupancy ratio 0.0–1.0 (only relevant for FW systems) |
| maxHubDistance | integer | 0 | When > 0, return only systems within N gate jumps of a major trade hub (Jita/Amarr/Dodixie/Rens/Hek) |
// GET /api/systems/activity?maxJumps=5&sortBy=weighted&limit=2
{
"systems": [
{
"system_id": 30000053,
"system_name": "G-0Q86",
"security_status": -0.496,
"region": "Delve",
"constellation": "B-WPLZ",
// Live ESI readings (last ~1 hour)
"jumps": 2,
"ship_kills": 0,
"pod_kills": 0,
"npc_kills": 14,
"activity_score": 3.2, // 0–100, P95-normalized; includes industry + ADM terms
"danger_density": 0, // PvP kills per 100 jumps
"pod_ratio": 0, // pod/ship kills; high = gate camp; null if pods but no ship kills
// 30-day trend metrics
"avg_daily_jumps_30d": 18.4, // SUM/day averaged over 30d
"avg_daily_kills_30d": 4.1,
"days_tracked_30d": 28,
"weighted_activity_score": 2.7, // exp decay, 2-day half-life
"quiet_days_30": 22,
"consistency_score": 78, // % of days that were quiet
"trend_direction": "stable",
"avg_daily_jumps": 17.9, // 7-day
"avg_daily_kills": 3.8,
// Topology
"topology_type": "dead-end", // dead-end|pipe|junction|hub
"gate_count": 1,
"bottleneck_score": 0,
"is_regional_gate": false,
"has_npc_station": true,
"neighbor_avg_activity": 5.8,
"reachable_via_wormhole": false,
"hub_distance": 14, // gate jumps to nearest trade hub; null if unreachable
// ESI flags
"in_incursion": false,
"incursion_staging": false,
"in_sov_campaign": false,
"in_fw": false,
"fw_occupancy": null,
"activity_type": "quiet",
// Sovereignty
"alliance_id": 99005338,
"corporation_id": null,
"sov_adm": 3.4 // CCP occupancy index 1–6; null if no sov / not reported
}
],
"total": 4893,
"filters": { /* echo of applied filters */ },
"timestamp": "2026-06-23T04:15:00.000Z"
}
Returns the list of all k-space region names. Useful for populating a region filter dropdown.
[
{ "id": 10000002, "name": "The Forge" },
{ "id": 10000030, "name": "Heimatar" },
/* … 114 regions total */
]
Returns constellations for the given region. Pass the numeric region ID (obtained from /regions) as the path segment.
// GET /api/constellations/10000060 (Delve)
[
{ "id": 20000700, "name": "1-A81R" },
{ "id": 20000690, "name": "6-UCYU" },
/* … */
]
Returns the average hourly activity distribution for a system over the last 30 days. Hours are in UTC (0–23). Values are averages of the hourly snapshot readings.
// GET /api/systems/30000053/circadian
{
"system_id": 30000053,
"hours": [
{ "hour": 0, "avg_jumps": 1.2, "avg_kills": 0.1 },
{ "hour": 1, "avg_jumps": 0.8, "avg_kills": 0.0 },
/* … 24 entries total … */
{ "hour": 23, "avg_jumps": 2.1, "avg_kills": 0.3 }
]
}
Case-insensitive substring search over known k-space system names (from the topology table).
Requires q with at least 2 characters (max 50); ILIKE wildcards are escaped. Returns up to 20 matches.
// GET /api/systems/search?q=jita
[
{ "system_id": 30000142, "system_name": "Jita", "region": "The Forge", "security_status": 0.946 }
]
Live status for up to 50 system ids passed as a comma-separated ids parameter.
Each entry has the same shape as a /systems/activity system object. Reuses cached ESI maps, so it is cheap.
// GET /api/systems/bulk?ids=30000142,30002187
{ "systems": [ /* same objects as /systems/activity */ ] }
All k-space systems that have map coordinates, with their latest activity score — for rendering the galaxy heatmap.
// GET /api/map/systems
[
{ "system_id": 30000142, "system_name": "Jita", "region": "The Forge",
"security_status": 0.946, "pos_x": -1.29e17, "pos_z": 1.20e17,
"activity_score": 92.4, "jumps": 3021 }
]
Cheap health check with no ESI dependency. Returns HTTP 200 when the database is reachable, 503 otherwise.
// GET /api/health
{ "status": "ok", "db": true, "last_collection": "2026-07-02T14:00:00.000Z" }
Historical Data
Returns raw hourly snapshot records for a system (up to 30 days). Each row is one collection run reading.
// GET /api/history/30000053
{
"system_id": 30000053,
"records": [
{
"timestamp": "2026-06-23T04:00:00.000Z",
"jumps": 2,
"ship_kills": 0,
"pod_kills": 0,
"npc_kills": 14,
"activity_score": 3.2
}
]
}
Aggregates hourly snapshots into daily totals (SUM per UTC day). This is what powers the 30-day history chart. One row per day with data.
| Name | Type | Default | Description |
|---|---|---|---|
| days | integer | 30 | Look-back window in days (max 30) |
// GET /api/history/30000053/range?days=30
{
"system_id": 30000053,
"days": [
{
"date": "2026-06-23",
"total_jumps": 38, // SUM of all hourly jump readings that day
"total_kills": 5,
"avg_score": 3.1,
"max_jumps": 8,
"max_kills": 2
}
]
}
total_jumps is the sum of every hourly reading for that UTC day —
not a 24-hour true total, since the ESI itself provides rolling 1-hour windows.
It is comparable to avg_daily_jumps_30d on the activity endpoint.
Systems with the largest activity change over the last 24 hours compared to their baseline.
{
"systems": [
{
"system_id": 30000053,
"system_name": "G-0Q86",
"region": "Delve",
"change_percent": -42.5,
"prev_avg_score": 6.1,
"curr_avg_score": 3.5
}
]
}
Systems ranked by consistency score — those that have been quiet the most days out of the last 30.
{
"systems": [
{
"system_id": 30000053,
"system_name": "G-0Q86",
"region": "Delve",
"consistency_score": 78,
"quiet_days_30": 22,
"avg_daily_jumps": 17.9
}
]
}
Groups systems by their computed 7-day trend direction: increasing stable decreasing.
{
"increasing": [ /* systems array */ ],
"stable": [ /* systems array */ ],
"decreasing": [ /* systems array */ ]
}
Gate Camping
Returns systems ranked by betweenness centrality (bottleneck score) — a measure of how many shortest paths in the k-space graph pass through each system. Higher = more traffic must cross this system. Topology data refreshes every 24 hours using Brandes' algorithm on ~5,200 k-space systems.
| Name | Type | Default | Description |
|---|---|---|---|
| minBottleneck | float | 0 | Minimum bottleneck score |
| topologyType | string | — | dead-end, pipe, junction, or hub |
| secTransition | boolean | false | Only systems that border a security band change (high↔low, low↔null) |
| securityMin | float | -1.0 | Minimum security status |
| securityMax | float | 1.0 | Maximum security status |
| region | string | — | Filter to a region by name |
| minJumps | integer | 0 | Minimum live jumps in the last hour |
| limit | integer | 50 | Max results to return |
{
"systems": [
{
"system_id": 30000142,
"system_name": "Jita",
"security_status": 0.946,
"region": "The Forge",
"jumps": 4821,
"ship_kills": 3,
"bottleneck_score": 18432.7,
"topology_type": "hub",
"gate_count": 6,
"is_regional_gate": true,
"connected_systems": [
{ "name": "Perimeter", "security": 0.943 }
],
"security_transitions": [],
"region_transitions": []
}
],
"total": 4893
}
Returns full topology data for one system: gate connections, bottleneck score, security/region transitions, and Thera wormhole access.
// GET /api/topology/30000053
{
"system_id": 30000053,
"topology_type": "dead-end",
"gate_count": 1,
"bottleneck_score": 0,
"is_regional_gate": false,
"has_npc_station": true,
"reachable_via_wormhole": false,
"connected_systems": [
{ "name": "NOL-M9", "security": -0.481 }
],
"security_transitions": [],
"region_transitions": [],
"last_updated": "2026-06-23T03:00:00.000Z"
}
Ore Scouting
Returns high-sec systems scored and tiered as ore anomaly scouting candidates. Scoring combines stargate topology (border proximity to low-sec) with 30-day historical activity data — quieter systems score higher as lower-competition targets. ESI cannot detect live anomalies; these are candidates requiring in-game confirmation.
| Tier | Criteria | Base Score |
|---|---|---|
| Tier 1 | 0.5 displayed security AND directly adjacent to a low-sec system | +100 |
| Tier 2 | High-sec AND within 1 stargate jump of a Tier 1 system | +30 |
| Tier 3 | All other high-sec systems | 0 |
| Condition | Modifier |
|---|---|
| Security display 0.5 | +15 |
| Security display 0.6 | +10 |
| Has NPC station (logistics) | +10 |
| More than 2 high-sec neighbors (route chaining) | +5 |
| Consistency score ≥ 70% (consistently quiet 30d) | +20 |
| Consistency score ≥ 50% | +10 |
| Avg daily jumps ≤ 5 (very low traffic) | +10 |
| Avg daily jumps ≤ 20 (low traffic) | +5 |
| Activity score > 40 (moderate competition) | −10 |
| Activity score > 60 (high competition) | −20 |
| Hub topology or bottleneck score > 0.005 (major route) | −20 |
| Name | Type | Default | Description |
|---|---|---|---|
| tier | integer | — | Filter to a specific tier: 1, 2, or 3. Omit for all tiers. |
| region | string | — | Filter to a region by name (e.g. Sinq Laison) |
| constellation | string | — | Filter to a constellation by name |
| minScore | integer | 0 | Exclude systems with a score below this threshold |
| npcStation | string | — | yes = only systems with an NPC station, no = only without. Omit for all. |
| sortBy | string | score | score | jumps (avg/day 30d) | kills (avg/day 30d) | consistency | activity | security | hub (jumps to nearest trade hub) |
| sortDir | string | per sort | asc or desc. Defaults to the sort's natural direction (score/consistency desc; jumps/kills/activity/security/hub asc). Ties break by score desc. |
| origin | string | — | Your current system (id or exact name, case-insensitive). Adds per-candidate jumps_from_origin, safe_jumps_from_origin (high-sec-only route; null if none exists) and route_crosses_lowsec, and enables sortBy=distance. Unknown system → 400. |
| routeMode | string | fastest | Requires origin. fastest = fewest jumps (ties prefer less low-sec); safest = least low-sec exposure first, then fewest jumps (like EVE's Safer autopilot — still routes through low-sec when unavoidable). Controls which route the distance sort and maxJumpsFromOrigin refer to. |
| avoidLowsec | boolean | false | Requires origin. Hard filter: excludes candidates with no all-high-sec route entirely. |
| maxJumpsFromOrigin | integer | 0 | Requires origin. When > 0, exclude candidates farther than N jumps (uses high-sec-only distance if avoidLowsec is set). |
| excludeIncursions | boolean | false | Exclude candidates in active Sansha incursion systems |
| limit | integer | 100 | Max results (capped at 500) |
// GET /api/systems/orescouting?tier=1®ion=Sinq+Laison&limit=2
{
"systems": [
{
"system_id": 30002718,
"system_name": "Ney",
"security_status": 0.4712, // raw
"security_status_display": 0.5, // ceil(raw*10)/10
"region": "Sinq Laison",
"constellation": "Alselbosier",
"tier": "Tier 1",
"score": 125,
"candidate_reasons": [
"0.5 high-sec adjacent to low-sec",
"Security 0.5",
"NPC station (logistics)"
],
// Neighbor breakdown
"lowsec_neighbors": [
{ "system_id": 30002719, "system_name": "Deltole", "security_status": 0.398 }
],
"highsec_neighbors": [
{ "system_id": 30002717, "system_name": "Carirgnottin", "security_status": 0.614 }
],
// Topology
"topology_type": "pipe",
"gate_count": 2,
"bottleneck_score": 48.2,
"has_npc_station": true,
"hub_distance": 6, // gate jumps to nearest trade hub
// Activity (30-day historical)
"consistency_score": 12, // % of last 30 days that were quiet
"quiet_days_30": 4,
"avg_daily_jumps_30d": 284.1,
"avg_daily_kills_30d": 1.2,
"weighted_activity_score": 8.4,
"activity_score": 14.2,
"currently_quiet": true,
"quiet_until_hour": 17, // UTC hour the quiet window ends
"incursion_active": false,
// Only when ?origin= is provided
"jumps_from_origin": 9, // fastest route; null = unreachable
"fastest_lowsec_jumps": 2, // low-sec systems on the fastest route
"safest_jumps_from_origin": 12, // least-low-sec route length
"safest_lowsec_jumps": 0, // low-sec systems even the safest route must cross
"safe_jumps_from_origin": 12, // all-high-sec route; null = none exists
"route_crosses_lowsec": true // fastest route uses low-sec gates
}
],
"total": 6,
"tier_counts": {
"Tier 1": 82,
"Tier 2": 92,
"Tier 3": 1072
}
}
Pochven Market Seeding
Returns market seeding opportunities for all 27 Pochven systems, ranked by
opportunity_score.
Each row represents one item in one system. Scoring combines ESI market data (Jita 4-4
reference price, local Pochven sell orders) with zKillboard activity (recent killmails,
doctrine ship losses, observed item drops) to identify scarce, high-margin items in
active systems.
Results are cached in PostgreSQL. On first call, or when the snapshot is older than
maxAgeMinutes,
a fresh build is triggered automatically (takes ~20–40 s while ESI and zKill are queried).
| Component | Weight | Source |
|---|---|---|
| activity_score | demand proxy | ESI jumps (28%) + PvP kills (34%) + NPC kills (22%) + zKill count (16%) |
| doctrine_relevance | item fit | Tag match against inferred doctrine (pvp/pve/dictor/cruiser…) + direct item loss count from zKill |
| scarcity_score | supply gap | max(0, 1 − local_orders / target_order_count) per category |
| margin_score | profit | Suggested sell vs Jita 4-4 sell; targets 35% markup, fallback 45% if no local orders |
| confidence_score | data quality | Additive bonus for having Jita reference price, zKill data, ESI activity, local orders |
| logistics_risk | penalty | Per-clade constant: Svarog 0.28, Perun 0.34, Veles 0.38 |
| overstock_penalty | penalty | Applied when local orders exceed 2× the category target |
| Call | Threshold |
|---|---|
| seed now | opportunity_score ≥ 9 AND confidence_score ≥ 0.55 |
| watch | opportunity_score ≥ 3.5 (below seed now threshold) |
| avoid | opportunity_score < 3.5 |
| Name | Type | Default | Description |
|---|---|---|---|
| system | string | — | Filter to a single Pochven system by name (case-insensitive, e.g. Skarkon) |
| category | string | — | Filter to an item category: ammo, consumables, drones, tackle, tank, scanning, propulsion, deployables, bubbles |
| recommendation | string | — | Filter by call: seed now, watch, or avoid |
| minScore | number | 0 | Minimum opportunity_score (0–100) |
| limit | integer | 100 | Max results (1–1000) |
| maxAgeMinutes | integer | 60 | If the latest snapshot is older than this, a fresh build is triggered automatically (1–1440) |
| windowHours | integer | 24 | zKillboard lookback window in hours when building a new snapshot (1–168) |
| force | boolean | false | Pass true to force a fresh build regardless of snapshot age |
// GET /api/pochven/opportunities?system=Senda&category=bubbles&limit=1
{
"snapshot": {
"id": 1,
"completed_at": "2026-06-29T16:41:34.880Z",
"status": "success",
"source_window_hours": 24,
"item_count": 27,
"system_count": 27
},
"opportunities": [
{
"system_id": 30020141,
"system_name": "Senda",
"clade": "Krai Veles",
"type_id": 41041,
"item_name": "Warp Disrupt Probe",
"category": "bubbles",
"recommendation": "seed now",
"suggested_quantity": 277,
// Pricing (null if no orders found)
"jita_sell_price": "87300",
"jita_buy_price": "76200",
"local_sell_price": null, // no public sell orders in this system
"local_order_count": 0,
"suggested_sell_price": "126585",
"estimated_margin_pct": 45.0,
// Scores (all 0–1 except opportunity_score which is 0–100)
"opportunity_score": 42.30,
"activity_score": 0.812,
"scarcity_score": 1.000,
"margin_score": 1.000,
"doctrine_relevance": 0.640,
"confidence_score": 0.900,
"logistics_risk": 0.380,
"overstock_penalty": 0.000,
// Evidence (from ESI + zKillboard)
"evidence": {
"jumps": 214,
"ship_kills": 8,
"pod_kills": 3,
"npc_kills": 1842,
"zkill_killmails": 12,
"matched_tags": ["universal", "pvp", "dictor"],
"observed_item_losses": 0,
"local_sell_volume": 0,
"sample_killmails": [{ "killmail_id": 123456789, "zkb": {}, "killmail_time": "2026-06-29T14:22:00Z" }],
"confidence_notes": [
"Jita 4-4 sell reference found",
"No Pochven local sell order observed",
"Pochven structure-market visibility may be incomplete through public ESI"
]
}
}
],
"total": 1,
"systems": [
{ "system_id": 30020141, "name": "Senda", "clade": "Krai Veles" }
/* … all 27 Pochven systems … */
],
"scoring_config": {
"desiredMarginPct": 35,
"fallbackMarkupPct": 45,
"logisticsRisk": { "Krai Svarog": 0.28, "Krai Perun": 0.34, "Krai Veles": 0.38 }
}
}
Immediately triggers a new market data build, bypassing the snapshot age check. Hits ESI market endpoints for all 27 items and fetches zKillboard for all 27 systems. Expect 20–40 seconds. The new snapshot is stored in the database and returned.
Auth & limits: when the server sets POCHVEN_REFRESH_TOKEN, this
endpoint requires a matching X-Refresh-Token header. It is rate-limited to 2 requests/hour,
honours a 10-minute minimum rebuild interval (returns the existing snapshot if fresher), and dedupes
concurrent rebuilds.
| Field | Type | Default | Description |
|---|---|---|---|
| windowHours | integer | 24 | zKillboard lookback window (1–168 hours) |
| limit | integer | 250 | Max opportunities to persist (1–1000) |
{
"snapshot_id": 2,
"systems": 27,
"items": 27,
"opportunities": [ /* … full opportunity array … */ ]
}
Returns the current opportunity snapshot as a downloadable CSV file.
Accepts the same filter parameters as GET /pochven/opportunities
(system, category, recommendation, minScore, limit).
Content-Type is text/csv; browsers will prompt a download.
system, clade, item, category, recommendation, quantity,
jita_sell, local_sell, suggested_sell, margin_pct, score, confidence
Stats
Returns a 7-day rolling summary of hourly data collection runs: success rate, systems collected, and recent run history.
{
"total_runs": 168,
"successful_runs": 166,
"failed_runs": 2,
"success_rate": 98.8,
"avg_systems_collected": 4891,
"recent_runs": [
{
"start_time": "2026-06-23T04:00:00.000Z",
"end_time": "2026-06-23T04:27:14.000Z",
"status": "success",
"systems_collected": 4893
}
]
}