Usage events are the foundation of usage-based billing. Send them from your application to track customer consumption.
Quick Start
Send a usage event:
curl -X POST https://coreapi.io/api/usage-events \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"events": [{
"transactionId": "req-abc-123",
"eventName": "ai_request",
"timestamp": "2026-01-15T14:30:00Z",
"customerId": "550e8400-e29b-41d4-a716-446655440000",
"properties": {
"tokens_used": 350,
"model": "gpt-4"
}
}]
}'
Event Structure
Each event requires these fields:
| Field | Type | Description |
|---|
transactionId | string | Unique ID for idempotency |
eventName | string | Matches your Nutzungsmetrik’s event name |
timestamp | ISO 8601 | When the event occurred |
customerId | UUID | The customer’s ID in Fynn |
properties | object | Event data (tokens, bytes, etc.) |
Example: AI Token Usage
{
"transactionId": "req-abc-123",
"eventName": "ai_request",
"timestamp": "2026-01-15T14:30:00Z",
"customerId": "550e8400-e29b-41d4-a716-446655440000",
"properties": {
"tokens_used": 350,
"model": "gpt-4",
"endpoint": "/v1/completions",
"status_code": 200
}
}
Example: API Call Tracking
{
"transactionId": "call-xyz-456",
"eventName": "api_call",
"timestamp": "2026-01-15T14:31:00Z",
"customerId": "550e8400-e29b-41d4-a716-446655440000",
"properties": {
"endpoint": "/api/users",
"method": "GET",
"response_time_ms": 145,
"status_code": 200
}
}
Batch Import
Send up to 1000 events in one request:
curl -X POST https://coreapi.io/api/usage-events \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"events": [
{
"transactionId": "req-001",
"eventName": "ai_request",
"timestamp": "2026-01-15T10:00:00Z",
"customerId": "cust-123",
"properties": { "tokens_used": 150, "model": "gpt-4" }
},
{
"transactionId": "req-002",
"eventName": "ai_request",
"timestamp": "2026-01-15T10:01:00Z",
"customerId": "cust-123",
"properties": { "tokens_used": 300, "model": "gpt-4-turbo" }
}
]
}'
Response
Success (202 Accepted):
{
"ingested": 2,
"failed": 0,
"errors": []
}
Partial Success:
{
"ingested": 1,
"failed": 1,
"errors": [
{
"index": 1,
"transactionId": "req-002",
"error": "Invalid customer ID"
}
]
}
Idempotency
Events with the same transactionId are only processed once. If you send the same event twice, Fynn returns the existing event instead of creating a duplicate.
Use deterministic transaction IDs, e.g.: ${customerId}-${timestamp}-${eventName} or UUIDs.
Properties for Nutzungsmetriks
The properties object should contain all fields your Nutzungsmetriks need:
| Nutzungsmetrik | Aggregation | Required Property |
|---|
| Token Usage | Sum | tokens_used |
| API Calls | Count | - (counts events) |
| Storage | Latest | storage_gb |
| Active Users | Unique Count | user_id |
Grouping Properties
If your Nutzungsmetrik uses groupBy, include those fields:
{
"properties": {
"tokens_used": 350,
"model": "gpt-4", // groupBy field
"region": "eu-west-1" // another groupBy field
}
}
Filter Properties
If your Nutzungsmetrik has filters, include the filtered fields:
{
"properties": {
"tokens_used": 350,
"status_code": 200 // filter: status_code in [200, 201, 204]
}
}
Legacy: Subscription Measurements
For existing integrations using subscription-based measurements:
curl -X POST https://coreapi.io/subscription-measurements/batch \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"values": [
{
"subscription": "SUBSCRIPTION_ID",
"subscriptionItem": "SUBSCRIPTION_ITEM_ID",
"measurementCode": "used_traffic",
"quantity": "1",
"measuredAt": "2026-01-15T00:00:00Z"
}
]
}'
See: API Reference
Best Practices
Timestamps
Always use UTC in ISO 8601 format:
✅ 2026-01-15T14:30:00Z
✅ 2026-01-15T14:30:00+00:00
❌ 2026-01-15 14:30:00
❌ 1705329000 (Unix timestamp)
Batch Sizes
| Scenario | Recommended Batch Size |
|---|
| Real-time tracking | 10-100 events |
| Bulk import | 500-1000 events |
| High volume | Buffer and send every 1-5 seconds |
Error Handling
async function sendEvents(events) {
const response = await fetch('https://coreapi.io/api/usage-events', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`
},
body: JSON.stringify({ events })
});
const result = await response.json();
if (result.failed > 0) {
// Retry failed events or log for manual review
console.error('Failed events:', result.errors);
}
return result;
}