Skip to main content

Table of Contents

What are Usage Events?

A Usage Event represents a unit of consumption in your application — an API call made, a document generated, storage consumed, a message sent. Publishing usage events lets SolvaPay track what your customers are consuming, enforce plan limits, and provide usage analytics. Usage events are distinct from meter events. Meters are for precise billing counters. Usage events are broader — they capture consumption context (which customer, which product, how many units) and feed into the event system for analytics, alerting, and operational visibility.

Publishing a Usage Event

Use createEvent() to publish a usage event:
import { createSolvaPay } from '@solvapay/server'

const solvaPay = createSolvaPay({
  apiKey: process.env.SOLVAPAY_SECRET_KEY,
})

await solvaPay.createEvent({
  type: 'usage.api_call',
  customerRef: 'cus_3C4D5E6F',
  units: 1,
})
The SDK authenticates the request using your API key. The backend validates the event, scopes it to your provider and environment, and publishes it through the event system.

Response

const { eventId } = await solvaPay.createEvent({
  type: 'usage.api_call',
  customerRef: 'cus_3C4D5E6F',
  units: 1,
})

console.log(eventId) // "evt_a1b2c3d4..."
The returned eventId is a unique identifier for the published event.

Event Fields

FieldTypeRequiredDescription
typestringYesDot-notation event type (e.g. usage.api_call)
customerRefstringYesThe customer reference this event belongs to
productRefstringNoThe product reference, if the event is scoped to a specific product
unitsnumberYesQuantity consumed (must be non-negative)

type

A dot-notation string that categorises the event. Convention is usage.<action>, for example:
  • usage.api_call
  • usage.document_generated
  • usage.message_sent
  • usage.storage
  • usage.token
  • usage.search
You define your own types. There are no restrictions on what comes after usage..

customerRef

The customer reference (cus_...) identifying who consumed the resource. This must be a valid customer reference in your SolvaPay account.

productRef

Optional. The product reference (prd_...) to scope the event to a specific product. Useful when a customer has purchases across multiple products and you want usage attributed to the correct one.

units

The quantity consumed. Must be a non-negative number. The meaning depends on your type:
  • For usage.api_call: typically 1 per call
  • For usage.token: the number of tokens consumed
  • For usage.storage: bytes or megabytes used

Event Types

You define your own event types using dot-notation. Here are common patterns:
TypeUse Case
usage.api_callREST or GraphQL API requests
usage.tokenLLM token consumption
usage.message_sentChat or notification messages
usage.document_generatedPDF, report, or file generation
usage.searchSearch queries executed
usage.storageFile or data storage consumption
usage.computeCompute time or processing units

Examples

Track API calls in Express

import express from 'express'
import { createSolvaPay } from '@solvapay/server'

const app = express()
const solvaPay = createSolvaPay({
  apiKey: process.env.SOLVAPAY_SECRET_KEY,
})

app.post('/api/generate', async (req, res) => {
  const customerRef = req.headers['x-customer-ref'] as string
  const result = await generateContent(req.body)

  await solvaPay.createEvent({
    type: 'usage.api_call',
    customerRef,
    productRef: 'prd_content_api',
    units: 1,
  })

  res.json(result)
})

Track token consumption in an AI app

const response = await openai.chat.completions.create({
  model: 'gpt-4',
  messages,
})

const tokensUsed = response.usage?.total_tokens ?? 0

await solvaPay.createEvent({
  type: 'usage.token',
  customerRef,
  productRef: 'prd_ai_assistant',
  units: tokensUsed,
})

Track document generation

async function generateReport(customerRef: string, data: ReportData) {
  const pdf = await renderPdf(data)

  await solvaPay.createEvent({
    type: 'usage.document_generated',
    customerRef,
    units: 1,
  })

  return pdf
}

Track storage usage

async function uploadFile(customerRef: string, file: Buffer) {
  const result = await storage.upload(file)
  const megabytes = Math.ceil(file.byteLength / (1024 * 1024))

  await solvaPay.createEvent({
    type: 'usage.storage',
    customerRef,
    units: megabytes,
  })

  return result
}

Relationship to Meters

Usage events and meter events serve different purposes:
Usage EventsMeter Events
PurposeOperational visibility and analyticsBilling and limit enforcement
MethodsolvaPay.createEvent()solvaPay.trackUsage()
Enforces limitsNoYes
Triggers paywallsNoYes
Visible in ops dashboardYesNo
If you need to both track usage for analytics and enforce billing limits, publish a usage event and record a meter event for the same action.

Next Steps

  • Core Concepts - Understand products, plans, and the paywall flow
  • Meters - Set up meters for billing and limit enforcement
  • Webhook Handling - React to purchase and payment events