Skip to content

What the marketplaces say each machine earned, by day

GET
/marketplaces/earnings
curl --request GET \
--url 'https://api.flotera.com/api/v1/marketplaces/earnings?days=7' \
--cookie __Host-erm_session=<__Host-erm_session>

One row per machine, marketplace and UTC day, carrying the platform’s own rolling 24-hour figure as of the last sample of that day.

This is not a ledger and not the money contour. It is somebody else’s number, recorded as reported; Ermeon’s own money lives in billing and is computed differently. Because the platform’s window rolls, a sum over several days is an estimate, and any total built from these rows must be labelled as coming from the marketplace.

samples says how many times the day was sampled. A day sampled once at noon describes half a day.

collected_since is the earliest day on record, and null when there is none. Without it an empty chart is unreadable: “earned nothing” and “not recorded yet” both render as blank space and lead opposite ways.

accrued_since is the earliest day the accrual itself ran. A row is also written by the platform-report path, which predates the accrual, so a row does not mean the day was watched — accrued_seconds does. A reader that draws price × time must date and mark it by this field, or it will report an unmeasured day as a measured zero.

days
integer
default: 7 >= 1 <= 90

Window length in days, inclusive of today.

Daily earnings as reported by the marketplaces.

Media typeapplication/json
object
days
required
integer
>= 1 <= 90
items
required
Array<object>
<= 8192 items

One machine, one marketplace, one UTC day — carrying TWO different sums. They are not interchangeable and must never be added together.

object
day
required
string format: date
server_id
required
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
earn_usd_day

What the platform itself reported for the day, AFTER its cut. Null when the platform said nothing; Clore publishes no such report at all, so this stays null there forever.

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

Our own count: the price of the running deals multiplied by the time they ran, BEFORE the platform’s cut. Computed identically on both marketplaces — a fleet total must be summed from this field, because the field beside it means one thing on Vast and nothing on Clore. The difference between the two is the platform’s cut plus downtime we did not observe.

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

Rented seconds behind earn_usd_accrued. Without it $0.05 over a day and $0.05 over an hour read the same.

integer
accrual_gap_seconds
required

Seconds of a KNOWN-RUNNING rental that could not be counted because sync stayed silent past its cap. Non-zero means earn_usd_accrued is understated by exactly this much time.

integer
samples
required

How many times this day was sampled.

integer
>= 1
by_currency
required

WHICH CURRENCIES the accrual arrived in, and what they were worth at the moment we accrued them. Empty for two DIFFERENT kinds of day, told apart by earn_usd_accrued: an idle day has zero (no deals, so no currency), a day accrued before the breakdown existed has a non-zero sum (there was a currency, we just did not write it down). The second cannot be re-priced at any rate, and showing it as zero coins would erase money that was earned.

Array<object>

What one deal currency brought in over one day.

object
currency
required

The marketplace’s own spelling — the same string the commission rate is keyed by.

string
amount
required

Coins. A MEASUREMENT: no rate went into it and it will never change. Twelve decimals because a two-minute slice of a bitcoin rental is smaller than a satoshi.

string
/^[0-9]+(\.[0-9]{1,12})?$/
usd
required

The same money at THE RATE OF THE MOMENT WE ACCRUED IT. “What we earned then” and “what it is worth now” are different questions; this answers the first, and amount with a current rate answers the second.

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

Earliest day on record; null when nothing has been recorded. Tells “earned nothing” apart from “not recorded yet”.

string | null format: date
accrued_since
required

Earliest day our own accrual actually ran (accrued_seconds > 0); null when it never has. Not the same as collected_since: a row is also created by the platform’s report, a path older than the accrual, and those days carry accrued_seconds = 0. Charting price × time and dating it by collected_since declares days watched that the accrual never saw.

string | null format: date
current_rates
required

Marketplace rates AS OF NOW, so the screen can answer “what is the earned money worth today”. A different number from usd inside the breakdown, which froze the rate of the accrual moment. A currency absent here is not converted at all: substituting someone else’s rate is the same as inventing money.

Array<object>

What one coin is worth in dollars RIGHT NOW, as the marketplace itself prices it. Not an exchange quote: this is the rate the platform uses to price the machine, and disagreeing with it would show the owner numbers their own dashboard does not have.

object
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
currency
required
string
usd_per_coin
required
string
/^[0-9]+(\.[0-9]{1,12})?$/
observed_at

When the snapshot carrying this rate was taken. Null for the dollar: nobody observes it, a dollar is a dollar.

string | null format: date-time
Example
{
"items": [
{
"marketplace": "vast",
"earn_usd_accrued": "12.340000",
"by_currency": [
{
"currency": "CLORE-Blockchain",
"amount": "10.750000000000",
"usd": "0.100000"
}
]
}
],
"current_rates": [
{
"marketplace": "vast",
"currency": "bitcoin",
"usd_per_coin": "63771.469876789735"
}
]
}

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"
}

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"
}