Skip to main content

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.