From 6058163c33f08105e8d842bdf595bc567e104ed6 Mon Sep 17 00:00:00 2001
From: Tony Giorgio
Date: Fri, 30 Jan 2026 10:50:10 -0600
Subject: [PATCH] feat: merge subscription credits with API credits UI updates
- Add api_credit_balance field to BillingStatus type
- Show API credit balance in CreditUsage when plan is >=75% used
- Add 'Buy API Credits' button in UpgradePromptDialog for paid users
- Update BillingStatus messaging to mention API credits option
- Add FAQ about using subscription for API access
- Update API Access feature descriptions in pricing config
- Update ApiCreditsSection description text
- Add api_settings URL param to open API settings dialog
Closes #406
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
---
frontend/src/billing/billingApi.ts | 1 +
frontend/src/components/BillingStatus.tsx | 11 ++++-
frontend/src/components/CreditUsage.tsx | 19 ++++++--
.../src/components/UpgradePromptDialog.tsx | 43 +++++++++++++------
.../components/apikeys/ApiCreditsSection.tsx | 2 +-
.../components/apikeys/ApiKeyDashboard.tsx | 6 +--
frontend/src/config/pricingConfig.tsx | 6 +--
frontend/src/routes/index.tsx | 16 ++++++-
frontend/src/routes/pricing.tsx | 17 ++++++++
9 files changed, 93 insertions(+), 28 deletions(-)
diff --git a/frontend/src/billing/billingApi.ts b/frontend/src/billing/billingApi.ts
index 74241622..26bb287c 100644
--- a/frontend/src/billing/billingApi.ts
+++ b/frontend/src/billing/billingApi.ts
@@ -18,6 +18,7 @@ export type BillingStatus = {
total_tokens: number | null;
used_tokens: number | null;
usage_reset_date: string | null;
+ api_credit_balance?: number;
};
type BillingRecurringInfo = {
diff --git a/frontend/src/components/BillingStatus.tsx b/frontend/src/components/BillingStatus.tsx
index 9ff291df..6f208fdf 100644
--- a/frontend/src/components/BillingStatus.tsx
+++ b/frontend/src/components/BillingStatus.tsx
@@ -50,6 +50,9 @@ export function BillingStatus() {
const isFree = billingStatus.product_name.toLowerCase().includes("free");
const isMax = billingStatus.product_name.toLowerCase().includes("max");
+ const hasApiAccess =
+ billingStatus.product_name?.toLowerCase().includes("pro") || isMax || isTeamPlan;
+
const getChatsText = () => {
if (isFree) {
if (billingStatus.chats_remaining === null || billingStatus.chats_remaining <= 0) {
@@ -59,9 +62,13 @@ export function BillingStatus() {
}
if (!billingStatus.can_chat) {
if (isMax) {
- return "Contact us to increase your limits";
+ return hasApiAccess
+ ? "Purchase API credits or contact us to increase limits"
+ : "Contact us to increase your limits";
}
- return "You've run out of messages, upgrade to keep chatting!";
+ return hasApiAccess
+ ? "Upgrade your plan or purchase API credits to keep chatting!"
+ : "You've run out of messages, upgrade to keep chatting!";
}
// Show team name for team plans
diff --git a/frontend/src/components/CreditUsage.tsx b/frontend/src/components/CreditUsage.tsx
index 17eb8882..63c9c5fc 100644
--- a/frontend/src/components/CreditUsage.tsx
+++ b/frontend/src/components/CreditUsage.tsx
@@ -22,6 +22,10 @@ export function CreditUsage() {
return null;
}
+ // Check if user has API credits - always show if they have any
+ const hasApiCredits =
+ billingStatus.api_credit_balance !== undefined && billingStatus.api_credit_balance > 0;
+
// Set bar color based on usage
const getBarColor = () => {
if (percentUsed >= 90) return "rgb(239, 68, 68)"; // Tailwind red-500
@@ -29,10 +33,14 @@ export function CreditUsage() {
return "rgb(16, 185, 129)"; // Tailwind emerald-500
};
+ const formatCredits = (credits: number) => {
+ return new Intl.NumberFormat("en-US").format(credits);
+ };
+
return (
- Credit Usage
+ Plan Credits{roundedPercent}%
@@ -44,8 +52,13 @@ export function CreditUsage() {
}}
/>