StarStock logo StarStockEVE Echoes tools

StarStock API

Free, read-only EVE Echoes market, contract, planet and star chart data from StarStock. No key, no sign-up.

In development. Endpoints and fields may change without notice. Offered as-is, with no uptime or accuracy guarantee.

Quick start

Base URL: https://api.starstock.app/api/v1

sell = the cheapest sell order (what you pay to buy now). buy = the highest buy order (what you get selling now). Jita prices are fields named cheapest_*; the best price in all regions is everywhere_*. Items are identified by type_id (Tritanium is 41000000000; find others with search).

Spreadsheets

Google Sheets

Load the market into an empty tab named Market (cell A1):

=IMPORTDATA("https://api.starstock.app/api/v1/items.csv")

Then look up a price by name from any other tab (A2 = item name). Column D is sell, E is buy, F is units for sale:

=INDEX(Market!D:D, MATCH(A2, Market!B:B, 0))

One item without a lookup tab (row 2, column 2 = sell; use column 3 for buy, 4 for units for sale):

=INDEX(IMPORTDATA("https://api.starstock.app/api/v1/items/41000000000.csv"), 2, 2)

Google refreshes IMPORTDATA on its own schedule (about hourly). Use one whole-market tab rather than many single-item formulas.

Excel

  1. Data → Get Data → From Other Sources → From Web, paste the link below, choose Anonymous if asked, then Load.
    https://api.starstock.app/api/v1/items.csv
  2. To keep it current: Data → Queries & Connections, right-click the query, Properties, tick Refresh every 10 minutes.
  3. Look up a price: =INDEX(items[cheapest_sell], MATCH(A2, items[name], 0)) (use the table name shown under Table Design).

Add ?scope=all to any CSV link for all-regions prices instead of Jita (the price columns are then named best_sell and best_buy).

Market endpoints

GET/items

Items with current prices, A to Z.

ParameterMeaning
limit, offsetPaging. limit 1 to 500 (default 100).
pathOnly items in one category (a path from /categories).
idsUp to 200 comma-separated type_ids, returned in that order.
live=1With ids: read the latest data instead of the list, which can be up to ~20 min behind.
GET /items?ids=41000000000,51000000006&live=1
GET/items/{type_id}

One item: current prices plus time-weighted averages over a window, and its estimate (see fields).

ParameterMeaning
window7d, 30d (default), 90d, 1y or all.
full=1Also include history for the window and a contracts summary: how many open contracts offer or want the item, and the cheapest one selling only this item (best.unit = ISK per unit incl. the 8% fee, best.id = contract_id), and typical: the item's sell_p10_30d / p50 / p90 / sell_src_30d plus sell_low_7d / everywhere_sell_low_7d (see fields).
{ "ok": true, "item": { "type_id": 51000000006, "name": "Rich Veldspar",
  "cheapest_sell": 28, "cheapest_buy": 25, "everywhere_sell": 26, "everywhere_buy": 25,
  "average_sell": 29.43, "average_buy": 25.4, "vol_jita": 4645133, "activity": "active", ... },
  "estimate": { "price": 26, "source": "market" } }
GET/items/{type_id}/history

Price points for one item, oldest first. A point is recorded when the price or units for sale changed. Takes window like above.

GET/history/days

Daily history files: every item's price points for one UTC day in one download. For the whole market's history, use these instead of one /history request per item. days = the dates with a file, newest first (about the last 4 weeks; a new day is added after 01:00 UTC).

{ "ok": true, "days": ["2026-10-11", "2026-10-10", ...],
  "fields": ["type_id", "ts", "cheapest_sell", ...], "url": "/api/v1/history/day/{date}" }
GET/history/day/{date}

One day's file ({date} = YYYY-MM-DD). points is a list of arrays in the order of fields: type_id, ts (Unix seconds), cheapest_sell, cheapest_buy, everywhere_sell, everywhere_buy, highest_sell, everywhere_highest_sell, vol_jita, vol_all. Like /history, a point is recorded only when something changed, so an item with no point that day kept its earlier price. A finished day never changes, so a file only needs downloading once.

{ "ok": true, "day": "2026-10-11", "fields": [...],
  "points": [[51000000006, 1791676800, 28, 25, 26, 25, 31, 31, 4645133, 9022871], ...] }
GET/items/{type_id}/orders

The order book: sell (cheapest first) and buy (highest first), each { price, qty, ss, rg, j } = price, quantity, solar system id, region id, and j: 1 if the order counts as Jita. fetched_at = when the book was read.

The game shows at most ~220 sell orders per item, so very deep items (Tritanium, PLEX) are cut off at the expensive end. The buy side is complete. A book is re-read when the price moves, and at least every 24 hours.

GET/recent

