billing
Billing pre-flight models.
POST /recordings/{recording_id}/analyses/quote answers "what will this
analysis cost, and can I afford it?" BEFORE submission, using the same cost
function and the same choice of balance the submission itself uses — a quote
equals the eventual settled charge for the same inputs.
BillingQuote
pydantic-model
¶
Bases: WalletQuote
Pre-flight cost quote for one analysis: the balance it is paid from, and whether it covers it.
Fields:
-
wallet(CreditBucket) -
estimated_credits(NonNegativeInt) -
available_credits(NonNegativeInt) -
balance_after(int) -
blocked_reason(Literal['insufficient_credits'] | None) -
placement(RunPlacement | None)
placement = None
pydantic-field
¶
Where the analysis would run. Null from a server that predates it.
BillingRates
pydantic-model
¶
Bases: BaseModel
Public billing rates and grant terms (config-fixed platform pricing).
Served by GET /status/billing-rates so clients display the SAME
numbers the server charges and grants with, instead of hardcoding them.
Credits are the unit throughout; euro pricing lives in the Stripe checkout.
Config:
frozen:True
Fields:
-
credit_cost_per_signal_hour(float) -
minimum_credits_per_analysis(int) -
storage_credits_per_gb_month(float) -
storage_grace_days(int) -
starter_grant_credits(int) -
grant_terms_months(list[int]) -
default_grant_term_months(int) -
grant_expiry_banner_days(int) -
grant_buffer_pct(int)
credit_cost_per_signal_hour
pydantic-field
¶
Credits charged per hour of analysed signal, unless an analysis sets its own price.
default_grant_term_months
pydantic-field
¶
The term a request starts at.
grant_buffer_pct
pydantic-field
¶
The margin a grant request adds to its plan's computed cost by default, in percent.
grant_expiry_banner_days
pydantic-field
¶
Days before a grant expires from which the organization's page shows the coming expiry.
grant_terms_months
pydantic-field
¶
The terms, in months, a grant or an extension may be asked for.
minimum_credits_per_analysis
pydantic-field
¶
Minimum credits charged per analysis submission.
starter_grant_credits
pydantic-field
¶
Research credits every new organization receives once; they never expire.
storage_credits_per_gb_month
pydantic-field
¶
Purchased credits charged per GB per month stored above an organization's free ceiling (daily debit). Storage up to the ceiling is free.
storage_grace_days
pydantic-field
¶
Days of grace after paid storage can no longer be paid for before the recordings above the ceiling are deleted.
CreditPackage
pydantic-model
¶
Bases: BaseModel
A purchasable credit package (one Stripe product).
Assembled by the api-server from its product->credits config plus LIVE Stripe price data, so displayed amounts always match what checkout charges. Clients must render these — never hardcode packages/prices.
Config:
frozen:True
Fields:
-
product_id(str) -
price_id(str) -
name(str) -
credits(int) -
amount_minor(int) -
currency(str)
amount_minor
pydantic-field
¶
Price in the currency's minor unit (e.g. euro cents).
credits
pydantic-field
¶
Credits granted on purchase.
currency
pydantic-field
¶
ISO currency code, e.g. "eur".
name
pydantic-field
¶
Display name from the Stripe product.
price_id
pydantic-field
¶
Stripe price id — pass to the checkout-session endpoint.
product_id
pydantic-field
¶
Stripe product id (fulfilment key).
RunPlacement
pydantic-model
¶
Bases: BaseModel
Where a submission would run, and what that does to its price.
Every analysis of an organisation runs in one place, set for the organisation: on the platform, or at its site.
Config:
frozen:True
Fields:
-
place(RunPlace) -
site_factor(float | None) -
runner_seen(bool)
Validators:
-
_a_factor_only_at_a_site
place
pydantic-field
¶
On the platform, or at the organisation's own site.
runner_seen
pydantic-field
¶
Whether a runner of the place's pool asked for work in the last three minutes. While none has, a submission waits in the queue, and is withdrawn after the queue timeout.
site_factor = None
pydantic-field
¶
The factor on the platform price the quoted credits include, for a run at the site; null on the platform.
WalletQuote
pydantic-model
¶
Bases: BaseModel
What a quoted cost asks of one balance.
Research analyses are paid from grants, commercial ones from
purchased; blocked_reason is set when that balance cannot cover the
cost. The client should then point to applying for a research grant
(grants) or to buying credits (purchased) rather than submitting.
Config:
frozen:True
Fields:
-
wallet(CreditBucket) -
estimated_credits(NonNegativeInt) -
available_credits(NonNegativeInt) -
balance_after(int) -
blocked_reason(Literal['insufficient_credits'] | None)
available_credits
pydantic-field
¶
Credits this balance has for new analyses (balance − held).
balance_after
pydantic-field
¶
available_credits − estimated_credits. Negative iff the submission would be rejected for insufficient credits.
blocked_reason = None
pydantic-field
¶
Why the submission would be rejected, or null if this balance covers it.
estimated_credits
pydantic-field
¶
Credits the analyses will cost from this balance (== the settled charge for the same inputs).
wallet
pydantic-field
¶
The balance that pays: grants or purchased.