Pricing, credits, and usage
ReOpenly prices compute in credits. Fetch live rates and estimates instead of copying values from examples: prices and platform settings can change independently of a client release.
Public pricing endpoints
GET /api/v1/pricing/platform
GET /api/v1/pricing/models
POST /api/v1/pricing/estimate
These routes require no authentication and are rate-limited. /platform
returns the current credits-per-minute and signup bonus; /models returns the
narrow public calculator catalog. The authenticated /api/v1/base-models remains
the authority for deployable models, capabilities, and training bounds.
Estimate inference with token and request counts, or fine-tuning with the planned steps, sequence length, trainable conversation count, held-out count, and effective batch size:
{
"kind": "fine_tune",
"model": "<catalog-model-id>",
"workload": {
"max_steps": 100,
"max_seq_length": 2048,
"messages": 5000,
"examples": 1000,
"eval_examples": 50,
"effective_batch_size": 8
}
}
For fine-tuning, expected is the central forecast of billable time --
the training loop only -- while authorization_ceiling is the conservative
admission number and covers the whole lease, because it bounds how long a run
may occupy a GPU rather than what it costs. The two therefore differ by more
than a safety factor: a short run's unbilled startup can be most of its lease. duration_components.execution_limit_seconds is the live maximum paid
exposure. Do not present the authorization ceiling as expected spend, or the
expected estimate as a guarantee. The large-corpus preparation term is still
an admission bound awaiting scale validation. The estimate subtracts the
measured calibration density and adds the exact frozen evaluation schedule, so
sparse plans can quote less as well as dense plans quoting more.
embedded_evaluation_seconds, scheduled_evaluation_seconds, and
evaluation_adjustment_seconds expose that arithmetic. Fine-tune workloads may
include the same discriminated evaluation_cadence object accepted by job
creation.
Billable fine-tune seconds are GPU training time, and nothing on either side
of it. The charge is each attempt's training_started_at to
post_processing_started_at interval, falling back to the attempt's end for a
run that never reached post-processing. Everything before training begins is
unbilled -- queue time, freezing your selection, loading the model, and
reading and tokenizing your data -- and so is everything after the loop ends:
saving, verifying and publishing the model. Gaps before a retry are unbilled too.
A run that never began training is charged nothing. That is what makes cancelling a queued or preparing job free.
The final charge uses the measured interval for each charged attempt, not the wall-clock job duration and not the estimate.
examples is the selected trainable conversation count before the split, while messages is the
selected-message count retained as an explicit workload assumption. Send
eval_examples when you know the held-out count. If both corpus fields are
omitted, the public calculator conservatively assumes the current maximum of
512 held-out examples and returns low confidence; omitting the field is not an
estimate of zero evaluation work. The authenticated training wizard obtains the
actual split and public training plan from estimate-messages.
Training time is rounded up to the next 100 ms unit for each charged attempt. Ledger charges and balances retain six decimal places. The training screen displays costs to four decimal places; that display does not change the stored charge. For example, 40.3 seconds at 0.03 credits per GPU minute costs 0.020150 credits, displayed as 0.0202.
Balance and statement
GET /api/v1/credits
GET /api/v1/credits/usage?month=YYYY-MM
GET /api/v1/credits/usage?month=YYYY-MM&limit=50&cursor=<next_cursor>
/api/v1/credits returns the current balance and only the 100 most recent ledger
rows. /usage is the complete UTC calendar-month statement with totals,
category and project rollups, and cursor pagination up to 100 rows per
page. A ledger row may include billable_seconds,
rate_credits_per_minute, and surcharge_percent; absence on historical,
deposit, or refund rows means “not recorded,” not zero compute.
Inference rows can also include the exact requested endpoint_name and resolved
base_model_name. A base-model request retains its <catalog-model-id>
name in the statement.
Buying credits
POST /api/v1/credits/checkout
GET /api/v1/credits/checkout/status?session_id=<stripe_session_id>
Checkout body amount is a credit count, not a money amount:
{"amount": 25, "currency": "brl"}
The response locks and returns credits, currency, money_amount, and
fx_rate, plus the Stripe URL. Pass a fresh UUID v4 Idempotency-Key for each
logical checkout attempt. After Stripe redirects back, poll the authenticated
status endpoint and treat only fulfilled as credited; authorization, capture,
and reconciliation can be intermediate states. A fulfilled status also
returns purchase with the credits granted and the money_amount charged in
currency (ISO 4217, upper case); it is null in every other state.
There is no customer endpoint that grants credits. /api/credits/grant is an
app-admin operator route, and the former self-service deposit route does not
exist.
Statement entries always page by cursor (50 by default, maximum 100). Follow
entries_next_cursor to reach every row. Cursors belong to the account and month;
monthly totals and rollups are complete on every page. No mode opt-in is required.