= ({ accessToken, keyToken, userId, userRole, activity }) => {
// Proxy admins read the whole key. For anyone else the endpoint applies the caller's own user_id
// alongside the key filter, so the figures cover only that viewer's requests on this key -- said
// plainly in the scope note below rather than left to be misread as the key's total.
const readsWholeKey = hasProxyWideSpendView(userRole);
- const activity = useScopedDailyActivityRange(accessToken, {
- userId: spendScopeUserId(userRole, userId),
- apiKey: keyToken,
- });
-
- const { dateValue, onDateChange, results, loading, isFetchingMore } = activity;
+ const { dateValue, onDateChange, results, loading, isFetchingMore } = useScopedDailyActivityRange(
+ accessToken,
+ { userId: spendScopeUserId(userRole, userId), apiKey: keyToken },
+ activity,
+ );
const startTime = dateValue.from ?? null;
const endTime = dateValue.to ?? null;
diff --git a/ui/litellm-dashboard/src/components/templates/key_info_view.test.tsx b/ui/litellm-dashboard/src/components/templates/key_info_view.test.tsx
index 7a27cc41e5e..b403255b329 100644
--- a/ui/litellm-dashboard/src/components/templates/key_info_view.test.tsx
+++ b/ui/litellm-dashboard/src/components/templates/key_info_view.test.tsx
@@ -26,6 +26,30 @@ vi.mock("./key_edit_view", () => ({
},
}));
+import type { ActivityDateRange } from "@/app/(dashboard)/cost-optimization/_components/useDailyActivityRange";
+
+const AnalyticsDateControl = ({ activity, keyToken }: { activity: ActivityDateRange; keyToken: string }) => (
+
+ {keyToken}
+
+ {[1, 10].map((day) => (
+
+ ))}
+
+);
+
+vi.mock("./KeyAutoRouterUsageTab", () => ({
+ default: (props: React.ComponentProps) => ,
+}));
+vi.mock("./KeySavingsTab", () => ({
+ default: (props: React.ComponentProps) => ,
+}));
+
vi.mock("@/app/(dashboard)/hooks/useTeams", () => ({
default: vi.fn(),
}));
@@ -176,6 +200,38 @@ describe("KeyInfoView", () => {
await userEvent.click(await screen.findByRole("button", { name: /more key actions/i }));
};
+ it("shows key-scoped auto-router usage as its own admin tab", async () => {
+ vi.mocked(useAuthorized).mockReturnValue({ ...baseUseAuthorizedMock, userRole: "Admin" });
+ renderWithProviders( {}} keyId="test-key-id" teams={[]} />);
+
+ await userEvent.click(screen.getByRole("tab", { name: "Auto-router usage" }));
+
+ expect(screen.getByTestId("key-auto-router-usage")).toHaveTextContent("test-token-123");
+ });
+
+ it("preserves dates in both directions across unmounted analytics panels", async () => {
+ vi.mocked(useAuthorized).mockReturnValue({ ...baseUseAuthorizedMock, userRole: "Admin" });
+ renderWithProviders( {}} keyId="test-key-id" teams={[]} />);
+
+ expect(screen.queryByLabelText("Selected dates")).not.toBeInTheDocument();
+ await userEvent.click(screen.getByRole("tab", { name: "Savings" }));
+ await userEvent.click(screen.getByRole("button", { name: "Select August 1" }));
+ await userEvent.click(screen.getByRole("tab", { name: "Auto-router usage" }));
+ expect(screen.getByLabelText("Selected dates")).toHaveTextContent("2026-08-01T00:00:00.000Z");
+ await userEvent.click(screen.getByRole("button", { name: "Select August 10" }));
+ await userEvent.click(screen.getByRole("tab", { name: "Settings" }));
+ expect(screen.queryByLabelText("Selected dates")).not.toBeInTheDocument();
+ await userEvent.click(screen.getByRole("tab", { name: "Savings" }));
+ expect(screen.getByLabelText("Selected dates")).toHaveTextContent("2026-08-10T00:00:00.000Z");
+ });
+
+ it("does not offer the admin-only auto-router usage tab to an internal user", () => {
+ vi.mocked(useAuthorized).mockReturnValue({ ...baseUseAuthorizedMock, userRole: "Internal User" });
+ renderWithProviders( {}} keyId="test-key-id" teams={[]} />);
+
+ expect(screen.queryByRole("tab", { name: "Auto-router usage" })).not.toBeInTheDocument();
+ });
+
describe("last updated", () => {
const renderWithTimestamps = (overrides: Partial) => {
vi.mocked(useAuthorized).mockReturnValue(baseUseAuthorizedMock);
diff --git a/ui/litellm-dashboard/src/components/templates/key_info_view.tsx b/ui/litellm-dashboard/src/components/templates/key_info_view.tsx
index 0dd0dd6d6af..f5c682a2ee0 100644
--- a/ui/litellm-dashboard/src/components/templates/key_info_view.tsx
+++ b/ui/litellm-dashboard/src/components/templates/key_info_view.tsx
@@ -16,8 +16,15 @@ import { modelGroupHref, teamDetailHref } from "@/utils/entityLinks";
import { BadgeLink } from "@/components/shared/BadgeLink";
import { KeyInfoHeader } from "./KeyInfoHeader";
import KeySavingsTab from "./KeySavingsTab";
+import KeyAutoRouterUsageTab from "./KeyAutoRouterUsageTab";
+import { useActivityDateRange } from "@/app/(dashboard)/cost-optimization/_components/useDailyActivityRange";
import { useEffect, useState } from "react";
-import { isProxyAdminRole, isUserTeamAdminForSingleTeam, rolesWithWriteAccess } from "../../utils/roles";
+import {
+ hasProxyWideSpendView,
+ isProxyAdminRole,
+ isUserTeamAdminForSingleTeam,
+ rolesWithWriteAccess,
+} from "../../utils/roles";
import { mapDisplayToInternalNames, mapInternalToDisplayNames } from "../callback_info_helpers";
import AutoRotationView from "../common_components/AutoRotationView";
import DeleteResourceModal from "../common_components/DeleteResourceModal";
@@ -81,6 +88,7 @@ export default function KeyInfoView({
backButtonText = "Back to Keys",
}: KeyInfoViewProps) {
const { accessToken, userId: userID, userRole, premiumUser } = useAuthorized();
+ const activityDateRange = useActivityDateRange();
const queryClient = useQueryClient();
const canEditGuardrails = premiumUser || (userRole != null && rolesWithWriteAccess.includes(userRole));
const { teams: teamsData } = useTeams();
@@ -618,6 +626,11 @@ export default function KeyInfoView({
Savings
+ {hasProxyWideSpendView(userRole) && (
+
+ Auto-router usage
+
+ )}
Settings
@@ -761,9 +774,20 @@ export default function KeyInfoView({
keyToken={currentKeyData.token}
userId={userID}
userRole={userRole}
+ activity={activityDateRange}
/>