Where a price stands in its card class, and what is rented around it
const url = 'https://api.flotera.com/api/v1/marketplaces/market/ladder?marketplace=vast&gpu_model=example&price=example';const options = { method: 'GET', headers: {cookie: '__Host-erm_session=<__Host-erm_session>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://api.flotera.com/api/v1/marketplaces/market/ladder?marketplace=vast&gpu_model=example&price=example' \ --cookie __Host-erm_session=<__Host-erm_session>The spread between hosts at one moment is an order of magnitude wider than the median’s drift over time: the middle half of RTX 4090 on Vast spans 40%, RTX 3060 on Clore 70%, while the median moved 7–22% over nine days. So “the median is X” answers the wrong question, and “you are at p85 of your class” answers the right one.
The position is COUNTED over live offers — how many are strictly cheaper and how many exist. It is never interpolated between the quartiles of the overview: prices are distributed arbitrarily inside a quartile, and an interpolated “about p78” is invented precision that a reader will take for a measurement and price against.
bands splits the ladder into fifths and reports, per rung, how many
offers there are and how many are rented right now. rented_known is
how many of them said anything about being rented at all: zero means
the marketplace does not report occupancy, and the share is then
unknowable — not zero. Bands are absent below min_offers_for_bands.
This is a MEASUREMENT of the market as it stands, never a probability of being rented. On live data RTX 3080 runs 96 → 71 → 26 → 4 → 0 across the rungs while RTX 3090 runs 66 → 31 → 37 → 77 → 21 — the fourth rung busier than the second. Reliability, bandwidth and a single renter taking ten neighbours at once all decide it; the price does not.
reference carries the same rungs measured on the OTHER marketplace,
and only when this one reports no occupancy at all — as on Vast, where
the sample is filtered to free machines and not one offer carries the
flag. What transfers is the POSITION, not the dollar: the same price
sits on different rungs on different marketplaces. The field names its
marketplace because that measurement must not be merged with ours.
Read price_sample before reading the position: on Vast the ladder is
built from free machines only — which is to say, from exactly the
machines competing for the next renter.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”Supported marketplace. The database constrains the same two values, so a third one is a migration rather than a new string.
Card class; normalised the same way market sampling normalises it.
The price whose position is asked, $/GPU-hour, as a decimal string. Money never travels as a JSON number.
Responses
Section titled “Responses”The ladder and this price’s place on it.
object
Supported marketplace. The database constrains the same two values, so a third one is a migration rather than a new string.
Which population the ladder is built from. On Vast it is free machines only — the ones a renter can take instead of you.
Offers strictly cheaper than the asked price.
Place of the price, 0..100. Null when there are no offers at all — which is not “cheaper than everyone”, and leads elsewhere.
Rung the price falls on, 0-based. Null on a thin market.
object
Cheapest price on this rung. Adjacent rungs MAY share a bound: the ladder is cut by count, so equal prices land on two rungs.
How many offers on this rung said anything about being rented. Zero means the marketplace does not report occupancy at all — the share is then unknowable, and reading it as “none rented” is the error this field exists to prevent.
The same rungs measured on the other marketplace, present only when this one reports no occupancy. Position transfers, price does not.
object
Supported marketplace. The database constrains the same two values, so a third one is a migration rather than a new string.
object
Cheapest price on this rung. Adjacent rungs MAY share a bound: the ladder is cut by count, so equal prices land on two rungs.
How many offers on this rung said anything about being rented. Zero means the marketplace does not report occupancy at all — the share is then unknowable, and reading it as “none rented” is the error this field exists to prevent.
NOT a probability model and not a fitted curve — exactly the counters of bands, summed over the window. Persistent humps stay visible; only single-hour swings vanish. A machine that sat rented for a day honestly weighs 24 observations: rung occupancy over time is what is summed, not the fates of individual offers. Always measured on Clore, the one marketplace with a truthful per-offer rented; position transfers across marketplaces, dollars do not — never merge these numbers with the venue’s own.
object
Supported marketplace. The database constrains the same two values, so a third one is a migration rather than a new string.
object
Rung 1..5, cheap to expensive — storage numbering.
Offer-hours observed on the rung over the window.
Rented share among offers whose occupancy the venue reported, 4 decimal places. Null when it reported none — which is not zero.
Below this many offers the ladder has no rungs.
Example
{ "marketplace": "vast", "price_sample": "all", "reference": { "marketplace": "vast", "price_sample": "all" }, "history": { "marketplace": "vast" }}Missing/invalid credentials (code=unauthorized).
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}Authenticated but not permitted. code=forbidden — role/scope mismatch; code=feature_not_entitled — the plan does not include the capability; code=account_frozen — the account is frozen and this operation is declared x-ermeon-frozen: deny. The three are deliberately distinct: only the last one is fixed by a top-up (13 §5.6).
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}Request failed validation (code=validation_failed), with per-field errors.
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}A dependency the endpoint needs is not configured or is temporarily unavailable (code=unavailable). The rest of the API keeps working — an absent external integration must not take the service down.
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}