Items whose price changed most recently. limit 1 to 150 (default 150).

GET/categories

The market's category tree, with the number of items in each category and its path.

GET/catalog.json

Every item in one compact response (about 1.7 MB), with short keys:

KeyMeaningKeyMeaning
itype_idnname
cs / cbJita sell / buyes / ebAll-regions sell / buy
vj / vaUnits for sale, Jita / all regionsicicon id
lj / laLowest sell in 7 days, Jita / all regionsq1 / q5 / q930-day typical sell price (see fields)
qsSource of q1-q9: j Jita, a all regions
GET/items.csv  ·  /items/{type_id}.csv

The whole market, or one item, as CSV. Columns: type_id (whole market only), name, path (whole market only), cheapest_sell, cheapest_buy, volume (units for sale), last_updated, estimated_price (the estimate price; empty = none). ?scope=all switches to all-regions prices; ?ids= (up to 200) limits items.csv to those items.

GET/meta

Number of items tracked and when data last came in (last_updated).

Contract endpoints

Public contracts from across New Eden. New contracts appear within minutes; accepted or cancelled ones are removed within about 30 minutes. Sellers are shown as an anonymous code (seller), the same code for all of one seller's contracts. The accepter pays price plus an 8% fee.

GET/contracts

Every open public contract, newest first (about 600 KB). ?type_id= keeps contracts that include that item; ?id= returns one contract.

{ "ok": true, "count": 591, "contracts": [ { "contract_id": 26259894, "type": 1,
  "seller": "07fcc10f48f0", "price": 160000000, "date_expired": 1790757677,
  "start_solar_system_id": 30004381, "items": [ { "t": 61999001320, "q": 1, "r": 0, "f": 0 } ], ... } ] }
GET/contract-sales

Contracts completed (accepted) in the last 60 days, newest first. sold_at = when StarStock saw it completed.

GET/contract-asks

Contracts that ended without a sale in the last 60 days (ended: expired or removed), newest first. Only contracts with up to 12 item lines that include at least one item with no market price are kept.

Planetary industry

Planets with resources and how much each one yields, from the game's own data. Resources are market items, so their prices come from the market endpoints.

GET/planets

Planets matching at least one filter. With resource, the planets with the most output of it come first; otherwise they are in system order.

ParameterMeaning
resourceA resource's type_id or name, e.g. Lustering Alloy.
systemA solar system's id or name.
region, constellationA region or constellation name.
limit, offsetPaging. limit 1 to 500 (default 100). total = how many planets matched.
GET /planets?resource=Lustering%20Alloy&region=The%20Forge&limit=1
{ "ok": true, "total": 409, "planets": [ { "name": "Fuskunen III", "planet_type": "Gas",
  "system_id": 30000199, "system": "Fuskunen", "security": 0.2, "true_security": 0.23,
  "constellation": "Mivora", "region": "The Forge", "jumps_from_jita": 15, "wormhole": false,
  "output_bonus": 1.8, "resources": [ { "type_id": 42001000000, "name": "Lustering Alloy",
  "richness": "Perfect", "output": 29.74 }, ... ] } ] }

Star chart

The map and live layers behind the Star Chart, read from the game. Systems are solar_system_ids. Kills, strongholds, Malpais, cyno and Sansha refresh about every 10 minutes; the other layers about every 3 hours. Each layer has its own at time (UTC).

GET/starmap/systems

Every system on the star chart (about 1.4 MB), with regions, constellations, faction names and NPC station names. x, y = position on the 2D chart; ly = 3D position in light-years. gates = the systems its stargates lead to. faction_id 0 = none. off_chart_stations = stations in systems the chart doesn't draw.

{ "ok": true, "regions": [ { "id": 10000001, "name": "Derelik" }, ... ],
  "constellations": [ { "id": 20000001, "name": "San Matar", "region_id": 10000001 }, ... ],
  "factions": { "500001": "Caldari State", ... },
  "systems": [ { "id": 30000001, "name": "Tanoo", "region_id": 10000001, "constellation_id": 20000001,
    "true_security": 0.8583, "faction_id": 500007, "x": 0.01896, "y": -0.07305, "ly": [-9.3556, 4.4785, -4.7051],
    "stations": [ "Tanoo IV - Trust Partners Trading Post", ... ], "gates": [ 30000003, ... ] }, ... ],
  "off_chart_stations": [ { "name": "...", "system": "0IRK-R" }, ... ] }
GET/starmap/borders

Each region's outline on the 2D chart, as lists of [x, y] points in the same coordinates as /starmap/systems (about 700 KB).

{ "ok": true, "regions": { "10000001": [ [ [0.1308, -0.0963], [0.1336, -0.0938], ... ] ], ... } }
GET/starmap/live

