Skip to main content

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.
ValueCategoryDescription
api_callGeneralREST API call
ai_generationAIGemini AI generation
storage_uploadStorageFile upload
storage_deleteStorageFile deletion
report_generationReportsPDF report generation
export_dataReportsData export
rag_queryRAGSemantic search query
rag_document_processRAGDocument chunking
rag_embeddingRAGEmbedding generation
agent_runAgentsComplete agent run (start to finish)
agent_stepAgentsIndividual step within an agent run
credit_consumedCreditsCredits deducted from balance
credit_purchasedCreditsCredits added via purchase
credit_reservedCreditsCredits reserved for an agent run
credit_releasedCreditsReserved credits released back to balance
module_installMarketplaceModule installed/activated
module_uninstallMarketplaceModule uninstalled
module_trial_startMarketplaceModule trial started
module_upgradeMarketplaceModule trial converted to paid

Core Types

UsageEvent

Persisted usage event document stored in the usage_events collection.
FieldTypeDescription
idstring?Firestore document ID (populated on read, absent on write)
organizationIdstringTenant isolation key
userIdstring?Firebase Auth UID of the user who triggered the event
eventTypeUsageEventTypeDiscriminator for the event — determines the metadata shape
timestampTimestamp | DateServer-generated timestamp (write) or Firestore Timestamp (read)
metadataRecord<string, unknown>Event-type-specific payload (see typed metadata interfaces)
quantitynumber?Aggregation unit — bytes for storage, 1 for API calls, chunk count for embeddings
costnumber?Optional estimated monetary cost of the event

Metadata Interfaces

Each UsageEventType has a corresponding typed metadata interface.

ApiCallMetadata

For api_call events.
FieldTypeDescription
endpointstringREST endpoint path (e.g. /v2/projects)
methodstringHTTP method (GET, POST, etc.)
durationnumber?Round-trip duration in milliseconds
statusCodenumber?HTTP status code returned

AiGenerationMetadata

For ai_generation events.
FieldTypeDescription
modelstringGemini model identifier (e.g. gemini-2.5-flash)
inputTokensnumber?Input token count reported by the model
outputTokensnumber?Output token count reported by the model
promptstring?First 100 characters of the prompt (for debugging)
featurestringWhich product feature triggered the generation. One of: 'monthly journal', 'report', 'assistant', 'me_indicators', 'me_narrative', 'me_anomaly'

StorageMetadata

For storage_upload and storage_delete events.
FieldTypeDescription
fileNamestringOriginal file name
fileSizenumberFile size in bytes
fileTypestringMIME type (or 'deleted' for deletions)
projectIdstring?Associated project ID, if any

RAGQueryMetadata

For rag_query events.
FieldTypeDescription
projectIdstringProject scope for the semantic search
queryTextstringFirst 100 characters of the user query (privacy-truncated)
queryTypestring?Optional query type classifier
responseTimeMsnumberEnd-to-end response time in milliseconds
cacheHitbooleanWhether the result was served from cache
citationCountnumberNumber of citations returned
confidencenumber?Average confidence score of the results (0-1)

RAGDocumentMetadata

For rag_document_process events.
FieldTypeDescription
projectIdstringProject scope
documentIdstringFirestore document ID of the processed document
fileNamestringOriginal file name
fileSizenumberFile size in bytes
chunkCountnumberNumber of text chunks produced
processingTimeMsnumberTotal processing time in milliseconds
status'success' | 'failed'Outcome of the processing operation
errorMessagestring?Error message if status is 'failed'

RAGEmbeddingMetadata

For rag_embedding events.
FieldTypeDescription
projectIdstringProject scope
documentIdstringFirestore document ID that was embedded
chunkCountnumberNumber of chunks embedded
embeddingModelstringEmbedding model identifier (e.g. text-embedding-004)
totalTokensnumber?Total token count across all chunks

AgentRunMetadata

For agent_run events — tracks a complete agent execution.
FieldTypeDescription
agentTypestringAgent definition key (e.g. 'compliance_checker')
runIdstringUnique agent run ID
stepCountnumberTotal steps executed in the run
totalInputTokensnumberCumulative input tokens across all steps
totalOutputTokensnumberCumulative output tokens across all steps
creditsCostnumberTotal credits consumed by the run
triggeredBystringFirebase Auth UID of the user who triggered the run
status'completed' | 'failed' | 'cancelled'Final status of the agent run
durationMsnumberWall-clock duration of the run in milliseconds
errorstring?Error message if status is 'failed'

AgentStepMetadata

For agent_step events — tracks a single step within an agent run.
FieldTypeDescription
agentTypestringAgent definition key
runIdstringParent agent run ID
stepIdstringUnique step ID within the run
stepIndexnumberZero-based index of this step in the run sequence
toolNamestringName of the tool invoked during this step
inputTokensnumber?Input tokens consumed by this step
outputTokensnumber?Output tokens produced by this step
creditsUsednumberCredits deducted for this step
durationMsnumberStep duration in milliseconds
status'completed' | 'failed' | 'skipped'Outcome of the step execution
errorstring?Error message if status is 'failed'

CreditTransactionMetadata

For credit_consumed, credit_purchased, credit_reserved, and credit_released events.
FieldTypeDescription
amountnumberCredits affected — positive for additions, negative for deductions
balanceBeforenumberCredit balance before the transaction
balanceAfternumberCredit balance after the transaction
sourcestringOrigin of the credit change. One of: 'subscription', 'purchase', 'agent_run', 'refund', 'admin_adjustment'
agentRunIdstring?Associated agent run ID, if the transaction is tied to an agent execution
reservationIdstring?Associated reservation ID, if this is a reservation lifecycle event
stripePaymentIntentIdstring?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.
FieldTypeDescription
totalQueriesnumberTotal number of semantic search queries
totalDocumentsProcessednumberTotal documents processed (chunked)
totalEmbeddingsGeneratednumberTotal embedding vectors generated
cacheHitRatenumberCache hit rate as a percentage (0-100)
avgResponseTimeMsnumberAverage query response time in milliseconds
avgConfidencenumberAverage confidence score across queries (0-1)
totalStorageBytesnumberTotal raw document storage in bytes
estimatedCostnumberEstimated 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".