Build a real-time prepaid credits dashboard with Chargebee
Credits are the currency in your product—they determine what customers can do. Customers need real-time visibility into their balance, spending, and what’s left. This is a RevOps moment: show transparency, and customers will spend more confidently. Chargebee's Ledger APIs give you the data; your dashboard makes it compelling to customers.
Credits determine what customers can and can’t do in your product. Give them real-visibility on it.
Credits are runtime monetization: every job is both a product action and a consumption event. The balance a customer sees isn’t static. It’s a live state that changes as jobs start and finish. When that state is unclear, customers over-spend, under-use, or get surprised.
This recipe provides visibility into consumption, reserved credits, credit sources, and expiration dates, so customers always know where they stand.
- “How many credits do I actually have available right now?”
- “Where did my credits come from and when do they expire?”
- “What consumed my credits? Which model, which job?”
- “Are any credits currently held for jobs still in progress?”
- “Do I have any bonus or promotional credits?”
Three APIs. Each answers one customer question.
Used together, they take a customer from “how many credits do I have?” to a complete account view: current balance, where those credits came from, and the full history of what was spent.
The real-time credit balance for this subscription: provisioned balance (what they paid for), overdraft balance (the safety buffer), usable balance, and hold amount (credits currently reserved for in-flight jobs). The foundation for every number on the dashboard.
Every credit grant tied to this subscription: its original allocation, remaining balance, active window, and expiry. Answers where credits came from, and surfaces any that are about to expire before the customer finds out on their own.
The full double-entry ledger: every capture, authorization, release, and grant event for this subscription, with timestamps, amounts, and your own metadata. This is the star of the credits dashboard. A usage bar tells customers how much they’ve spent. The ledger tells them exactly what spent it.
How many credits does my customer actually have right now?
Provisioned balance is what they paid for. Hold amount is what’s reserved for jobs in progress. Usable balance is what they can actually spend right now. One API call returns all three, always in sync.
Always compute available as
usable_balance directly from the API. Never derive it by subtraction. Held credits are already excluded. Deriving it yourself creates a race condition when multiple jobs run in parallel. // Query params ?subscription_id[is]="sub_FrameshiftStudio" &unit_id[is]="ai_credits" // Response { "ledger_account_balance": { "subscription_id": "sub_FrameshiftStudio", "unit_id": "ai_credits", "unit_type": "credit_unit", "modified_at": 1751020800, "provisioned_balance": { "usable_balance": "22800", // spendable now "hold_amount": "6000", // in-flight holds "consumed_balance": "51200" // permanently used }, "overdraft_balance": { "usable_balance": "0", "hold_amount": "0", "consumed_balance": "0" } } }
Where did the credits come from? And when do they expire?
Every credit in a customer’s balance traces back to a grant block: a specific allocation with its own active window and expiry. Listing grant blocks turns a raw number into a sourced, time-aware account view. Promotional grants appear here too, as a distinct type alongside the plan allocation.
// Query params ?subscription_id[is]="sub_FrameshiftStudio" &unit_id[is]="ai_credits" // Response: one object per grant { "grant_block": { "id": "gb_JunePlan2025", "subscription_id": "sub_FrameshiftStudio", "unit_id": "ai_credits", "granted_amount": "80000", "usable_balance": "22800", "effective_from": 1748736000, // Jun 1 "expires_at": 1751328000, // Jul 1 "source": "item_price" } }
Promotional grants created via
POST /promotional_grants appear alongside plan grants in the grant blocks list, with source: "promotional_grant". Filter on this field to badge them differently on the dashboard. What spent the credits? The ledger is the honest answer.
A balance tells customers how much is left. The ledger tells them exactly where it went. Every capture is a job that completed. Every authorization is a job still running. Every release is a job that failed and returned credits to the pool. And because ledger operations are immutable once recorded, the ledger is also a tamper-proof audit trail: every state change permanently on the record, traceable back to its source.
| Type | Description | Amount | Balance after |
|---|---|---|---|
Kling 3.0 / 4K video (job A) op_sA9x · 2 min ago | −2,000 held | 22,800 | |
| Captured | Kling 3.0 / 4K video op_sB3k · 2 min ago | −2,400 | 24,800 |
| Captured | Kling 3.0 / short clip op_kL7m · 18 min ago | −820 | 27,200 |
| Released | Veo 3.1 / failed render op_vE1p · 34 min ago | +2,000 returned | 28,020 |
| Captured | ElevenLabs / voiceover op_eV2q · 1h ago | −110 | 26,020 |
| Allocation | AI Creator plan, Jun renewal gb_JunePlan2025 · Jun 1 | +80,000 | 80,000 |
The
metadata field is an opaque JSON object stored verbatim. Pass model, resolution, job_id on every capture, and your ledger feed becomes a readable production log, not just a list of numbers. // Query params ?subscription_id[is]="sub_FrameshiftStudio" &unit_id[is]="ai_credits" &limit=25 // Response: one object per event { "ledger_operation": { "id": "op_sB3k", "type": "capture", "subscription_id": "sub_FrameshiftStudio", "unit_id": "ai_credits", "amount": "2400", "provisioned_start_balance": "27200", "provisioned_end_balance": "24800", // 'balance after' column "ledger_operation_timestamp": 1751018400, "metadata": { "model": "kling-3.0", "resolution": "4k", "job_id": "job_7fabc91" } } }
Visibility that drives customers to spend more.
Prepaid credits only work when customers trust their balance and understand what they have left. Chargebee's Ledger APIs track every grant, spending, expiration, and reserve in real time so your dashboard shows the complete picture. Customers see clarity. They spend confidently. You capture more revenue per account.


