Events API
Ingest events from SDKs and server-side integrations via EventsService.BatchCreate.
Service: EventsService
Auth: SDK API key
Protocol: Connect RPC
BatchCreate
Send one or more events in a single RPC call. This is the only ingestion method — there is no single-event endpoint.
Request
{
"events": [
{
"name": "page_view",
"properties": {
"path": "/pricing",
"title": "Pricing"
},
"timestamp": "2026-06-01T14:30:00Z",
"sessionId": "sess_abc123"
},
{
"name": "purchase",
"properties": {
"revenue": 29.99,
"currency": "USD",
"order_id": "ord-456"
},
"timestamp": "2026-06-01T14:32:00Z",
"sessionId": "sess_abc123"
}
]
}Request fields
| Field | Type | Required | Description |
|---|---|---|---|
events | array | Yes | One or more events (max batch size enforced server-side) |
events[].name | string | Yes | Event name |
events[].properties | map | No | Key-value properties (string, number, boolean) |
events[].timestamp | timestamp | No | Event time; defaults to server receive time |
events[].sessionId | string | No | Session identifier; SDK-managed in client integrations |
Response
{
"eventsCreated": 2
}TypeScript client
import { createClient } from '@connectrpc/connect'
import { createConnectTransport } from '@connectrpc/connect-web'
import { EventsService } from './gen/events/v1/events_connect'
const transport = createConnectTransport({
baseUrl: 'https://api.pug.sh',
interceptors: [
next => async req => {
req.header.set('Authorization', `Bearer ${process.env.PUG_SDK_API_KEY}`)
req.header.set('x-project-id', process.env.PUG_PROJECT_ID!)
return next(req)
}
]
})
const client = createClient(EventsService, transport)
await client.batchCreate({
events: [{
name: 'purchase',
properties: { revenue: 29.99, currency: 'USD', order_id: 'ord-456' },
timestamp: new Date()
}]
})curl (Connect protocol)
curl -X POST https://api.pug.sh/events.v1.EventsService/BatchCreate \
-H "Authorization: Bearer YOUR_SDK_API_KEY" \
-H "x-project-id: YOUR_PROJECT_ID" \
-H "Content-Type: application/json" \
-H "Connect-Protocol-Version: 1" \
-d '{
"events": [{
"name": "page_view",
"properties": {"path": "/home"}
}]
}'Pipeline
Events are processed asynchronously after ingestion:
BatchCreate
→ validate (protovalidate + well-known event schemas)
→ publish to NATS
→ event workers enrich:
$geo.country, $geo.city, $geo.region (from IP)
$browser, $browserVersion (from User-Agent)
$os, $device
$botScore (bot detection)
→ write to ClickHouse
→ available in Insights queriesTypical latency: 2–10 seconds from ingestion to appearing in Live.
Well-known events
Standard event names have protobuf-defined property schemas validated at ingestion:
{
"name": "purchase",
"properties": {
"revenue": 29.99,
"currency": "USD",
"order_id": "ord-456"
}
}Invalid properties on well-known events return invalid_argument. See Well-known events.
Custom event names skip schema validation — any properties accepted.
Batching guidance
| Context | Recommendation |
|---|---|
| Browser SDK | Use client-side batching (default) — SDK handles this |
| Server-side high volume | Batch up to server limit per RPC call |
| Critical conversions | Send immediately in a single-event batch |
| Offline replay | Batch by time window; set accurate timestamp |
The Web SDK batches client-side with localStorage persistence. Server integrations should batch for efficiency but send critical events immediately.
Querying events
Events are not queried directly via EventsService. Use:
- InsightsService — aggregations, funnels, retention
- ProfilesService — per-user event history
- ActivityService — recent activity feeds
- Dashboard Events page — catalog and schema
Errors
| Error | Cause | Fix |
|---|---|---|
unauthenticated | Invalid API key | Check Settings → API keys |
invalid_argument on name | Empty event name | Provide non-empty string |
invalid_argument on properties | Schema validation failed | Check Well-known events |
invalid_argument on batch size | Too many events in one call | Reduce batch size |
Further reading
- Tracking events — SDK usage
- Well-known events — schemas
- Auto-properties — server-enriched fields