Skip to main content
Use the freeze -> consume / unfreeze flow to bill work that you price yourself, when the cost is unknown upfront. This is one half of Velobase: the billing ledger for your own work. This is the right choice for async tasks, batch jobs, and any flow where the final cost is only known after execution.
If you are billing model calls, you usually do not need this flow. Point your OpenAI or Anthropic SDK at https://api.velobase.io/v1 and pass X-Velobase-Customer: <user-id>, and the gateway freezes, settles the real token cost, and deducts from the customer wallet for you on every call. See the Quickstart for the gateway path. Use staged deduction below when you price the work yourself rather than per model token.
transaction_id is the unique ID for this charge transaction and stays the same across freeze, consume, and unfreeze. All amount fields are in cents. 1 USD = 100 cents = 1,000,000 credits. A bare amount is legacy and is interpreted as cents.
1

Freeze

Reserve a maximum budget before starting work. After freezing, the funds are no longer available to spend, but they have not been consumed yet.
Freeze Parameters
body.customer_id
string
required
The unique identifier for this customer. The customer must already exist and have enough available funds in their wallet to cover the freeze amount.
body.transaction_id
string
required
Unique ID for this charge transaction. Use the same value for the subsequent consume or unfreeze call.
body.amount_cents
number
required
Maximum amount to reserve, in cents (1 USD = 100 cents = 1,000,000 credits). You may instead send amount_usd or amount_credits. A bare amount is legacy and is read as cents. Must be greater than 0. Set this to the upper bound of expected cost.
body.credit_types
string[]
Restrict the freeze to these wallet categories only. If omitted, the system may use any active funds. The same categories are used automatically during consume.
body.business_type
string
Transaction category for reporting. Examples: TASK, ORDER, TOKEN_USAGE.
body.description
string
A human-readable note for this freeze.
Freeze Response
transaction_id
string
The transaction ID passed in the request.
frozen_amount
number
Total amount reserved by this freeze, in cents.
freeze_details
array
Breakdown of which wallet sources were frozen. The system may freeze across multiple wallet categories.
is_idempotent_replay
boolean
true when the response was returned from a previous request with the same transaction_id.
Returns 400 with insufficient balance if the customer wallet does not have enough available funds.If credit_types is provided during freeze, and the selected wallet categories do not have enough funds, the error message becomes insufficient balance in selected credit_types.
2

Consume

Settle the actual cost after the task finishes. Any unused funds are returned automatically.
Example: freeze 100 cents, finish with an actual cost of 73 cents, and the remaining 27 cents is automatically returned.Consume Parameters
body.transaction_id
string
required
The same transaction ID used in the freeze step.
body.actual_amount
number
Actual amount to consume, in cents. If less than the frozen amount, the remainder is returned. Defaults to the full frozen amount if omitted.
Consume Response
consumed_amount
number
Amount permanently consumed by this operation, in cents.
returned_amount
number
Unused frozen funds automatically returned to the available wallet balance, in cents (frozen_amount - actual_amount).
consume_details
array
Breakdown of which wallet sources were consumed.
consumed_at
string
ISO 8601 timestamp when consumption completed.
is_idempotent_replay
boolean
true when the response was returned from a previous request with the same transaction_id.
3

Unfreeze (Cancel)

Release frozen funds without consuming. Use when the task is cancelled.
Unfreeze Response
unfrozen_amount
number
Total amount returned to the available wallet balance, in cents.
unfreeze_details
array
Breakdown of which wallet sources were unfrozen.
unfrozen_at
string
ISO 8601 timestamp when the unfreeze completed.
is_idempotent_replay
boolean
true when the response was returned from a previous request with the same transaction_id.

Wallet Categories and Consumption Order

  • The system automatically freezes and consumes from all available wallet funds.
  • If credit_types is provided during freeze, only those wallet categories are eligible for this transaction.
  • Callers do not choose which wallet category to use.
  • Funds that expire sooner are handled first. If expiry is the same, older sources are handled first.
  • Only funds that are currently active participate in freeze and consume. Funds that have not started yet or have already expired are ignored.
  • Use the customer API to inspect remaining funds per wallet source.

Idempotency

All three operations are idempotent on transaction_id. Duplicate calls return the original result with is_idempotent_replay: true.

Verify the Result

Fetch the customer to inspect their wallets:
After each step, check the wallets["default"] summary:
  • whether frozen increases after freeze
  • whether used increases after consume
  • whether available changes as expected
  • which wallet sources[] were used
All wallet amounts are in cents (1 USD = 100 cents = 1,000,000 credits).

Error Format

All API errors return an HTTP error status and a structured error object:
error.message
string
Human-readable description of the error.
error.type
string
High-level error category.
error.code
string
Stable machine-readable error code for programmatic handling.