Quickstart
One URL. No setup.
Use the global market and request no more than 100 rows per page. Continue increasing offset until a page contains fewer rows than limit.
const url = new URL("https://market-api.spiritvalers.com/v2/markets/global/listings");
url.search = new URLSearchParams({
snapshot: "2",
sort: "price-asc",
limit: "100",
offset: "0"
});
const response = await fetch(url);
if (!response.ok) throw new Error(`ValeMarket ${response.status}`);
const snapshot = await response.json();
Authorization header. The contributor upload token is a separate credential and is not a developer API key.Endpoints
Read the market.
/v2/markets/{marketId}/listingsCurrent listingsReturns confirmed, fresh observations across the market. Use global as the current market ID.
minPriceMinimum unit pricemaxPriceMaximum unit pricestatStat name filtersortprice-ascorprice-descoffset0–100,000limit1–100; default 50snapshotCurrent browser contract:2
/v2/markets/{marketId}/items/{itemType}/{itemId}One itemReturns current observations for one numeric item type and item ID. It accepts the same filters and pagination parameters as the market listing route.
/v2/markets/global/items/1/Flax?limit=100
/v2/markets/{marketId}/items/{itemType}/{itemId}/historyObservation historyReturns up to 100 confirmed historical observations for one item. This endpoint does not accept query parameters.
/v2/markets/global/items/1/Flax/history
/healthService healthReturns service status and the current observation protocol version. Use this for diagnostics, not frequent polling.
{"status":"ok","protocolVersion":2}Response
Fields that matter.
Listing responses contain marketId, generatedAt, and a listings array. Item routes also echo itemType and itemId.
| Field | Type | Meaning |
|---|---|---|
| generatedAt | ISO 8601 | When this cached API snapshot was generated. |
| listingKey | string | Stable public identity for the observed listing. |
| itemType / itemId | integer / string | Spirit Vale item identifiers. |
| displayName | string | null | Observed display name when available. |
| unitPrice / quantity | integer | Observed unit price and quantity. |
| stats | array | Public item roll fields: type, optional name/value, and percent flag. |
| firstSeenAt / lastSeenAt | ISO 8601 | Bounds of confirmed observation time. |
| expiresAt | ISO 8601 | null | Known listing expiry. Filter rows where this time has passed. |
Freshness
Share the snapshot.
Cloudflare caches public responses for 15 minutes. The snapshot limits database work and gives every integration a consistent view of recently confirmed observations.
- Honor
Cache-ControlandETag. Do not add cache-busting query values or poll faster than the shared snapshot interval. - Use
generatedAtfor snapshot age. Your local request time does not describe data freshness. - Filter
expiresAtlocally. A listing can expire during the 15-minute cache window. - Treat rows as observations, not sales. ValeMarket does not report completed transactions or guarantee that a listing remains available.
Errors
Handle status, then JSON.
| Status | Meaning | Action |
|---|---|---|
| 304 | Not modified | Reuse the representation associated with your ETag. |
| 400 | Invalid path or query | Read the JSON error and correct the request. |
| 404 | Unknown route | Check the endpoint and path identifiers. |
| 429 | Traffic limited | Back off. Do not rotate addresses or add cache-busting parameters. |
| 503 | Reads temporarily disabled | Honor Retry-After when present. |
Developer access
Building something public?
Tell us what you are integrating and the traffic you expect. Reads remain keyless during preview; access requests help shape managed keys, quotas, and change notifications before they become necessary.