diff --git a/ui/litellm-dashboard/src/app/(dashboard)/customers/_components/CreateCustomerDialog.tsx b/ui/litellm-dashboard/src/app/(dashboard)/customers/_components/CreateCustomerDialog.tsx
index 3cbdd5a79cc..3fc37523154 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/customers/_components/CreateCustomerDialog.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/customers/_components/CreateCustomerDialog.tsx
@@ -12,6 +12,8 @@ export default function CreateCustomerDialog({ open, onOpenChange, onCreated }:
const [userId, setUserId] = useState("");
const [alias, setAlias] = useState("");
const [budget, setBudget] = useState("");
+ const [tpm, setTpm] = useState("");
+ const [rpm, setRpm] = useState("");
const create = $api.useMutation("post", "/customer/new", {
onSuccess: () => {
toast.success(`Created ${alias || userId}`);
@@ -30,6 +32,8 @@ export default function CreateCustomerDialog({ open, onOpenChange, onCreated }:
blocked: false,
max_budget: budget ? Number(budget) : null,
budget_duration: budget ? "1mo" : null,
+ tpm_limit: tpm ? Number(tpm) : null,
+ rpm_limit: rpm ? Number(rpm) : null,
},
});
};
@@ -52,10 +56,23 @@ export default function CreateCustomerDialog({ open, onOpenChange, onCreated }:
setAlias(e.target.value)} placeholder="Acme Corp" />
-
-
-
setBudget(e.target.value.replace(/[^0-9.]/g, ""))} placeholder="Leave empty for no budget" />
+
+
+
+ setBudget(e.target.value.replace(/[^0-9.]/g, ""))} placeholder="Leave empty for no budget" />
+
+
+
TPM/RPM apply to this customer across every key it uses; the proxy returns 429 above them.
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/customers/_components/CustomerDetail.tsx b/ui/litellm-dashboard/src/app/(dashboard)/customers/_components/CustomerDetail.tsx
index ddcdc75ccd6..e043145bd65 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/customers/_components/CustomerDetail.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/customers/_components/CustomerDetail.tsx
@@ -43,6 +43,9 @@ export default function CustomerDetail({ customerId, onBack }: { customerId: str
const label = c?.alias || customerId;
const status = c ? customerStatus(c, spend) : "active";
const max = c?.litellm_budget_table?.max_budget ?? null;
+ const tpmLimit = c?.litellm_budget_table?.tpm_limit ?? null;
+ const rpmLimit = c?.litellm_budget_table?.rpm_limit ?? null;
+ const limitsText = [tpmLimit !== null ? `${tpmLimit.toLocaleString()} TPM` : null, rpmLimit !== null ? `${rpmLimit.toLocaleString()} RPM` : null].filter(Boolean).join(" / ");
const refresh = () => { keysQuery.refetch(); trafficQuery.refetch(); };
const removeKey = async (k: PortalKey) => {
if (!accessToken) return;
@@ -67,6 +70,7 @@ export default function CustomerDetail({ customerId, onBack }: { customerId: str
Spend this month {formatUSD(spend)}
{max !== null && max !== undefined ? <> of {formatUSD(max)} budget> : ", no budget"}
+ {limitsText && <> · {limitsText}>}
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/customers/_components/EditCustomerDialog.tsx b/ui/litellm-dashboard/src/app/(dashboard)/customers/_components/EditCustomerDialog.tsx
index 1a2d21bdcf2..5257a2a4c67 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/customers/_components/EditCustomerDialog.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/customers/_components/EditCustomerDialog.tsx
@@ -20,8 +20,16 @@ function EditCustomerForm({ onOpenChange, customer, onSaved }: Omit
(n === null || n === undefined ? "" : String(n));
+ const [tpm, setTpm] = useState(asText(customer.litellm_budget_table?.tpm_limit));
+ const [rpm, setRpm] = useState(asText(customer.litellm_budget_table?.rpm_limit));
+ const updateLimits = $api.useMutation("post", "/budget/update");
const update = $api.useMutation("post", "/customer/update", {
- onSuccess: () => {
+ onSuccess: async () => {
+ if (budgetId) {
+ await updateLimits.mutateAsync({ body: { budget_id: budgetId, tpm_limit: tpm ? Number(tpm) : null, rpm_limit: rpm ? Number(rpm) : null } });
+ }
toast.success("Customer updated");
onSaved();
onOpenChange(false);
@@ -54,9 +62,20 @@ function EditCustomerForm({ onOpenChange, customer, onSaved }: OmitMax Budget (USD)
setBudget(e.target.value.replace(/[^0-9.]/g, ""))} placeholder="Leave empty for no budget" />
+
+ {budgetId ? "Limits apply to this customer across every key it uses." : "Set a budget or limits when creating the customer to enable TPM/RPM here."}
-
+