The latest reading of every layer.

{ "ok": true, "received_at": "2026-10-10T21:57:26.992Z", "layers": {
  "kills1h": { "at": "2026-10-10T21:57:26Z", "data": [ [30000195, 11], ... ] },
  "sov": { "at": "2026-10-10T19:40:35Z", "data": { "30000208": [0, 1000022908, 2000000675], ... } }, ... } }
Layerdata
kills1h[[system, ships destroyed]] in the last hour.
kills24h[[system, ships destroyed]] in the last 24 hours.
strongholds[[system, level]]: pirate strongholds destroyed today as the game's level since 2026-10-15 (1 = 1-50, 2 = 51-100, 3 = 101-150, 4 = 151-200, 5 = over 200; before that, the count). The game resets it at 00:00 UTC.
strongholds_est[[system, estimate]]: our estimate of today's count per system, from when each system reached each level (since 2026-10-15).
malpais[[system, count]] from the game's [Malpais] High-activity systems filter.
cyno[system] with cyno beacons.
sansha{ "incursions": [[constellation, race, end_at]], "boss_systems": [system] }
ansiblexAnsiblex jump bridges: [[from, to, from_alliance, to_alliance, from_corp, to_corp]].
keepstars[system] with a Keepstar.
sovSovereignty: { system: [faction, corp, alliance] }. 0 = none.
colors{ owner id: "#rrggbb" }, the game's map colour for each sov owner.
alliances{ id: [ticker, name, logo, members] }. logo = the game's logo codes.
corps{ id: [ticker, name, logo, members] }.
GET/starmap/snapshots

Days with a saved daily copy of the layers.

{ "ok": true, "dates": [ "2026-10-07", "2026-10-08", ... ] }
GET/starmap/snapshot/{date}

One day's copy (YYYY-MM-DD, UTC), same shape as /starmap/live plus date. HTTP 404 for a day with no copy.

GET/starmap/ratting

Pirate strongholds destroyed in each sov owner's systems (the Rat Board). The owner is the system's sov alliance, else its sov corp.

{ "ok": true, "today": "2026-10-10", "dates": [ "2026-10-09", "2026-10-10" ], "board": [ { "id": 2000000572,
  "kind": "alliance", "ticker": "SOS", "name": "...", "logo": [41, 20, 21, 1, 19, 19, 1], "members": 2602,
  "totals": { "today": 10645, "d3": 22323, "d7": 22323, "d30": 22323, "all": 22323 },
  "corps": [ [ "THDG", "...", [10, 5, 7, 19, 32, 19, 56, 0], 95, 1000023717 ], ... ] }, ... ],
  "corp_dates": [ "2026-10-11" ], "corp_board": [ { "id": 1000011193, "ticker": "THD", "name": "...",
  "logo": [10, 5, 7, 19, 32, 19, 56, 0], "members": 331, "alliance": [ 2000000572, "SOS", "..." ],
  "totals": { "today": 1229, "d3": 1229, "d7": 1229, "d30": 1229, "all": 1229 } }, ... ] }

totals: today so far, the last 3, 7 and 30 days (including today), and every day recorded (dates). corps (alliances only): member corps holding its systems now, as [ticker, name, logo, members, id].

corp_board: every corp holding sov systems (alliance members included), counting the systems it holds, over the days in corp_dates (per-corp counts start 2026-10-11). alliance: [id, ticker, name], or null for a corp without one.

top (every row): its 3 systems with the most strongholds destroyed per period, { "today": [[system, count], ...], "d3", "d7", "d30", "all" }, over the days in sys_dates (per-system counts start 2026-10-11).

GET/starmap/route

A route between two systems, worked out like the Star Chart's route finder. Systems and regions can be names (any case) or ids; lists are comma separated.

ParameterMeaning
fromStart system (required).
toDestination system (required).
safest1 = stay in high-sec (0.5 and up) where a way exists. Default: fewest jumps.
sec_minLowest security to pass through, -1 to 1. The start and destination always count.
sec_maxHighest security to pass through, -1 to 1.
avoid_systemsSystems never to pass through (up to 100).
avoid_regionsRegions never to pass through (up to 100).
ansiblex1 = also use Ansiblex jump bridges (both directions) from the latest ansiblex layer.
cyno1 = also jump to cyno beacons from the latest cyno layer, from systems below 0.45 true security. Needs ship = a ship that can fit a jump drive.
cyno_rangeJump range in light-years (0.1 to 50) instead of the ship's base range.
shipAny ship name: adds travel_time_s.
/starmap/route?from=Jita&to=Amarr&safest=1&ship=Rifter

