Documentation Index
Fetch the complete documentation index at: https://docs.fanfare.io/llms.txt
Use this file to discover all available pages before exploring further.
Analytics API
The Analytics API provides access to metrics and reporting data using a flexible DSL (Domain Specific Language) for querying.
Query Analytics
Execute an analytics query using the metrics DSL.
POST /api/v1/analytics/query
Authentication
Request Body
interface QueryRequest {
measures: Measure[];
timeRange: string; // e.g., "7d", "30d", "90d"
granularity?: "hour" | "day" | "week" | "month";
filters?: Filter[];
groupBy?: string[];
}
interface Measure {
name: string; // Unique name for this measure
event: string; // Event type to measure
op: "count" | "sum" | "avg" | "min" | "max";
field?: string; // Field for sum/avg operations
unit?: "number" | "currency";
filters?: Filter[];
}
interface Filter {
field: string;
operator: "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "contains";
value: string | number | string[];
}
Supported Events
| Event | Description |
|---|
queue_entry | Consumer entered a queue |
queue_admit | Consumer admitted from queue |
queue_exit | Consumer left queue |
draw_entry | Consumer entered a draw |
draw_win | Consumer won a draw |
auction_bid | Bid placed on auction |
auction_win | Auction won |
order_created | Order was created |
order_completed | Order was completed |
Supported Fields for Aggregation
| Event | Fields |
|---|
order_created | orderValue, itemCount |
order_completed | orderValue, itemCount |
auction_bid | bidAmount |
auction_win | winningBid |
Response
interface QueryResponse {
measures: MeasureResult[];
timeRange: {
start: string;
end: string;
};
currencyCode: string;
}
interface MeasureResult {
name: string;
value: number;
unit: "number" | "currency";
series?: SeriesPoint[];
}
interface SeriesPoint {
timestamp: string;
value: number;
}
Example: Basic Query
Query queue entries and admissions for the last 7 days:
curl -X POST https://admin.fanfare.io/api/v1/analytics/query \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"measures": [
{
"name": "total_queue_entries",
"event": "queue_entry",
"op": "count"
},
{
"name": "total_admissions",
"event": "queue_admit",
"op": "count"
}
],
"timeRange": "7d"
}'
Response:
{
"measures": [
{
"name": "total_queue_entries",
"value": 15420,
"unit": "number"
},
{
"name": "total_admissions",
"value": 12850,
"unit": "number"
}
],
"timeRange": {
"start": "2024-11-24T00:00:00Z",
"end": "2024-12-01T00:00:00Z"
},
"currencyCode": "USD"
}
Example: Time Series Query
Query order revenue by day:
curl -X POST https://admin.fanfare.io/api/v1/analytics/query \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"measures": [
{
"name": "daily_revenue",
"event": "order_completed",
"op": "sum",
"field": "orderValue",
"unit": "currency"
}
],
"timeRange": "30d",
"granularity": "day"
}'
Response:
{
"measures": [
{
"name": "daily_revenue",
"value": 125000.0,
"unit": "currency",
"series": [
{ "timestamp": "2024-11-01T00:00:00Z", "value": 4250.0 },
{ "timestamp": "2024-11-02T00:00:00Z", "value": 3800.0 },
{ "timestamp": "2024-11-03T00:00:00Z", "value": 5100.0 }
]
}
],
"timeRange": {
"start": "2024-11-01T00:00:00Z",
"end": "2024-12-01T00:00:00Z"
},
"currencyCode": "USD"
}
Example: Filtered Query
Query queue entries for a specific experience:
curl -X POST https://admin.fanfare.io/api/v1/analytics/query \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"measures": [
{
"name": "experience_entries",
"event": "queue_entry",
"op": "count",
"filters": [
{
"field": "experienceId",
"operator": "eq",
"value": "exp_01HXYZ123456789"
}
]
}
],
"timeRange": "7d"
}'
Example: Multiple Measures
Query conversion funnel metrics:
curl -X POST https://admin.fanfare.io/api/v1/analytics/query \
-H "Authorization: Bearer sk_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"measures": [
{
"name": "queue_entries",
"event": "queue_entry",
"op": "count"
},
{
"name": "admissions",
"event": "queue_admit",
"op": "count"
},
{
"name": "orders",
"event": "order_created",
"op": "count"
},
{
"name": "revenue",
"event": "order_completed",
"op": "sum",
"field": "orderValue",
"unit": "currency"
},
{
"name": "avg_order_value",
"event": "order_completed",
"op": "avg",
"field": "orderValue",
"unit": "currency"
}
],
"timeRange": "30d"
}'
Guardrails
The analytics API enforces the following limits:
| Limit | Value |
|---|
| Maximum measures per query | 10 |
| Maximum time range | 90 days |
| Rate limit | 100 queries per minute |
Error Responses
| Status | Error | Description |
|---|
| 400 | Too many measures (max 10) | Exceeded measure limit |
| 400 | Requested timeRange exceeds the allowed maximum (90d) | Time range too large |
| 400 | Event 'xxx' is not supported | Invalid event type |
| 400 | Measure 'xxx' requires a field when using 'sum' | Missing field for aggregation |
| 400 | Field 'xxx' is not allowed for event 'yyy' | Invalid field for event |
| 401 | Unauthorized | Missing or invalid authentication |
| 404 | Organization not found | Invalid organization |
SDK Usage
import { FanfareAdmin } from "@fanfare/admin-sdk";
const admin = new FanfareAdmin({
secretKey: process.env.FANFARE_SECRET_KEY,
});
// Basic query
const result = await admin.analytics.query({
measures: [
{ name: "total_entries", event: "queue_entry", op: "count" },
{ name: "total_revenue", event: "order_completed", op: "sum", field: "orderValue", unit: "currency" },
],
timeRange: "30d",
});
console.log(`Total Entries: ${result.measures[0].value}`);
console.log(`Total Revenue: ${result.measures[1].value} ${result.currencyCode}`);
// Time series query
const timeSeries = await admin.analytics.query({
measures: [{ name: "daily_entries", event: "queue_entry", op: "count" }],
timeRange: "7d",
granularity: "day",
});
// Access series data
timeSeries.measures[0].series?.forEach((point) => {
console.log(`${point.timestamp}: ${point.value}`);
});
Common Use Cases
Conversion Rate
const result = await admin.analytics.query({
measures: [
{ name: "entries", event: "queue_entry", op: "count" },
{ name: "orders", event: "order_created", op: "count" },
],
timeRange: "30d",
});
const conversionRate = (result.measures[1].value / result.measures[0].value) * 100;
console.log(`Conversion Rate: ${conversionRate.toFixed(2)}%`);
Daily Active Users
const result = await admin.analytics.query({
measures: [{ name: "daily_users", event: "queue_entry", op: "count" }],
timeRange: "30d",
granularity: "day",
});
Revenue by Day
const result = await admin.analytics.query({
measures: [{ name: "revenue", event: "order_completed", op: "sum", field: "orderValue", unit: "currency" }],
timeRange: "30d",
granularity: "day",
});