Back to Documentation
api
Event-ingestion
API endpoint for receiving batched events from the SDK EventTracker.
Endpoint
POST /api/tracking/events/batch
Authentication
Header: X-API-Key: sk_live_...
Request
Headers
X-API-Key: sk_live_your-api-key
Content-Type: application/json
Body
{
"events": [
{
"eventName": "page_viewed",
"properties": {
"page": "/dashboard"
},
"timestamp": "2025-01-25T10:30:00Z",
"sessionId": "sess_abc123",
"userId": "user_123",
"accountId": "acct_456",
"context": {
"url": "https://example.com/dashboard",
"pathname": "/dashboard",
"userAgent": "Mozilla/5.0...",
"screenWidth": 1920,
"screenHeight": 1080
}
}
],
"vendorId": "vendor-uuid",
"batchId": "batch_1234567890_xyz"
}
Event structure
{
eventName: string; // Required, non-empty
properties?: object; // Optional, defaults to {}
timestamp: string; // Required, ISO 8601 format
sessionId: string; // Required, non-empty
userId?: string | null; // Optional
accountId?: string | null; // Optional
context?: {
url: string;
pathname: string;
referrer?: string;
userAgent: string;
screenWidth: number;
screenHeight: number;
timestamp: string;
};
}
Response
Success
{
"success": true,
"batchId": "batch_1234567890_xyz",
"processed": 20,
"failed": 0,
"results": [
{
"index": 0,
"success": true,
"eventId": "550e8400-e29b-41d4-a716-446655440000"
},
{
"index": 1,
"success": true,
"eventId": "660e8400-e29b-41d4-a716-446655440001"
}
]
}
Partial failure
{
"success": true,
"batchId": "batch_1234567890_xyz",
"processed": 18,
"failed": 2,
"results": [
{
"index": 0,
"success": true,
"eventId": "550e8400-e29b-41d4-a716-446655440000"
},
{
"index": 1,
"success": false,
"error": "Invalid timestamp format"
}
]
}
Error responses
400 bad request
Empty events array:
{
"success": false,
"error": "Invalid request body",
"batchId": "unknown",
"processed": 0,
"failed": 0,
"results": []
}
Large batch (>100 events):
{
"success": false,
"error": "Batch size exceeds maximum (100 events)",
"batchId": "batch_123...",
"processed": 0,
"failed": 101,
"results": []
}
Invalid event structure:
{
"success": false,
"error": "Invalid request body",
"details": [
{
"path": "events.0.timestamp",
"message": "Required"
}
],
"batchId": "batch_123...",
"processed": 0,
"failed": 1,
"results": []
}
401 unauthorized
{
"error": "Invalid API key",
"valid": false
}
403 forbidden
{
"success": false,
"error": "Vendor ID mismatch",
"batchId": "batch_123...",
"processed": 0,
"failed": 1,
"results": []
}
429 too many requests
{
"error": "Rate limit exceeded"
}
Rate limiting
- Limit: 100 batches per minute per API key
- Window: 1 minute rolling window
- Response: 429 Too Many Requests
Cors
The API supports CORS for cross-origin SDK requests:
- Allowed Origins:
* - Allowed Methods:
POST, OPTIONS - Allowed Headers:
Content-Type, X-API-Key
Batch processing
Events are processed in batches:
- Maximum batch size: 100 events
- Recommended batch size: 20 events (SDK default)
- Partial failures: Some events may succeed while others fail
- Per-event status: Response includes success/failure for each event
Database storage
Events are stored in the product_events table:
- Table:
product_events - Indexes: vendor_id, account_id, user_id, event_name
- Retention: Indefinite (for health scoring)
Sdk integration
The SDK EventTracker automatically:
- Queues events (up to 20 per batch)
- Flushes batches every 5 seconds
- Flushes on page unload using
sendBeacon() - Retries failed requests (max 3 retries)
You don't need to call this API directly - the SDK handles it!
Examples
Sdk usage
// SDK automatically batches and sends events
firstDistro.track('page_viewed', { page: '/dashboard' });
firstDistro.track('feature_used', { feature: 'export' });
// ... 18 more events
// → Automatically sends batch of 20 events
Manual api call
const response = await fetch('https://firstdistro.com/api/tracking/events/batch', {
method: 'POST',
headers: {
'X-API-Key': 'sk_live_your-api-key',
'Content-Type': 'application/json'
},
body: JSON.stringify({
events: [
{
eventName: 'custom_event',
properties: { custom: 'data' },
timestamp: new Date().toISOString(),
sessionId: 'sess_123',
userId: 'user_123',
accountId: 'acct_456',
context: {
url: window.location.href,
pathname: window.location.pathname,
userAgent: navigator.userAgent,
screenWidth: window.screen.width,
screenHeight: window.screen.height,
timestamp: new Date().toISOString()
}
}
],
vendorId: 'your-vendor-id',
batchId: `batch_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
})
});
const data = await response.json();
console.log(`Processed: ${data.processed}, Failed: ${data.failed}`);