feat(billing): rewrite historical usage endpoints to use Autumn API#3273
feat(billing): rewrite historical usage endpoints to use Autumn API#3273firecrawl-spring[bot] wants to merge 1 commit intofeat/autumn-balance-endpointsfrom
Conversation
Replace Supabase RPC calls with Autumn SDK for the credit-usage-historical and token-usage-historical endpoints (v1 + v2). The new implementation fetches billing period boundaries from the active subscription and makes parallel events.aggregate calls for each period. Also resolves API key IDs back to human-readable names via the api_keys table to preserve backwards compatibility with the apiKey response field. Co-Authored-By: micahstairs <micah@sideguide.dev>
There was a problem hiding this comment.
2 issues found across 5 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/api/src/services/autumn/usage.ts">
<violation number="1" location="apps/api/src/services/autumn/usage.ts:229">
P2: Period boundaries assume a constant period length, which is incorrect for monthly billing. Months range from 28–31 days, so subtracting a fixed `periodLengthSec` causes past period boundaries to drift from actual billing cycles (e.g., current period = March 1 → April 1 yields the previous period as Jan 29 → March 1 instead of Feb 1 → March 1). Consider fetching actual historical period boundaries from the subscription or using calendar-aware date arithmetic.</violation>
<violation number="2" location="apps/api/src/services/autumn/usage.ts:286">
P1: Missing `.sum` accessor on grouped aggregate values — likely yields `NaN` for all `byApiKey=true` responses.
The ungrouped path correctly uses `result.total?.[CREDITS_FEATURE_ID]?.sum`, but here the code accesses `values[CREDITS_FEATURE_ID]` without `.sum`. If the grouped value structure mirrors the total structure (as is standard for aggregate APIs), this returns an object instead of a number.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.
| const current = apiKeyTotals.get(apiKeyId) ?? 0; | ||
| apiKeyTotals.set( | ||
| apiKeyId, | ||
| current + (values[CREDITS_FEATURE_ID] ?? 0), |
There was a problem hiding this comment.
P1: Missing .sum accessor on grouped aggregate values — likely yields NaN for all byApiKey=true responses.
The ungrouped path correctly uses result.total?.[CREDITS_FEATURE_ID]?.sum, but here the code accesses values[CREDITS_FEATURE_ID] without .sum. If the grouped value structure mirrors the total structure (as is standard for aggregate APIs), this returns an object instead of a number.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/api/src/services/autumn/usage.ts, line 286:
<comment>Missing `.sum` accessor on grouped aggregate values — likely yields `NaN` for all `byApiKey=true` responses.
The ungrouped path correctly uses `result.total?.[CREDITS_FEATURE_ID]?.sum`, but here the code accesses `values[CREDITS_FEATURE_ID]` without `.sum`. If the grouped value structure mirrors the total structure (as is standard for aggregate APIs), this returns an object instead of a number.</comment>
<file context>
@@ -123,3 +159,185 @@ export async function getTeamBalance(
+ const current = apiKeyTotals.get(apiKeyId) ?? 0;
+ apiKeyTotals.set(
+ apiKeyId,
+ current + (values[CREDITS_FEATURE_ID] ?? 0),
+ );
+ }
</file context>
| current + (values[CREDITS_FEATURE_ID] ?? 0), | |
| current + ((values as any)[CREDITS_FEATURE_ID]?.sum ?? 0), |
| // Build period boundaries going backwards from the current period | ||
| const periods: Array<{ start: number; end: number }> = []; | ||
| for (let i = HISTORICAL_PERIOD_COUNT - 1; i >= 0; i--) { | ||
| const start = currentStart - i * periodLengthSec; |
There was a problem hiding this comment.
P2: Period boundaries assume a constant period length, which is incorrect for monthly billing. Months range from 28–31 days, so subtracting a fixed periodLengthSec causes past period boundaries to drift from actual billing cycles (e.g., current period = March 1 → April 1 yields the previous period as Jan 29 → March 1 instead of Feb 1 → March 1). Consider fetching actual historical period boundaries from the subscription or using calendar-aware date arithmetic.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/api/src/services/autumn/usage.ts, line 229:
<comment>Period boundaries assume a constant period length, which is incorrect for monthly billing. Months range from 28–31 days, so subtracting a fixed `periodLengthSec` causes past period boundaries to drift from actual billing cycles (e.g., current period = March 1 → April 1 yields the previous period as Jan 29 → March 1 instead of Feb 1 → March 1). Consider fetching actual historical period boundaries from the subscription or using calendar-aware date arithmetic.</comment>
<file context>
@@ -123,3 +159,185 @@ export async function getTeamBalance(
+ // Build period boundaries going backwards from the current period
+ const periods: Array<{ start: number; end: number }> = [];
+ for (let i = HISTORICAL_PERIOD_COUNT - 1; i >= 0; i--) {
+ const start = currentStart - i * periodLengthSec;
+ const end = currentEnd - i * periodLengthSec;
+ periods.push({ start, end });
</file context>
Summary
credit-usage-historicalandtoken-usage-historicalendpoints (v1 + v2)events.aggregatecalls per periodapi_keystable to preserve backwards compatibility with theapiKeyresponse fieldresolveApiKeyNames()andgetHistoricalUsage()toservices/autumn/usage.tsStacked on #3272 — merge that first.
Test plan
GET /v1/team/credit-usage/historicalreturns billing-period-aligned usage binsGET /v2/team/credit-usage/historicalreturns same in camelCaseGET /v1/team/token-usage/historicalreturns token values (credits × 15)GET /v2/team/token-usage/historicalreturns token values (credits × 15)?byApiKey=truereturns human-readable API key names (not numeric IDs)Summary by cubic
Rewrite historical credit and token usage endpoints (v1 and v2) to use the Autumn API, aligning results to billing periods and preserving response shape. Adds API key name resolution and parallel aggregation for faster, consistent usage data.
events.aggregateacross billing-period ranges.byApiKey=truenow groups by API key and resolves IDs to human-readable names for theapiKeyfield.getHistoricalUsage()andresolveApiKeyNames()inservices/autumn/usage.ts; shared by all four endpoints.[]when no active subscription; periods sorted ascending; token endpoints computetokensUsedascreditsUsed * 15.Written for commit ecb38dc. Summary will update on new commits.