# Create Event
Source: https://docs.emitkit.com/api-reference/events/create-event
api-reference/openapi.json post /v1/events
Creates a new event and optionally sends push notifications to connected devices.
## Channel Auto-Creation
If the specified channel doesn't exist, it will be automatically created.
This reduces setup complexity for simple integrations.
## Notifications
Set `notify: true` (default) to send push notifications to devices connected through PWA or browsers that have accepted notifications (e.g., Chrome).
# Identify User
Source: https://docs.emitkit.com/api-reference/identity/identify-user
api-reference/openapi.json post /v1/identify
Creates or updates a user identity with custom properties and aliases.
## User Identity
User identities store custom properties about your users (email, name, plan, etc.)
and allow you to track events by user ID.
## Aliases
Aliases let you reference the same user by multiple identifiers:
- Email addresses
- Usernames
- External system IDs
- Social media handles
## Idempotency
User identity creation is naturally idempotent. Calling identify multiple times
for the same userId will update the properties without creating duplicates.
## Property Merging
Properties are **replaced** on each identify call, not merged. Include all
properties you want to keep.
# API Reference
Source: https://docs.emitkit.com/api-reference/introduction
Complete EmitKit API documentation
## Overview
The EmitKit API provides a simple, RESTful interface for monitoring critical product moments and sending real-time alerts.
**Base URL**: `https://api.emitkit.com`
## Authentication
All API requests require authentication using a Bearer token in the `Authorization` header:
```bash theme={null}
Authorization: Bearer emitkit_xxxxxxxxxxxxxxxxxxxxx
```
Create API keys in your dashboard at Settings → API Keys.
Keep in mind that API keys are scoped to organizations and projects.
## Rate Limiting
* **Default**: 100 requests per minute per API key
* Rate limit information is returned in response headers:
* `X-RateLimit-Limit`: Maximum requests allowed
* `X-RateLimit-Remaining`: Remaining requests in current window
* `X-RateLimit-Reset`: Unix timestamp when limit resets
When you exceed the rate limit, you'll receive a `429 Too Many Requests` response.
## Idempotency
To safely retry requests without creating duplicates, include an `Idempotency-Key` header:
```bash theme={null}
Idempotency-Key: payment-123-retry-1
```
* Idempotency keys are valid for 24 hours
* Replayed requests return the original response with an `X-Idempotent-Replay: true` header
* Use this for webhooks, payment processing, or any operation you want to make retry-safe
## Request IDs
Every response includes a `requestId` field for debugging and support purposes:
```json theme={null}
{
"success": true,
"data": { ... },
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
```
Include the request ID when contacting support.
## Response Format
All successful responses follow this format:
```json theme={null}
{
"success": true,
"data": {
// Response data
},
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
```
Error responses:
```json theme={null}
{
"success": false,
"error": "Error message",
"details": [
// Validation errors (if applicable)
],
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
```
## Error Handling
### HTTP Status Codes
* `200` - Success (identify endpoint)
* `201` - Created (event created)
* `400` - Bad Request (validation error)
* `401` - Unauthorized (missing or invalid API key)
* `429` - Too Many Requests (rate limit exceeded)
* `500` - Internal Server Error
### Validation Errors
When your request fails validation, you'll receive a `400` response with details:
```json theme={null}
{
"success": false,
"error": "Validation error",
"details": [
{
"path": ["channelName"],
"message": "Required"
}
],
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
```
## Endpoints
### Events
Create a new event and optionally send notifications
### Identity
Create or update user identity with properties and aliases
### Meta
Get the OpenAPI 3.1 specification
## SDKs
We provide official SDKs for easy integration:
Official SDK with full type safety
```bash theme={null}
npm install @emitkit/js
```
Direct HTTP requests for any language
See code examples on each endpoint
## Quick Example
```typescript TypeScript theme={null}
import { EmitKit } from '@emitkit/js';
const client = new EmitKit('emitkit_xxxxxxxxxxxxxxxxxxxxx');
await client.events.create({
channelName: 'payments',
title: 'Payment Received',
metadata: { amount: 99.99 }
});
```
```bash cURL theme={null}
curl -X POST https://api.emitkit.com/v1/events \
-H "Authorization: Bearer emitkit_xxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"channelName": "payments",
"title": "Payment Received",
"metadata": {"amount": 99.99}
}'
```
## Next Steps
Learn about the TypeScript SDK
Send your first event in 5 minutes
Understand EmitKit's architecture
Deploy your own EmitKit instance
# Get OpenAPI Specification
Source: https://docs.emitkit.com/api-reference/meta/get-openapi-specification
api-reference/openapi.json get /api/openapi.json
Returns the OpenAPI 3.1 specification for this API in JSON format
# Authentication
Source: https://docs.emitkit.com/concepts/authentication
API keys and security
## Authentication
EmitKit uses Bearer token authentication with API keys scoped to organizations and projects.
```bash theme={null}
Authorization: Bearer emitkit_xxxxxxxxxxxxxxxxxxxxx
```
See [API Reference](/api-reference/introduction) for complete documentation.
# Events & Channels
Source: https://docs.emitkit.com/concepts/events
Understanding events and channel organization
## Events
Events are the core building block of EmitKit. Each event represents something that happened in your application.
## Channels
Channels organize events into categories like "payments", "user-activity", or "system-alerts". Channels are created automatically when you send an event.
See [Overview](/concepts/overview) for architecture details.
# Multi-tenancy
Source: https://docs.emitkit.com/concepts/multi-tenancy
Organization and project structure
## Multi-tenancy
EmitKit supports multi-tenancy with a hierarchical structure:
Organization → Project → Channel → Event
See [Overview](/concepts/overview) for architecture details.
# Push Notifications
Source: https://docs.emitkit.com/concepts/notifications
Real-time browser notifications with Web Push
## Push Notifications
EmitKit supports Web Push notifications using the VAPID protocol for secure, real-time browser notifications.
See [Overview](/concepts/overview) for architecture details.
# Core Concepts
Source: https://docs.emitkit.com/concepts/overview
Understanding EmitKit's architecture and design
## What is EmitKit?
EmitKit is an event streaming and notification platform focused on **awareness, not analysis**. It monitors critical product moments - signups, cancellations, payments - and alerts you in real-time.
Unlike analytics platforms that track everything, EmitKit focuses on pivotal business events that matter.
## Architecture
* **Organizations**: Top-level accounts
* **Projects**: Individual products or applications within an organization
* **Channels**: Event categories (payments, user-activity, etc.)
* **Events**: Individual occurrences with metadata
## Key Features
* Real-time push notifications (PWA and browser)
* Multi-tenancy support (organizations and projects)
* Webhook triggers with HMAC signatures
* Channel-based event organization
* Type-safe TypeScript SDK
See [Events](/concepts/events) for more details.
# Webhooks
Source: https://docs.emitkit.com/concepts/webhooks
HTTP POST dispatching with HMAC signatures
## Webhooks
Configure webhooks to receive HTTP POST notifications when events occur. All webhooks are signed with HMAC for security.
See [Overview](/concepts/overview) for architecture details.
# Welcome to EmitKit
Source: https://docs.emitkit.com/index
Monitor critical product moments with real-time alerts
## What is EmitKit?
EmitKit is an open-source event streaming and notification platform that monitors critical product moments. Get instant alerts about signups, cancellations, payments, and other pivotal business events - **awareness, not analysis**.
Get started in minutes with our quick start guide
Deploy your own EmitKit instance
Official TypeScript/JavaScript SDK with full type safety
Explore the complete API documentation
## Key Features
Browser push notifications and mobile PWA support for critical events
Organize events into channels like Slack - payments, signups, cancellations
Automate workflows and integrations when events occur
TypeScript SDK with autocomplete - setup in under 5 minutes
Deploy on your infrastructure with Vercel or host anywhere
AGPL-3.0 licensed - built on ClickHouse and Tinybird
## Quick Example
```typescript theme={null}
import { EmitKit } from '@emitkit/js';
const client = new EmitKit('emitkit_xxxxxxxxxxxxxxxxxxxxx');
// Create an event
await client.events.create({
channelName: 'payments',
title: 'Payment Received',
description: 'User upgraded to Pro plan',
icon: '💰',
metadata: {
amount: 99.99,
currency: 'USD'
}
});
// Identify users with aliases
await client.identify({
user_id: 'user_123',
properties: {
email: 'john@example.com',
name: 'John Doe',
plan: 'pro'
},
aliases: ['john@example.com', 'johndoe']
});
```
## Use Cases
Get instant alerts for signups, trial activations, payment receipts, and cancellations. Stay aware of what's happening in your product without checking dashboards.
Stop constantly refreshing analytics dashboards. EmitKit pushes critical moments to you in real-time via browser or mobile notifications.
Trigger webhooks when important events occur - send Slack messages, update CRMs, or kick off automation workflows.
Keep your entire team in sync with what's happening. Organize events into channels so everyone sees what matters to them.
## Why EmitKit?
Focus on critical moments, not comprehensive analytics. Know when important things happen without the noise.
Install the SDK, get an API key, and start tracking events. No complex configuration or dashboards to learn.
Deploy on your infrastructure. Full data ownership. Built on battle-tested tech: ClickHouse, PostgreSQL, SvelteKit.
## Tech Stack
* **Framework**: [SvelteKit](https://kit.svelte.dev/) with [Svelte 5](https://svelte.dev/)
* **Database**: PostgreSQL with [Drizzle ORM](https://orm.drizzle.team/)
* **Event Storage**: [Tinybird](https://www.tinybird.co/) (ClickHouse)
* **Authentication**: [Better Auth](https://www.better-auth.com/)
* **UI Components**: [shadcn-svelte](https://www.shadcn-svelte.com/) + [Tailwind CSS](https://tailwindcss.com/)
## Get Started
Install the SDK and send your first event in 5 minutes
Deploy your own EmitKit instance with our comprehensive guide
## Community & Support
Star us on GitHub and contribute to the project
Join the community, ask questions, and share feedback
# Installation
Source: https://docs.emitkit.com/installation
Install and set up the EmitKit SDK
## Installation
Install the EmitKit TypeScript/JavaScript SDK using your preferred package manager:
```bash npm theme={null}
npm install @emitkit/js
```
```bash pnpm theme={null}
pnpm add @emitkit/js
```
```bash yarn theme={null}
yarn add @emitkit/js
```
## Requirements
* Node.js 16+ or modern browser
* TypeScript 4.5+ (optional, but recommended)
## Basic Setup
```typescript theme={null}
import { EmitKit } from '@emitkit/js';
const client = new EmitKit('emitkit_xxxxxxxxxxxxxxxxxxxxx');
```
## Next Steps
Send your first event in 5 minutes
Learn about all SDK features
Deploy your own instance
Complete API documentation
# Quickstart
Source: https://docs.emitkit.com/quickstart
Get started with EmitKit in under 5 minutes
## Get Started in 3 Steps
Monitor your first critical product moment and get instant alerts.
### Step 1: Get an API Key
You'll need an EmitKit API key to get started. You can either:
* Sign up for a hosted account at [emitkit.com](https://emitkit.com)
* [Self-host EmitKit](/self-hosting/overview) on your own infrastructure
1. Log into your dashboard
2. Navigate to Settings → API Keys
3. Click "Create API Key"
4. Copy your API key (it starts with `emitkit_`)
Keep in mind that API keys are scoped to organizations and projects.
### Step 2: Install the SDK
```bash npm theme={null}
npm install @emitkit/js
```
```bash pnpm theme={null}
pnpm add @emitkit/js
```
```bash yarn theme={null}
yarn add @emitkit/js
```
### Step 3: Send Your First Event
```typescript TypeScript theme={null}
import { EmitKit } from '@emitkit/js';
// Initialize the client
const client = new EmitKit('emitkit_xxxxxxxxxxxxxxxxxxxxx');
// Send an event
const result = await client.events.create({
channelName: 'general',
title: 'Hello from EmitKit!',
description: 'My first event',
icon: '👋'
});
console.log('Event created:', result.data.id);
```
```javascript JavaScript theme={null}
const { EmitKit } = require('@emitkit/js');
// Initialize the client
const client = new EmitKit('emitkit_xxxxxxxxxxxxxxxxxxxxx');
// Send an event
const result = await client.events.create({
channelName: 'general',
title: 'Hello from EmitKit!',
description: 'My first event',
icon: '👋'
});
console.log('Event created:', result.data.id);
```
**Success!** You've sent your first event. You should see it in your EmitKit dashboard immediately.
## Next Steps
Now that you've sent your first event, explore more features:
Identify users and track events by user ID
Attach custom data to your events
Handle errors and rate limits properly
Explore the full API documentation
## Common Patterns
### Monitor Critical Events
```typescript theme={null}
import { EmitKit } from '@emitkit/js';
const client = new EmitKit('your_api_key');
// Get alerted when a user signs up
await client.events.create({
channelName: 'signups',
title: 'New user signed up',
userId: 'user_123',
metadata: {
email: 'user@example.com',
source: 'google',
plan: 'free'
}
});
```
### Send Notifications
```typescript theme={null}
// Send a notification
await client.events.create({
channelName: 'alerts',
title: 'Payment Failed',
description: 'Credit card declined',
icon: '⚠️',
notify: true
});
```
### Track Payments
```typescript theme={null}
await client.events.create({
channelName: 'payments',
title: 'Payment Received',
description: 'User upgraded to Pro plan',
icon: '💰',
userId: 'user_123',
tags: ['payment', 'upgrade'],
metadata: {
amount: 99.99,
currency: 'USD',
plan: 'pro',
transactionId: 'txn_abc123'
}
});
```
### Identify Users
```typescript theme={null}
// Create user identity with aliases
await client.identify({
user_id: 'user_123',
properties: {
email: 'john@example.com',
name: 'John Doe',
plan: 'pro',
signupDate: '2025-01-15'
},
aliases: [
'john@example.com', // Email
'johndoe', // Username
'ext_12345' // External system ID
]
});
// Now you can reference the user by any alias
await client.events.create({
channelName: 'activity',
title: 'User logged in',
userId: 'john@example.com', // ← Alias works!
});
```
## Environment Variables
**Best Practice**: Store your API key in environment variables, not in your code.
```bash .env theme={null}
EMITKIT_API_KEY=emitkit_xxxxxxxxxxxxxxxxxxxxx
```
```typescript app.ts theme={null}
import { EmitKit } from '@emitkit/js';
const client = new EmitKit(process.env.EMITKIT_API_KEY);
```
## Configuration Options
```typescript theme={null}
const client = new EmitKit('your_api_key', {
// Custom base URL (for self-hosted instances)
baseUrl: 'https://api.your-domain.com',
// Request timeout in milliseconds
timeout: 30000,
// Custom fetch implementation (optional)
fetch: customFetch
});
```
## Need Help?
Learn about all SDK features and capabilities
Complete API endpoint documentation
Deploy your own EmitKit instance
Get help from the community
# Advanced Features
Source: https://docs.emitkit.com/sdk/advanced
Idempotency, retries, and advanced SDK usage
## Idempotency
Prevent duplicate events with idempotency keys:
```typescript theme={null}
const result = await client.events.create(
{
channelName: 'payments',
title: 'Payment Received',
metadata: { paymentId: 'pay_123' }
},
{ idempotencyKey: 'payment-pay_123-webhook' }
);
console.log('Was replayed:', result.wasReplayed);
```
## Rate Limit Tracking
```typescript theme={null}
const result = await client.events.create({...});
console.log(result.rateLimit);
// Access last known rate limit
console.log(client.rateLimit);
```
See [TypeScript SDK](/sdk/typescript) for complete documentation.
# Error Handling
Source: https://docs.emitkit.com/sdk/error-handling
Handle errors and rate limits with the SDK
## Error Types
The SDK provides type-safe error classes:
```typescript theme={null}
import {
EmitKitError,
RateLimitError,
ValidationError
} from '@emitkit/js';
try {
await client.events.create({...});
} catch (error) {
if (error instanceof RateLimitError) {
console.log(`Retry in ${error.rateLimit.resetIn}ms`);
} else if (error instanceof ValidationError) {
console.log('Validation errors:', error.validationErrors);
}
}
```
See [TypeScript SDK](/sdk/typescript) for complete documentation.
# Creating Events
Source: https://docs.emitkit.com/sdk/events
Learn how to create and manage events with the SDK
## Creating Events
Use the `events.create()` method to send events to EmitKit:
```typescript theme={null}
await client.events.create({
channelName: 'payments',
title: 'Payment Received',
description: 'User upgraded to Pro plan',
icon: '💰',
metadata: {
amount: 99.99,
currency: 'USD'
}
});
```
## With User Tracking
```typescript theme={null}
await client.events.create({
channelName: 'user-activity',
title: 'User Signed Up',
userId: 'user_123',
metadata: {
email: 'user@example.com',
plan: 'free'
}
});
```
See [TypeScript SDK](/sdk/typescript) for complete documentation.
# User Identification
Source: https://docs.emitkit.com/sdk/identify
Identify users and manage aliases
## Identifying Users
Create or update user identities with custom properties:
```typescript theme={null}
await client.identify({
user_id: 'user_123',
properties: {
email: 'john@example.com',
name: 'John Doe',
plan: 'pro'
},
aliases: ['john@example.com', 'johndoe']
});
```
## Using Aliases
Reference users by any alias in events:
```typescript theme={null}
await client.events.create({
channelName: 'activity',
title: 'User Logged In',
userId: 'john@example.com', // ← Alias works!
});
```
See [TypeScript SDK](/sdk/typescript) for complete documentation.
# SDK Installation
Source: https://docs.emitkit.com/sdk/installation
Install and configure the EmitKit SDK
## Installation
```bash npm theme={null}
npm install @emitkit/js
```
```bash pnpm theme={null}
pnpm add @emitkit/js
```
```bash yarn theme={null}
yarn add @emitkit/js
```
## Requirements
* Node.js 16+
* TypeScript 4.5+ (optional)
## Basic Setup
```typescript theme={null}
import { EmitKit } from '@emitkit/js';
const client = new EmitKit('emitkit_xxxxxxxxxxxxxxxxxxxxx');
```
See [Quick Start](/quickstart) for a complete guide.
# TypeScript SDK
Source: https://docs.emitkit.com/sdk/typescript
Official TypeScript/JavaScript SDK for EmitKit
## Overview
The EmitKit TypeScript/JavaScript SDK provides a type-safe, developer-friendly interface for monitoring critical product moments and sending real-time alerts.
## Features
Full TypeScript support with auto-generated types
No external runtime dependencies, minimal bundle size
Type-safe error classes with detailed information
Automatic rate limit tracking and handling
Built-in support for safe retries
Optimized bundle size with ES modules
## Installation
```bash npm theme={null}
npm install @emitkit/js
```
```bash pnpm theme={null}
pnpm add @emitkit/js
```
```bash yarn theme={null}
yarn add @emitkit/js
```
## Basic Usage
```typescript theme={null}
import { EmitKit } from '@emitkit/js';
const client = new EmitKit('emitkit_xxxxxxxxxxxxxxxxxxxxx');
// Create an event
const result = await client.events.create({
channelName: 'payments',
title: 'Payment Received',
metadata: { amount: 99.99 }
});
console.log('Event ID:', result.data.id);
console.log('Rate limit remaining:', result.rateLimit.remaining);
```
## Configuration
### Basic Configuration
```typescript theme={null}
const client = new EmitKit('your_api_key');
```
### Advanced Configuration
```typescript theme={null}
const client = new EmitKit('your_api_key', {
// Custom base URL (for self-hosted instances)
baseUrl: 'https://api.your-domain.com',
// Request timeout in milliseconds (default: 30000)
timeout: 60000,
// Custom fetch implementation
fetch: customFetch
});
```
## Methods
### events.create()
Create a new event and optionally send notifications.
**Parameters:**
* `channelName` (string, required): Channel name (auto-creates if doesn't exist)
* `title` (string, required): Event title
* `description` (string, optional): Event description
* `icon` (string, optional): Single emoji icon
* `tags` (string\[], optional): Array of tags
* `metadata` (object, optional): Custom JSON metadata
* `userId` (string | null, optional): User identifier
* `notify` (boolean, optional): Send push notification to connected devices (default: true)
* `source` (string, optional): Source identifier
**Options:**
* `idempotencyKey` (string): For safe retries
* `timeout` (number): Request timeout override
* `headers` (object): Additional headers
**Returns:** `Promise`
```typescript theme={null}
const result = await client.events.create({
channelName: 'payments',
title: 'Payment Received',
description: 'User upgraded to Pro plan',
icon: '💰',
tags: ['payment', 'upgrade'],
metadata: {
amount: 99.99,
currency: 'USD',
plan: 'pro'
},
userId: 'user_123',
notify: true
});
```
### identify()
Create or update a user identity with properties and aliases.
**Parameters:**
* `user_id` (string, required): Your internal user ID
* `properties` (object, optional): Custom user properties
* `aliases` (string\[], optional): Alternative identifiers
**Returns:** `Promise>`
```typescript theme={null}
await client.identify({
user_id: 'user_123',
properties: {
email: 'john@example.com',
name: 'John Doe',
plan: 'pro'
},
aliases: ['john@example.com', 'johndoe']
});
```
## Response Types
### EmitKitResponse
```typescript theme={null}
interface EmitKitResponse {
data: T; // Response data
rateLimit: RateLimitInfo; // Rate limit info
requestId: string; // Request ID for debugging
wasReplayed: boolean; // Idempotent replay flag
}
```
### RateLimitInfo
```typescript theme={null}
interface RateLimitInfo {
limit: number; // Max requests allowed
remaining: number; // Remaining requests
reset: number; // Unix timestamp when limit resets
resetIn: number; // Milliseconds until reset
}
```
## Error Handling
The SDK provides type-safe error classes for different error scenarios:
```typescript theme={null}
import {
EmitKit,
EmitKitError,
RateLimitError,
ValidationError
} from '@emitkit/js';
try {
await client.events.create({...});
} catch (error) {
if (error instanceof RateLimitError) {
console.log('Rate limit exceeded!');
console.log(`Retry in ${error.rateLimit.resetIn}ms`);
} else if (error instanceof ValidationError) {
console.log('Validation failed:');
error.validationErrors.forEach(err => {
console.log(`- ${err.path.join('.')}: ${err.message}`);
});
} else if (error instanceof EmitKitError) {
console.log(`API Error ${error.statusCode}:`, error.message);
console.log('Request ID:', error.requestId);
}
}
```
See [Error Handling](/sdk/error-handling) for detailed documentation.
## Rate Limit Tracking
Access rate limit information from responses:
```typescript theme={null}
const result = await client.events.create({...});
console.log(result.rateLimit);
// {
// limit: 100,
// remaining: 95,
// reset: 1733270400,
// resetIn: 45000
// }
// Access last known rate limit
console.log(client.rateLimit);
```
## Next Steps
Learn about event creation and metadata
Identify users and manage aliases
Handle errors and rate limits
Idempotency, retries, and more
# Configuration
Source: https://docs.emitkit.com/self-hosting/configuration
Configure environment variables
## Configuration
Copy and configure environment variables:
```bash theme={null}
cp .env.example .env
```
See [Tinybird Setup](/self-hosting/tinybird) for event storage configuration.
# Deployment
Source: https://docs.emitkit.com/self-hosting/deployment
Deploy to production
## Deployment
Deploy EmitKit to Vercel or your preferred hosting platform.
See [Overview](/self-hosting/overview) for more information.
# Installation
Source: https://docs.emitkit.com/self-hosting/installation
Install and configure EmitKit
## Installation
Clone and install dependencies:
```bash theme={null}
git clone https://github.com/emitkit/emitkit-cloud.git
cd emitkit-cloud
pnpm install
```
See [Configuration](/self-hosting/configuration) for environment setup.
# Self-Hosting Overview
Source: https://docs.emitkit.com/self-hosting/overview
Deploy your own EmitKit instance
## Self-Hosting EmitKit
EmitKit is AGPL-3.0 open-source and designed to be self-hosted on your own infrastructure.
## Why Self-Host?
* **Data ownership**: Keep all event data on your infrastructure
* **Privacy**: Full control over your business-critical event data
* **Customization**: Modify and extend EmitKit for your specific needs
* **Zero cost**: No per-event or per-user pricing when self-hosted
## Requirements
* Node.js 18+
* PostgreSQL database
* Tinybird account (for event storage)
* Redis (optional, for caching)
See [Prerequisites](/self-hosting/prerequisites) for detailed requirements.
# Prerequisites
Source: https://docs.emitkit.com/self-hosting/prerequisites
Requirements for self-hosting EmitKit
## Prerequisites
* Node.js 18+ and pnpm
* PostgreSQL database
* Tinybird account
* Redis (optional)
See [Installation](/self-hosting/installation) for setup instructions.
# Tinybird Setup
Source: https://docs.emitkit.com/self-hosting/tinybird
Configure Tinybird for event storage
## Tinybird Setup
EmitKit uses Tinybird (ClickHouse) for event storage:
```bash theme={null}
cd tinybird
tb auth
tb push --force
```
See [Deployment](/self-hosting/deployment) for production setup.
# Troubleshooting
Source: https://docs.emitkit.com/self-hosting/troubleshooting
Common issues and solutions
## Troubleshooting
Common issues and solutions for self-hosting EmitKit.
See [Overview](/self-hosting/overview) for more information.