{ "ok": true, "from": { "id": 30000142, "name": "Jita", "region": "The Forge" },
  "to": { "id": 30002187, "name": "Amarr", "region": "Domain" },
  "jumps": 9, "low_sec": 0, "null_sec": 0, "ship": "Rifter", "travel_time_s": 304,
  "steps": [ { "to": { "id": 30002187, "name": "Amarr" }, "via": "gate", "jumps": 9 } ],
  "route": [ { "id": 30000142, "name": "Jita", "region": "The Forge", "security": 0.9, "via": null },
    { "id": 30000144, "name": "Perimeter", "region": "The Forge", "security": 1, "via": "gate" }, ... ],
  "filters": { "safest": true, "sec_min": null, "sec_max": null, "avoid_systems": [], "avoid_regions": [],
    "ansiblex": false, "cyno_range": null },
  "star_chart_url": "https://starstock.app/starmap?route=30000142-30002187&safe=1" }

route: every system in order, with its security as the chart shows it (rounded to 0.1) and how it is reached: via gate, ansiblex or cyno (null for the start). steps: the autopilot steps, each run of stargate jumps as one step and each Ansiblex or cyno jump as its own. low_sec / null_sec: systems passed through (not the start) at 0.1 to 0.4 / 0.0 and below. travel_time_s: seconds, from the game's own formula with the ship's base stats (no skills), starting 30 AU from the first gate like the game; null without a ship or when the route has an Ansiblex or cyno jump. live (only with ansiblex or cyno): the at time of the layer used, null when none is newer than 12 hours. star_chart_url opens the same route on the Star Chart. The game's autopilot picks its own way between steps.

HTTP 400 for a missing or unknown system, ship or region, or a bad number; 404 when no route exists (with the filters given). Both answer { "ok": false, "error": "..." }.

Fields

Items

FieldMeaning
cheapest_sell / cheapest_buyBest Jita sell / buy price (ISK). null = no orders.
everywhere_sell / everywhere_buyBest sell / buy price in any region.
highest_sell, everywhere_highest_sellMost expensive listed sell order (item detail only).
vol_jita / vol_allUnits listed for sale, Jita / all regions. Supply, not units traded.
sell_order_countNumber of sell orders, all regions.
activityactive (6+ sell orders), low (2 to 5), minimal (1), no orders.
average_*Time-weighted average over the window (item detail only).
sell_high_7d / sell_low_7dHighest / lowest Jita sell price in the last 7 days (everywhere_sell_*_7d for all regions).
sell_p10_30d / p50 / p9030-day typical sell price: the price was at or below this 10% / 50% / 90% of the time. sell_src_30d: j Jita, a all regions.
estimateOn /items/{type_id} (next to item) and on every /items row: the Estimated price shown on the item page, as { "price", "source" }. source market = from market sell prices (the lower of the usual 30-day low and today's price). Items with no market price are estimated from contracts: contracts_sold = middle price of completed contracts, contracts_asking = the cheapest asking price on contracts (nobody has bought one yet), with count = how many contracts or sellers it's from. It switches back to market as soon as the item has market prices. null = no estimate.
last_updatedWhen the price last changed (ISO 8601, UTC).
last_checkedWhen the item was last read. Can lag up to ~45 minutes for an item whose price didn't change.
pathCategory, e.g. Manufacturing Materials > Minerals > minerals(10).
icon_urlRelative to https://starstock.app/. null = no icon.

Contracts

FieldMeaning
type1 item exchange, 2 auction.
seller, seller_corpAnonymous codes for the seller and their corporation.
priceISK the accepter pays (before the 8% fee). top_bid: highest bid on an auction.
rewardISK the accepter receives.
itemst type_id, q quantity, r: 1 = the seller wants this item in return, f: 1 = fitted inside another item in the contract.
date_issued, date_expiredUnix time in seconds. first_seen = when StarStock found it.
start_solar_system_idWhere the contract is. start_solar_system_name = its name (open contracts only).
descriptionThe seller's note (up to 200 characters).
volume, collateralSize in m³ and collateral (ISK).

Planets

FieldMeaning
name, planet_typePlanet name and type (Temperate, Barren, Oceanic, Ice, Gas, Lava, Storm or Plasma).
system_id, system, constellation, regionWhere the planet is.
security, true_securitySecurity status as the game shows it, and the exact value.
jumps_from_jitaStargate jumps from Jita. null = no stargate route from Jita (wormhole systems and a few far regions).
wormholetrue = in wormhole space.
output_bonusHow many times more this system's planets yield than the same planet at 1.0 security. Already included in output.
resourcestype_id, name, richness (Perfect, Rich, Medium or Poor) and output = units per hour per extraction array.

Limits & errors

Use of the API is covered by the terms. Questions or feedback: the StarStock Discord, linked from starstock.app.