Skip to content

Withdraw the offer

DELETE
/marketplaces/links/{server_id}/{marketplace}/offer
curl --request DELETE \
--url https://api.flotera.com/api/v1/marketplaces/links/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/vast/offer \
--cookie __Host-erm_session=<__Host-erm_session>

The machine leaves the search results. Rentals already running continue to their end — their terms were frozen when they were signed.

server_id
required

UUID (v7 for new entities; v4 accepted during migration).

string format: uuid
marketplace
required

Supported marketplace. The database constrains the same two values, so a third one is a migration rather than a new string.

string
Allowed values: vast clore

Marketplace identifier. Closed set: adding one is a migration, not a new string, because the database constrains the same two values.

Idempotency-Key
string
>= 1 characters <= 128 characters /^[\x21-\x7E]{1,128}$/

Idempotency key, 1–128 ASCII, unique per (tenant_id, operation, key) for at least 24 hours. Retrying with the same body replays the stored response; a different body returns 409 idempotency_conflict.

Withdrawn; the link carries the platform’s new state.

Media typeapplication/json
object
server_id
required

UUID (v7 for new entities; v4 accepted during migration).

string format: uuid
marketplace
required

Supported marketplace. The database constrains the same two values, so a third one is a migration rather than a new string.

string
Allowed values: vast clore
external_machine_id
required
string
<= 128 characters
bind_mode
required

How the link was established. agent is not produced by anything yet: automatic binding needs an agent on the machine.

string
Allowed values: manual agent
state
required

stale means the machine stopped appearing in the marketplace response. The link is kept, not deleted: a manual binding was approved by a person, and a machine delisted for an hour will come back.

string
Allowed values: linked stale conflict
linked_at
required

RFC 3339 UTC with microsecond precision.

string format: date-time
last_seen_at

RFC 3339 UTC with microsecond precision, or null.

string | null format: date-time
remote

What the marketplace knows about this machine, normalised. The raw answer is stored as the platform sent it — a foreign format changes without notice, and parsing it on the way in would silently drop fields nobody has thought about yet. What travels here is a normalised projection, so that a client never learns that on Vast the price is called listed_gpu_cost. Every field may be null, and that is ordinary rather than a fault: an unlisted machine has no prices at all, an unverified one has no scores yet, and a field the platform did not send is not a zero.

object
listed
boolean | null
verification
string | null
<= 32 characters
hostname

The hostname the machine reported to the platform.

string | null
<= 256 characters
reliability

A fraction, not a percentage: 0.7745 means 77.45 %. Left unrounded on purpose — the platform’s own threshold sits at 95 %, and rounding here would cost the owner the difference between 95 and 94.6.

number | null
rentals_running
integer | null
gpu_name

The card as the PLATFORM names it — RTX 3060, not NVIDIA GeForce….

string | null
<= 128 characters
gpu_count
integer | null
gpu_occupancy

Card occupancy, one character per card, exactly as the platform prints it. Undocumented on their side, so a string whose length disagrees with the card count means “not understood” and the card map is not drawn at all — an invented layout is worse than none.

string | null
<= 64 characters
gpu_model

The same card as the key of MarketSummary.gpu_model, so that the matching market row can be found. Normalised on the server: a name normalised twice by different rules stops matching itself, and the comparison against the market would then silently read as “no data” instead of a price.

string | null
<= 128 characters
price_gpu_hour

Decimal string or null when unknown.

string | null
/^-?[0-9]+(\.[0-9]{1,6})?$/
min_bid_hour

Decimal string or null when unknown.

string | null
/^-?[0-9]+(\.[0-9]{1,6})?$/
price_storage_gb_month

Decimal string or null when unknown.

string | null
/^-?[0-9]+(\.[0-9]{1,6})?$/
price_inet_up_tb

Per TERABYTE. The platform’s API carries this per gigabyte and its own CLI multiplies by 1024 before printing. The conversion lives on the server side so that exactly one place remembers the factor — getting it wrong is a thousandfold error in a price.

string | null
/^-?[0-9]+(\.[0-9]{1,6})?$/
price_inet_down_tb
string | null
/^-?[0-9]+(\.[0-9]{1,6})?$/
min_gpu_count
integer | null
discount_max
number | null
end_date

For a ROLLING offer this is a derivative, not the owner’s intent: the platform keeps it equal to now + duration and moves it constantly. Whether the offer is rolling is told by ask_duration_seconds.

string | null
<= 64 characters
ask_duration_seconds

The offer’s rolling window in seconds; null when the term is a fixed end date. An offer whose window is shorter than a day is filtered out by most renters’ searches.

number | null
earnings_day

Decimal string or null when unknown.

string | null
/^-?[0-9]+(\.[0-9]{1,6})?$/
earnings_hour

Decimal string or null when unknown.

string | null
/^-?[0-9]+(\.[0-9]{1,6})?$/
gpu_lanes

The hardware as the PLATFORM sees it, kept alongside our own measurements on purpose: a disagreement means the machine is being advertised as something it is not.

