Skip to content

Price a plan change without ordering it

GET
/subscription/quote
curl --request GET \
--url 'https://api.flotera.com/api/v1/subscription/quote?plan=example' \
--cookie __Host-erm_session=<__Host-erm_session>

The gate of 14 §3.2: one day of the target plan at the current fleet size, checked against the current balance. No consumption projection is involved. billing_effective_day follows the target plan’s change policy (same UTC day for upgrades by default).

Only an upgrade is gated. A downgrade is never blocked by balance — moving to a cheaper plan is exactly what a tenant short on money needs (14 §3.3), so covered is true for downgrade and lateral regardless of the balance.

plan
required

Internal catalog code. Not the public label — labels are not unique.

string
<= 64 characters /^[a-z][a-z0-9_-]{1,63}$/

Target plan code from GET /plans.

Quote.

Media typeapplication/json
object
target_plan
required

Internal catalog code. Not the public label — labels are not unique.

string
<= 64 characters /^[a-z][a-z0-9_-]{1,63}$/
current_plan
Any of:

Internal catalog code. Not the public label — labels are not unique.

string
<= 64 characters /^[a-z][a-z0-9_-]{1,63}$/
direction
required

Computed from effective prices only, never from plan names. Only upgrade is gated by balance.

string
Allowed values: upgrade downgrade lateral
managed_servers
required
integer
monthly_price_per_server_usd

Decimal string or null when unknown.

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

Monthly price divided by the days in the current month (D-03).

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

unit_daily_rate_usd × managed_servers; 0 when not gated.

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

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

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

Always true for downgrade and lateral. For upgrade it is balance_usd >= required_reserve_usd; a false value is an offer to top up, not a refusal.

boolean
server_limit

fleet.servers.max of the target plan; null — unlimited.

integer | null
billing_effective_day
required

UTC calendar day.

string format: date
quoted_at
required

RFC 3339 UTC with microsecond precision.

string format: date-time
Example
{
"direction": "upgrade",
"required_reserve_usd": "12.340000",
"balance_usd": "12.340000",
"quoted_at": "2026-07-25T10:15:30.123456Z"
}

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

The target plan is contract-priced, so a self-service quote is impossible (code=feature_not_entitled), or the caller lacks the scope (code=forbidden).

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

The tenant has no plan assignment yet (code=plan_required).

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