Documentation Index
Fetch the complete documentation index at: https://grantmaster.dev/llms.txt
Use this file to discover all available pages before exploring further.
Usage Tracking Reference
Source: src/features/billing/services/usageTracking.ts
Records every billable action (AI generation, storage upload, RAG query, agent run, credit transaction, etc.) into the usage_events Firestore collection. Each event carries typed metadata and triggers asynchronous aggregation updates for dashboard reporting.
All tracking functions are fire-and-forget — failures are logged but never propagated to the caller, so metering issues cannot break user workflows.
Quick Example
// Track an AI generation
await trackAiGeneration(orgId, 'monthly journal', { userId, model: 'gemini-2.5-flash' });
// Track a complete agent run
await trackAgentRun(orgId, runId, 'compliance_checker', {
userId, stepCount: 5, totalInputTokens: 3200, totalOutputTokens: 1800,
creditsCost: 12, status: 'completed', durationMs: 45000,
});
// Query usage for the current billing period
const { start, end } = getCurrentBillingPeriod();
const events = await getUsageEvents(orgId, start, end, 'ai_generation');
Event Types
UsageEventType
Discriminated union of all 18 billable action types.
| Value | Category | Description |
|---|
api_call | General | REST API call |
ai_generation | AI | Gemini AI generation |
storage_upload | Storage | File upload |
storage_delete | Storage | File deletion |
report_generation | Reports | PDF report generation |
export_data | Reports | Data export |
rag_query | RAG | Semantic search query |
rag_document_process | RAG | Document chunking |
rag_embedding | RAG | Embedding generation |
agent_run | Agents | Complete agent run (start to finish) |
agent_step | Agents | Individual step within an agent run |
credit_consumed | Credits | Credits deducted from balance |
credit_purchased | Credits | Credits added via purchase |
credit_reserved | Credits | Credits reserved for an agent run |
credit_released | Credits | Reserved credits released back to balance |
module_install | Marketplace | Module installed/activated |
module_uninstall | Marketplace | Module uninstalled |
module_trial_start | Marketplace | Module trial started |
module_upgrade | Marketplace | Module trial converted to paid |
Core Types
UsageEvent
Persisted usage event document stored in the usage_events collection.
| Field | Type | Description |
|---|
id | string? | Firestore document ID (populated on read, absent on write) |
organizationId | string | Tenant isolation key |
userId | string? | Firebase Auth UID of the user who triggered the event |
eventType | UsageEventType | Discriminator for the event — determines the metadata shape |
timestamp | Timestamp | Date | Server-generated timestamp (write) or Firestore Timestamp (read) |
metadata | Record<string, unknown> | Event-type-specific payload (see typed metadata interfaces) |
quantity | number? | Aggregation unit — bytes for storage, 1 for API calls, chunk count for embeddings |
cost | number? | Optional estimated monetary cost of the event |
Each UsageEventType has a corresponding typed metadata interface.
For api_call events.
| Field | Type | Description |
|---|
endpoint | string | REST endpoint path (e.g. /v2/projects) |
method | string | HTTP method (GET, POST, etc.) |
duration | number? | Round-trip duration in milliseconds |
statusCode | number? | HTTP status code returned |
For ai_generation events.
| Field | Type | Description |
|---|
model | string | Gemini model identifier (e.g. gemini-2.5-flash) |
inputTokens | number? | Input token count reported by the model |
outputTokens | number? | Output token count reported by the model |
prompt | string? | First 100 characters of the prompt (for debugging) |
feature | string | Which product feature triggered the generation. One of: 'monthly journal', 'report', 'assistant', 'me_indicators', 'me_narrative', 'me_anomaly' |
For storage_upload and storage_delete events.
| Field | Type | Description |
|---|
fileName | string | Original file name |
fileSize | number | File size in bytes |
fileType | string | MIME type (or 'deleted' for deletions) |
projectId | string? | Associated project ID, if any |
For rag_query events.
| Field | Type | Description |
|---|
projectId | string | Project scope for the semantic search |
queryText | string | First 100 characters of the user query (privacy-truncated) |
queryType | string? | Optional query type classifier |
responseTimeMs | number | End-to-end response time in milliseconds |
cacheHit | boolean | Whether the result was served from cache |
citationCount | number | Number of citations returned |
confidence | number? | Average confidence score of the results (0-1) |
For rag_document_process events.
| Field | Type | Description |
|---|
projectId | string | Project scope |
documentId | string | Firestore document ID of the processed document |
fileName | string | Original file name |
fileSize | number | File size in bytes |
chunkCount | number | Number of text chunks produced |
processingTimeMs | number | Total processing time in milliseconds |
status | 'success' | 'failed' | Outcome of the processing operation |
errorMessage | string? | Error message if status is 'failed' |
For rag_embedding events.
| Field | Type | Description |
|---|
projectId | string | Project scope |
documentId | string | Firestore document ID that was embedded |
chunkCount | number | Number of chunks embedded |
embeddingModel | string | Embedding model identifier (e.g. text-embedding-004) |
totalTokens | number? | Total token count across all chunks |
For agent_run events — tracks a complete agent execution.
| Field | Type | Description |
|---|
agentType | string | Agent definition key (e.g. 'compliance_checker') |
runId | string | Unique agent run ID |
stepCount | number | Total steps executed in the run |
totalInputTokens | number | Cumulative input tokens across all steps |
totalOutputTokens | number | Cumulative output tokens across all steps |
creditsCost | number | Total credits consumed by the run |
triggeredBy | string | Firebase Auth UID of the user who triggered the run |
status | 'completed' | 'failed' | 'cancelled' | Final status of the agent run |
durationMs | number | Wall-clock duration of the run in milliseconds |
error | string? | Error message if status is 'failed' |
For agent_step events — tracks a single step within an agent run.
| Field | Type | Description |
|---|
agentType | string | Agent definition key |
runId | string | Parent agent run ID |
stepId | string | Unique step ID within the run |
stepIndex | number | Zero-based index of this step in the run sequence |
toolName | string | Name of the tool invoked during this step |
inputTokens | number? | Input tokens consumed by this step |
outputTokens | number? | Output tokens produced by this step |
creditsUsed | number | Credits deducted for this step |
durationMs | number | Step duration in milliseconds |
status | 'completed' | 'failed' | 'skipped' | Outcome of the step execution |
error | string? | Error message if status is 'failed' |
For credit_consumed, credit_purchased, credit_reserved, and credit_released events.
| Field | Type | Description |
|---|
amount | number | Credits affected — positive for additions, negative for deductions |
balanceBefore | number | Credit balance before the transaction |
balanceAfter | number | Credit balance after the transaction |
source | string | Origin of the credit change. One of: 'subscription', 'purchase', 'agent_run', 'refund', 'admin_adjustment' |
agentRunId | string? | Associated agent run ID, if the transaction is tied to an agent execution |
reservationId | string? | Associated reservation ID, if this is a reservation lifecycle event |
stripePaymentIntentId | string? | Stripe PaymentIntent ID, if this is a purchase transaction |
Tracking Functions
trackUsageEvent() (Core)
Record a billable usage event to the usage_events collection. This is the core metering primitive — all domain-specific helpers delegate to this function.
trackUsageEvent(
organizationId: string,
eventType: UsageEventType,
metadata: Record<string, unknown>,
options?: { userId?: string; quantity?: number; cost?: number }
): Promise<void>
Side effects: Triggers updateUsageAggregates() asynchronously after writing the event document.
Domain-Specific Helpers
All helpers are fire-and-forget wrappers around trackUsageEvent().
trackApiCall()
trackApiCall(
organizationId: string,
endpoint: string,
method: string,
options?: { userId?: string; duration?: number; statusCode?: number }
): Promise<void>
trackAiGeneration()
trackAiGeneration(
organizationId: string,
feature: 'monthly journal' | 'report' | 'assistant' | 'me_indicators' | 'me_narrative' | 'me_anomaly',
options?: { userId?: string; model?: string; inputTokens?: number; outputTokens?: number; prompt?: string }
): Promise<void>
trackStorageUpload()
Quantity is set to fileSize bytes.
trackStorageUpload(
organizationId: string,
fileName: string,
fileSize: number,
fileType: string,
options?: { userId?: string; projectId?: string }
): Promise<void>
trackStorageDelete()
Quantity is set to fileSize bytes.
trackStorageDelete(
organizationId: string,
fileName: string,
fileSize: number,
options?: { userId?: string; projectId?: string }
): Promise<void>
trackRAGQuery()
Query text is truncated to 100 characters for privacy.
trackRAGQuery(
organizationId: string,
projectId: string,
queryText: string,
options?: { userId?: string; queryType?: string; responseTimeMs?: number; cacheHit?: boolean; citationCount?: number; confidence?: number }
): Promise<void>
trackDocumentProcessing()
Quantity is set to chunkCount.
trackDocumentProcessing(
organizationId: string,
projectId: string,
documentId: string,
fileName: string,
fileSize: number,
chunkCount: number,
processingTimeMs: number,
options?: { userId?: string; status?: 'success' | 'failed'; errorMessage?: string }
): Promise<void>
trackEmbeddingGeneration()
Quantity is set to chunkCount.
trackEmbeddingGeneration(
organizationId: string,
projectId: string,
documentId: string,
chunkCount: number,
options?: { userId?: string; embeddingModel?: string; totalTokens?: number }
): Promise<void>
trackAgentRun()
Cost is set to creditsCost.
trackAgentRun(
organizationId: string,
runId: string,
agentType: string,
options: {
userId: string; stepCount: number; totalInputTokens: number;
totalOutputTokens: number; creditsCost: number;
status: 'completed' | 'failed' | 'cancelled'; durationMs: number; error?: string;
}
): Promise<void>
trackAgentStep()
Cost is set to creditsUsed.
trackAgentStep(
organizationId: string,
runId: string,
stepId: string,
options: {
userId?: string; agentType: string; stepIndex: number; toolName: string;
inputTokens?: number; outputTokens?: number; creditsUsed: number;
durationMs: number; status: 'completed' | 'failed' | 'skipped'; error?: string;
}
): Promise<void>
trackCreditConsumption()
The amount field in metadata is stored as a negative number.
trackCreditConsumption(
organizationId: string,
amount: number,
options: {
userId?: string; balanceBefore: number; balanceAfter: number;
source: CreditTransactionMetadata['source']; agentRunId?: string; reservationId?: string;
}
): Promise<void>
trackCreditPurchase()
trackCreditPurchase(
organizationId: string,
amount: number,
options: {
userId?: string; balanceBefore: number; balanceAfter: number;
stripePaymentIntentId?: string;
}
): Promise<void>
Query & Aggregation
getUsageEvents()
Retrieve usage events for an organization within a date range.
getUsageEvents(
organizationId: string,
startDate: Date,
endDate: Date,
eventType?: UsageEventType
): Promise<UsageEvent[]>
Returns an empty array on error (never throws).
RAGUsageStats
Aggregated RAG usage statistics for a billing period.
| Field | Type | Description |
|---|
totalQueries | number | Total number of semantic search queries |
totalDocumentsProcessed | number | Total documents processed (chunked) |
totalEmbeddingsGenerated | number | Total embedding vectors generated |
cacheHitRate | number | Cache hit rate as a percentage (0-100) |
avgResponseTimeMs | number | Average query response time in milliseconds |
avgConfidence | number | Average confidence score across queries (0-1) |
totalStorageBytes | number | Total raw document storage in bytes |
estimatedCost | number | Estimated cost based on Gemini embedding pricing |
getRAGUsageStats()
Compute aggregated RAG usage statistics for a billing period.
getRAGUsageStats(
organizationId: string,
startDate: Date,
endDate: Date
): Promise<RAGUsageStats>
Returns zeroed stats on error (never throws).
Billing Period Utilities
getCurrentBillingPeriod()
Return the start and end dates of the current calendar-month billing period.
getCurrentBillingPeriod(): { start: Date; end: Date }
getBillingPeriodKey()
Generate a YYYY-MM key suitable for partitioned aggregation storage.
getBillingPeriodKey(date?: Date): string
Example: getBillingPeriodKey() returns "2026-02".