integer | null
pcie_bandwidth_gbs
number | null
inet_up_mbps
number | null
inet_down_mbps
number | null
direct_port_count
integer | null
maintenance_announced

Whether a maintenance window is announced. A flag of its own rather than something inferred from the dates: the platform’s record shape can change without us, and “is a window announced” must still have an answer when the details cannot be read.

boolean
maintenance_starts_at
string | null format: date-time
maintenance_hours
number | null
error

What the platform considers broken. Null means no complaint.

string | null
<= 512 characters
rentals

Rentals running right now, one entry per order, as the marketplace describes them. Empty when idle or when the platform gives no per-order breakdown (Vast). The counter above answers “how many cards”; this answers what the tenant actually pays — and on Clore the currency decides the host surcharge.

Array<object>
object
kind
required

Order type in the platform’s own word — on_demand, spot, fixed_usd.

string | null
<= 32 characters
currency
required
string | null
<= 32 characters
price_day
required

Order price per day, in the order’s own currency — not converted.

string | null
/^-?[0-9]+(\.[0-9]{1,6})?$/
gpu_count
required
integer | null
ends_at
required
string | null format: date-time
clore
One of:

What the owner set in Clore’s own console. Mostly read-only: the platform exposes no write for these, and guessing intent costs more than showing the fact and naming where it is changed.

The exception is the currency set, which the offer editor DOES change: set_server_settings honours enabled-<currency> when the currency’s own prices travel with it. That was found live on 2026-08-12 — until then we told owners the set was console-only, which was wrong.

Every field is nullable — the config call may not have answered, and a dash is more honest than an invented default.

object
max_rental_hours
required

Ceiling on a single rental, hours (mrl). Absent from the machine list.

integer | null
partial_rental
required

Whether renters may take part of the cards. False means whole machine only.

boolean | null
vpn
required
boolean | null
partner
required
boolean | null
overclock
required

Whether the renter is allowed to move clocks.

boolean | null
update_channel
required
string | null
<= 32 characters
backend_version
required
integer | null
target_backend_version
required

Version the chosen channel expects; a gap means their agent is behind.

integer | null
driver_status
required
string | null
<= 32 characters
driver_version
required
string | null
<= 64 characters
kernel
required
string | null
<= 128 characters
max_fair_price_day
required

The platform’s own quality estimate, USD per day. Not decorative: the token-lock bonus is computed from it.

number | null
coins
required

Currencies the machine accepts.

Array<string>
fixed_coins
required

Currencies whose price the owner pinned in the coin itself. A price edit here leaves them untouched.

Array<string>
coin_prices
required

Absolute prices per currency, in the currency itself. Not a reference: the absolute figure sent with a currency BEATS the dollar target, so the owner must see what will actually go to the platform in each — and the machine’s own rate is derived from these same numbers.

object
key
additional properties
object
on_demand
string
nullable
spot
string
nullable
spot
required
One of:
object
bids
required

Renter bids on this machine. An empty array means nobody is bidding — an observation, not a gap. As of 2026-08-12 no machine on the platform had any, so the shape of a non-empty entry comes from the vendor docs rather than a live body, and every field is optional on purpose.

Array<object>
object
offer_id
required
integer | null
bid
required
One of:

Decimal value serialized as a string, never a JSON number.

string
/^-?[0-9]+(\.[0-9]{1,6})?$/
currency
required
string | null
<= 32 characters
active
required
boolean
mine
required
boolean
rates_usd_per_coin
required

The platform’s own currency table, USD PER COIN — the inverse of a coins-per-dollar rate. These are the figures revenue in a deal currency is now converted with, so the owner is entitled to see the rate they were charged at.

object
key
additional properties

Decimal value serialized as a string, never a JSON number.

string
/^-?[0-9]+(\.[0-9]{1,6})?$/
best_bid_usd
required
One of:

Decimal value serialized as a string, never a JSON number.

string
/^-?[0-9]+(\.[0-9]{1,6})?$/
electricity_usd_per_gpu_hour

Measured electricity cost of one GPU-hour on this machine — billing facts over the last 7 days (energy integrated from power telemetry, up to a wall-plug meter, times the owner’s tariff), divided across the machine’s cards. This is the break-even floor a price must clear. null means it cannot be computed — no tariff, no power measurements, or no card count — and an unknown cost is never presented as zero. Computed by the links list; single-link responses (bind, offer edits) return null.

string | null
/^-?[0-9]+(\.[0-9]{1,6})?$/
Example
{
"marketplace": "vast",
"bind_mode": "manual",
"state": "linked",
"linked_at": "2026-07-25T10:15:30.123456Z",
"remote": {
"clore": {
"spot": {
"bids": [
{
"bid": "12.340000"
}
],
"rates_usd_per_coin": {
"additionalProperty": "12.340000"
},
"best_bid_usd": "12.340000"
}
}
}
}

Missing/invalid credentials (code=unauthorized).

Media typeapplication/problem+json

RFC 9457 problem document with a stable machine code.

object
type
required
string format: uri
title
required
string
<= 256 characters
status
required
integer
>= 100 <= 599
code
required

