Skip to main content

Documentation

No results found.
Features

AI Usage & Costs

Every AI feature in the CMS — image generation, text drafting, translations, alt text, the site generator — bills directly to the site owner's own account with each provider. The AI Usage & Costs page (Dashboard → Settings → AI Usage, a...

Every AI feature in the CMS — image generation, text drafting, translations, alt text, the site generator — bills directly to the site owner's own account with each provider. The AI Usage & Costs page (Dashboard → Settings → AI Usage, admin-only) turns those opaque provider bills into a report inside the dashboard: spend over time, month-to-date total, cost per billing line item, how many images were generated and what each one roughly cost, and token consumption per text model.

Providers

Provider Status Data source
OpenAI Live Organization Costs API (/v1/organization/costs) + Usage APIs (/usage/images, /usage/completions)
Claude (Anthropic) Live Admin API (/v1/organizations/cost_report + /v1/organizations/usage_report/messages)
Google Gemini No reporting API exists Google exposes no key-based spend/usage endpoint for the Gemini API — the page says so and deep-links to AI Studio's usage page and Google Cloud Billing instead of pretending otherwise

fal.ai and Stability are deliberately out of scope.

OpenAI setup — the Admin key

OpenAI only serves billing data to an organization Admin API key (sk-admin-…); the regular project key used for generation calls is refused with a 401/403. The Admin key is created at platform.openai.com → Settings → Organization → Admin keys and pasted into Settings → API Keys → OpenAI → Admin API Key (setting ai.openai_admin_key). It is stored separately from the generation key and is never used for generation calls. Until it's saved, the AI Usage page shows a connect card that links to both the API Keys page and OpenAI's key console.

Anthropic setup — the Admin key

Same shape as OpenAI: billing data requires an Admin API key (sk-ant-admin…), created at console.anthropic.com → Settings → Admin keys and pasted into Settings → API Keys → Claude (Anthropic) → Admin API Key (setting ai.claude_admin_key). Two Anthropic-specific caveats: Admin keys exist only for Anthropic organization accounts (individual accounts get a connect card that explains this), and the Admin API's cost amounts arrive as decimal strings in cents — the provider converts to dollars. Claude generates no images, so the image-generation card and table are hidden entirely for this provider (the summary row drops to three cards).

What the page shows

  • Summary cards — spend over the selected window (7/30/60/90 days), month-to-date spend (flagged as partial when the window starts after the 1st), images generated with an approximate per-image cost, and total input/output tokens.
  • Balance remaining — OpenAI does not expose remaining credit balance through any API, so the card says exactly that and deep-links to the provider's billing console. The report shape carries a nullable balance so a future provider that does expose one renders it automatically.
  • Daily spend — a zero-filled bar chart over the window (UTC days, matching how billing APIs bucket).
  • Cost breakdown — spend per billing line item (gpt-image-2, images, gpt-4o, input, …), largest first, with share-of-total bars.
  • Image generation — images and requests per model from the usage API. The per-image figure comes from cross-referencing image-matching cost line items against the image count; line-item naming isn't contractual, so when nothing matches the count shows without a $/image figure.
  • Text models — input/output tokens per model.

Behaviour notes

  • Reports are cached for one hour per provider + window (AiCostReports::CACHE_TTL_SECONDS); the Refresh button bypasses the cache. Failures are never cached.
  • The page never fetches during navigation — the first fetch fires via wire:init after the page paints, so a slow billing API can't block the dashboard. Provider errors render as a friendly card (including the "that's not an Admin key" case) with a retry button.
  • Costs lag real usage by minutes to hours on the provider side; the empty state says so.

Architecture (adding a provider)

  • app/Support/AiCosts/AiCostProvider.php — the interface: key/label/supportsReporting/supportsImageGeneration/isConfigured/keyHint/keyConsoleUrl/billingUrl/fetch(days). fetch() returns one normalized report shape (currency, window total, month-to-date, nullable balance, zero-filled daily series, line items, images, tokens) and throws RuntimeException with a user-presentable message on failure. supportsReporting() === false renders the vendor as an explanatory card (Gemini); supportsImageGeneration() === false hides the image card/table (Claude).
  • app/Support/AiCosts/OpenAiCostsProvider.php — OpenAI; paginates each endpoint via next_page cursors with a hard page cap.
  • app/Support/AiCosts/AnthropicCostsProvider.php — Anthropic Admin API; same cursor pagination, x-api-key + anthropic-version headers, hand-built group_by[]= query strings (the API rejects PHP's indexed group_by[0]= form), cents→dollars conversion.
  • app/Support/AiCosts/GoogleGeminiCostsProvider.php — the no-reporting-API stub for Gemini; fetch() is never called.
  • app/Support/AiCosts/AiCostReports.php — registry + hourly cache. Adding a future provider is one new class registered in providers() — the page itself needs no other changes.
  • resources/views/pages/dashboard/settings/⚡ai-usage.blade.php — the Volt page; route dashboard.settings.ai-usage (admin group in routes/cms.php).

Tests: tests/Feature/AiUsageReportTest.php.