SDK Reference
Official Node.js & browser client for Enrich.sh.
Installation
npm install enrich.shWorks in Node.js, browsers, and edge workers (Cloudflare Workers, Deno, Bun).
Quick Start
import { Enrich } from 'enrich.sh'
const enrich = new Enrich('sk_live_your_api_key')
// Buffer events (auto-flushes when ready)
enrich.track('page_views', {
url: window.location.href,
user_id: 'user_123',
})
// Or send immediately
await enrich.ingest('page_views', [
{ url: '/home', user_id: 'user_123' },
{ url: '/pricing', user_id: 'user_456' },
])Constructor
new Enrich(apiKey: string, options?: EnrichOptions)| Parameter | Type | Required | Description |
|---|---|---|---|
apiKey | string | ✅ | Your API key (sk_live_* or sk_test_*) |
options | EnrichOptions | ❌ | Configuration options |
EnrichOptions
| Option | Type | Default | Description |
|---|---|---|---|
baseUrl | string | https://enrich.sh | API base URL |
Example:
const enrich = new Enrich('sk_live_your_key')
// Custom base URL (self-hosted / staging)
const enrich = new Enrich('sk_test_your_key', {
baseUrl: 'https://staging.enrich.sh',
})TIP
Batching, flush timing, and retries are managed automatically by the SDK. No configuration needed — we handle optimal delivery for you.
Methods
track(streamId, event)
Buffer a single event for automatic batched delivery. The SDK handles batching and flush timing automatically for optimal throughput.
track(streamId: string, event: Record<string, unknown>): void| Parameter | Type | Description |
|---|---|---|
streamId | string | Target stream identifier |
event | object | Event payload (any JSON-serializable object) |
enrich.track('events', {
event: 'page_view',
url: '/pricing',
user_id: 'user_123',
})TIP
A _ts field (Unix millisecond timestamp) is automatically added to each tracked event.
ingest(streamId, data)
Send events immediately without buffering.
ingest(streamId: string, data: object | object[]): Promise<IngestResponse>| Parameter | Type | Description |
|---|---|---|
streamId | string | Target stream identifier |
data | object or object[] | Single event or array of events |
Returns: Promise<IngestResponse>
interface IngestResponse {
accepted: number
buffered: number
}// Single event
await enrich.ingest('events', { event: 'signup', user_id: 'u_123' })
// Batch
await enrich.ingest('events', [
{ event: 'page_view', url: '/home' },
{ event: 'page_view', url: '/pricing' },
])flush(streamId?)
Force-flush buffered events. Normally you don't need to call this — the SDK auto-flushes. Use it before shutdown or when you need guaranteed delivery.
flush(streamId?: string): Promise<void>// Flush one stream
await enrich.flush('events')
// Flush all streams
await enrich.flush()query(streamId, params?)
Get presigned URLs for stored Parquet files. Pass directly to DuckDB's read_parquet().
query(streamId: string, params?: QueryParams): Promise<string[]>QueryParams
| Parameter | Type | Description |
|---|---|---|
date | string | Single day — YYYY-MM-DD |
start | string | Range start — YYYY-MM-DD |
end | string | Range end — YYYY-MM-DD |
days | number | Last N days |
// Last 7 days
const urls = await enrich.query('events', { days: 7 })
// Date range
const urls = await enrich.query('events', {
start: '2026-02-01',
end: '2026-02-07',
})
// Use with DuckDB
await conn.query(
`SELECT * FROM read_parquet(${JSON.stringify(urls)})`
)queryDetailed(streamId, params?)
Same as query() but returns full metadata.
queryDetailed(streamId: string, params?: QueryParams): Promise<QueryDetailedResponse>interface QueryDetailedResponse {
success: boolean
stream_id: string
file_count: number
urls: string[]
files: FileInfo[]
expires_at: string
}
interface FileInfo {
key: string
url: string
size: number
uploaded_at: string
}const result = await enrich.queryDetailed('events', { days: 7 })
console.log(`${result.file_count} files, expires ${result.expires_at}`)beacon(streamId?)
Best-effort flush that survives page unload/tab close. Uses fetch({ keepalive: true }) with proper Authorization headers. Fire-and-forget — does not return a Promise.
beacon(streamId?: string): void// Recommended: call on page unload
window.addEventListener('beforeunload', () => {
enrich.beacon()
})
// Or flush a specific stream
enrich.beacon('events')INFO
Unlike navigator.sendBeacon(), this method supports custom headers (Authorization), so your API key never appears in the URL.
destroy()
Flush all buffers and stop timers. Call before shutdown.
destroy(): Promise<void>// Clean shutdown
await enrich.destroy()Full Example
Edge / Service Worker
import { Enrich } from 'enrich.sh'
const enrich = new Enrich('sk_live_your_key')
// Track navigation events
chrome.webNavigation.onCompleted.addListener((details) => {
enrich.track('navigation', {
url: details.url,
tab_id: details.tabId,
})
})
// Flush before extension unloads
chrome.runtime.onSuspend.addListener(() => {
enrich.beacon()
})Node.js Server
import { Enrich } from 'enrich.sh'
const enrich = new Enrich('sk_live_your_key')
// Track API requests
app.use((req, res, next) => {
enrich.track('api_logs', {
method: req.method,
path: req.path,
status: res.statusCode,
duration_ms: Date.now() - req.startTime,
})
next()
})
// Clean shutdown
process.on('SIGTERM', async () => {
await enrich.destroy()
process.exit(0)
})Querying with DuckDB
import { Enrich } from 'enrich.sh'
import duckdb from 'duckdb'
const enrich = new Enrich('sk_live_your_key')
// Get presigned URLs
const urls = await enrich.query('events', { days: 30 })
// Query with DuckDB
const db = new duckdb.Database(':memory:')
const conn = db.connect()
conn.run(`
SELECT event, COUNT(*) as count
FROM read_parquet(${JSON.stringify(urls)})
GROUP BY event
ORDER BY count DESC
`, (err, result) => {
console.table(result)
})