Puffn Documentation

Welcome to the Puffn API documentation. Learn how to track events and query your analytics data.

Coming Soon

Puffn is currently in development. Join our waitlist to get early access when we launch.

Overview

Puffn provides a simple REST API for tracking events and querying analytics data. Our API is built with performance in mind, using Rust and ClickHouse to deliver blazing fast analytics for your applications.

Simple REST API

Easy-to-use REST API for sending events and querying data based on timeframes.

Bring Your Own Charts

Use your favorite charting library with our data. Works with Recharts, Chart.js, and more.

Blazing Fast

Built with Rust and ClickHouse for incredible performance, even with billions of events.

Authentication

All API requests require authentication using an API key. You'll need to include your API key in theX-API-Keyheader with every request.

authentication-example.js
fetch('https://api.puffn.io/events', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': 'your_api_key'
},
body: JSON.stringify({
event: 'page_view',
properties: {
page: '/dashboard'
}
})
}

Installation

Puffn doesn't require any client-side SDK. You can use the REST API directly with any HTTP client. However, we provide some helper libraries for popular frameworks.

npm install @puffn/react

API Reference

Events API

The Events API allows you to track events in your application. Events can be anything from page views to button clicks to custom actions.

POST
/events

Request Body

{
"event": "page_view",
"properties": {
"page": "/dashboard",
"referrer": "https://google.com",
"user_id": "123"
}
}

Response

{
"success": true,
"id": "evt_123456789"
}

Query API

The Query API allows you to retrieve analytics data based on events, metrics, and timeframes.

POST
/query

Request Body

{
"metric": "count",
"event": "page_view",
"timeframe": {
"start": "2025-01-01T00:00:00Z",
"end": "2025-01-31T23:59:59Z"
},
"interval": "day"
}

Response

[
{
"date": "2025-01-01",
"value": 42
},
{
"date": "2025-01-02",
"value": 57
},
// ... more data points
]

Metrics

Metrics define what type of calculation to perform on your event data. Here are the available metrics:

MetricDescription
countCount of events
uniqueCount of unique values for a property (requires property parameter)
sumSum of values for a property (requires property parameter)
avgAverage of values for a property (requires property parameter)
min/maxMinimum or maximum value for a property (requires property parameter)

Timeframes

Timeframes define the period for which you want to retrieve data. You can specify a custom timeframe with start and end dates, or use one of the predefined timeframes:

TimeframeDescription
todayData for the current day
yesterdayData for the previous day
this_weekData for the current week
last_weekData for the previous week
this_monthData for the current month
last_monthData for the previous month

Examples

React + Recharts Example

Here's an example of how to use Puffn with React and Recharts to create a simple analytics dashboard.

analytics-dashboard.jsx
import {useState, useEffect} from 'react';
import {BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer} from 'recharts';
// Create a secure API route in your Next.js app (app/api/analytics/route.js)
// to proxy requests to Puffn and keep your API key secure
export default function AnalyticsDashboard() {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Fetch data from your secure API endpoint
fetch('/api/analytics', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
metric: 'count',
event: 'page_view',
timeframe: { start: '2025-04-01', end: '2025-04-30' },
interval: 'day'
})
})
.then(res => res.json())
.then(data => {
setData(data);
setLoading(false);
})
.catch(err => {
console.error('Error fetching analytics:', err);
setLoading(false);
});
}, []);
if (loading) return <div>Loading analytics data...</div>;
return (
<div className="h-80 w-full">
<ResponsiveContainer width="100%" height="100%">
<BarChart data={data}>
<XAxis dataKey="date" />
<YAxis />
<Tooltip />
<Bar dataKey="value" fill="#FF8A3D" />
</BarChart>
</ResponsiveContainer>
</div>
);
}

Node.js Example

Here's an example of how to use Puffn with Node.js to track server-side events.

server.js
import express from 'express';
import fetch from 'node-fetch';
import dotenv from 'dotenv';
// Load environment variables
dotenv.config();
const app = express();
const port = 3000;
const PUFFN_API_KEY = process.env.PUFFN_API_KEY;
app.use(express.json());
// Track API usage
app.use(async (req, res, next) => {
const startTime = Date.now();
res.on('finish', async () => {
const duration = Date.now() - startTime;
try {
await fetch('https://api.puffn.io/events', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': PUFFN_API_KEY
},
body: JSON.stringify({
event: 'api_request',
properties: {
path: req.path,
method: req.method,
status_code: res.statusCode,
duration_ms: duration,
user_id: req.user?.id
}
})
})
} catch (error) {
console.error('Failed to track event:', error);
}
});
next();
})
app.get('/', (req, res) => {
res.send('Hello World!');
})
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
})

Secure API Route Example

Here's an example of how to create a secure API route in Next.js to proxy requests to Puffn while keeping your API key secure on the server.

app/api/analytics/route.js
// app/api/analytics/route.js
export async function POST( request) {
try {
const body = await request.json();
// You can add validation here
const response = await fetch('https://api.puffn.io/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.PUFFN_API_KEY // Securely access API key on server
},
body: JSON.stringify(body)
});
const data = await response.json();
if (!response.ok) {
return Response.json({ error: data.message ||'Failed to fetch analytics' }, { status: response.status });
}
return Response.json(data);
} catch (error) {
console.error('Analytics API error:', error);
return Response.json({ error:'Internal server error' }, { status: 500 });
}
}