Skip to content
Indiana
Dashboard
Docs
Browse docs / Credits & usage

Credits & usage

Read balances, consume atomically and reserve for asynchronous work.

SDK 0.0.1Updated

Read balances

Configure current credit rates

Products & Billing → Entitlements → credit

Isolated fixture capture of current components; no persistence or live-service calls.

  1. Separate quotes from execution

    quoteBalance provides a read-only estimate. The trusted backend uses mutateBalance for consume, reserve, confirm, release or refund and retains the original idempotency key.

Check the resultRates publish with an immutable entitlement version. There is no separate legacy Credit Pool. Consumption uses the atomic balance protocol.

app/credits.tsTypeScript
const { holdings } = await grow.readHoldings();const { quote } = await grow.quoteBalance({  operation: "quote", entitlementId, quantity: "1", properties: {},});const { ledger } = await grow.readLedger({  type: null, from: null, to: null, after: null, limit: 50,});// For display only. Consume on your trusted backend.

Browser reads use the current customer token and credits:read. Quantities are decimal strings. quoteBalance is a display estimate, not consumption authorization. Published catalog data determines pools, rates and sources.

Consume atomically

  • Use a private backend key with credits:consume. Derive customerId from your trusted user mapping.
  • Retry the same customer, operation, parameters and idempotency key to receive the original receipt. Changing parameters conflicts; a lost response must not cause a second charge.
  • Rejected results are also idempotent. Use a new key for a new attempt after balance changes.
server/consume.tsTypeScript
const { receipt } = await groove.mutateBalance({  customerId: authenticatedGrooveCustomerId,  command: {    operation: "consume", entitlementId, quantity: "1", properties: {},    idempotencyKey: `job:${jobId}:consume`,  },});if (!receipt.accepted) throw new Error(receipt.reason ?? "Credits unavailable");

Reserve and finalize

Reserve before asynchronous work, confirm actual quantity on success, or release on failure. Reservations last at most 24 hours. Confirm, release and timeout allow one terminal state. Failed additional consumption rolls back finalization and keeps the hold pending. Refunds reference the original successful transaction and its historic pricing.

server/reserve.tsTypeScript
const { receipt: hold } = await groove.mutateBalance({  customerId: authenticatedGrooveCustomerId,  command: {    operation: "reserve", entitlementId, quantity: "10", properties: {},    expiresInSeconds: 300, idempotencyKey: `job:${jobId}:reserve`,  },});if (!hold.accepted) throw new Error("Insufficient credits");await groove.mutateBalance({  customerId: authenticatedGrooveCustomerId,  command: {    operation: "confirm", operationId: hold.id, quantity: "8",    idempotencyKey: `job:${jobId}:confirm`,  },});// On failure use mutateBalance with operation release and operationId hold.id; omit quantity.