Stable machine-readable error code (03 §2.4).

string
Allowed values: unauthorized forbidden csrf_rejected not_found conflict idempotency_conflict validation_failed rate_limited payload_too_large unsupported_agent_version temporarily_unavailable offline_queue_full online_queue_full plan_required server_limit_reached feature_not_entitled account_in_grace account_frozen payment_pending payment_expired payment_amount_mismatch change_already_pending change_already_applied change_effective reserve_not_covered direction_changed
detail
string
<= 2048 characters
instance
string
<= 512 characters
request_id

UUID (v7 for new entities; v4 accepted during migration).

string format: uuid
errors
Array<object>
<= 100 items
object
path
required

JSON Pointer to the offending field.

string
<= 512 characters
code
required
string
<= 64 characters
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).

Media typeapplication/problem+json

RFC 9457 problem document with a stable machine code.

object
type
required
string format: uri
title
required
string
<= 256 characters
status
required
integer
>= 100 <= 599
code
required

Stable machine-readable error code (03 §2.4).

string
Allowed values: unauthorized forbidden csrf_rejected not_found conflict idempotency_conflict validation_failed rate_limited payload_too_large unsupported_agent_version temporarily_unavailable offline_queue_full online_queue_full plan_required server_limit_reached feature_not_entitled account_in_grace account_frozen payment_pending payment_expired payment_amount_mismatch change_already_pending change_already_applied change_effective reserve_not_covered direction_changed
detail
string
<= 2048 characters
instance
string
<= 512 characters
request_id

UUID (v7 for new entities; v4 accepted during migration).

string format: uuid
errors
Array<object>
<= 100 items
object
path
required

JSON Pointer to the offending field.

string
<= 512 characters
code
required
string
<= 64 characters
Example
{
"type": "https://ermeon.com/problems/validation",
"code": "unauthorized"
}

Resource does not exist in this tenant. Foreign identifiers also return 404 (anti-enumeration).

Media typeapplication/problem+json

RFC 9457 problem document with a stable machine code.

object
type
required
string format: uri
title
required
string
<= 256 characters
status
required
integer
>= 100 <= 599
code
required

Stable machine-readable error code (03 §2.4).

string
Allowed values: unauthorized forbidden csrf_rejected not_found conflict idempotency_conflict validation_failed rate_limited payload_too_large unsupported_agent_version temporarily_unavailable offline_queue_full online_queue_full plan_required server_limit_reached feature_not_entitled account_in_grace account_frozen payment_pending payment_expired payment_amount_mismatch change_already_pending change_already_applied change_effective reserve_not_covered direction_changed
detail
string
<= 2048 characters
instance
string
<= 512 characters
request_id

UUID (v7 for new entities; v4 accepted during migration).

string format: uuid
errors
Array<object>
<= 100 items
object
path
required

JSON Pointer to the offending field.

string
<= 512 characters
code
required
string
<= 64 characters
Example
{
"type": "https://ermeon.com/problems/validation",
"code": "unauthorized"
}

Request failed validation (code=validation_failed), with per-field errors.

Media typeapplication/problem+json

RFC 9457 problem document with a stable machine code.

object
type
required
string format: uri
title
required
string
<= 256 characters
status
required
integer
>= 100 <= 599
code
required

Stable machine-readable error code (03 §2.4).

string
Allowed values: unauthorized forbidden csrf_rejected not_found conflict idempotency_conflict validation_failed rate_limited payload_too_large unsupported_agent_version temporarily_unavailable offline_queue_full online_queue_full plan_required server_limit_reached feature_not_entitled account_in_grace account_frozen payment_pending payment_expired payment_amount_mismatch change_already_pending change_already_applied change_effective reserve_not_covered direction_changed
detail
string
<= 2048 characters
instance
string
<= 512 characters
request_id

UUID (v7 for new entities; v4 accepted during migration).

string format: uuid
errors
Array<object>
<= 100 items
object
path
required

JSON Pointer to the offending field.

string
<= 512 characters
code
required
string
<= 64 characters
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.

Media typeapplication/problem+json

RFC 9457 problem document with a stable machine code.

object
type
required
string format: uri
title
required
string
<= 256 characters
status
required
integer
>= 100 <= 599
code
required

Stable machine-readable error code (03 §2.4).

string
Allowed values: unauthorized forbidden csrf_rejected not_found conflict idempotency_conflict validation_failed rate_limited payload_too_large unsupported_agent_version temporarily_unavailable offline_queue_full online_queue_full plan_required server_limit_reached feature_not_entitled account_in_grace account_frozen payment_pending payment_expired payment_amount_mismatch change_already_pending change_already_applied change_effective reserve_not_covered direction_changed
detail
string
<= 2048 characters
instance
string
<= 512 characters
request_id

UUID (v7 for new entities; v4 accepted during migration).

string format: uuid
errors
Array<object>
<= 100 items
object
path
required

JSON Pointer to the offending field.

string
<= 512 characters
code
required
string
<= 64 characters
Example
{
"type": "https://ermeon.com/problems/validation",
"code": "unauthorized"
}