Introduction
Pulse Analytics is a privacy-friendly, self-hosted web analytics platform built in Rust. It provides real-time pageview tracking, custom events, user segmentation, funnel analysis, A/B testing, surveys, error tracking, and more — all through a single, fast API.
Base URL
https://pulse.ayushojha.com
All API endpoints are relative to this base URL. The API accepts and returns JSON unless otherwise noted (e.g., CSV exports).
Production Runtime
The reference deployment uses the current stable Rust and Node toolchains, PostgreSQL 18, Redis 8, and Debian Trixie runtime images. Configure these environment variables before running the server:
| Variable | Purpose |
|---|---|
DATABASE_URL | PostgreSQL connection string used by migrations, ingestion, and query APIs. |
REDIS_URL | Redis connection string for buffering, rate limits, and background work. |
PULSE_ADMIN_TOKEN | Bearer token for project, key, module, and webhook administration. |
PULSE_COOKIE_SECRET | Secret used to sign dashboard cookies. Set explicitly in production. |
EMAIL_REPORT_WEBHOOK_URL | Optional delivery endpoint for scheduled email report payloads. |
ALLOWED_ORIGINS | Comma-separated list of browser origins allowed to call the API. |
Quick Start
Get Your API Keys
Register your project with the admin API and create ingest + query scoped API keys.
Add the Tracking Script
Drop a single <script> tag into your site’s HTML before the closing </body> tag.
View Your Dashboard
Open pulse.ayushojha.com/dashboard and log in with your query-scoped API key.
<!-- Add before </body> -->
<script defer
src="https://pulse.ayushojha.com/api/script.js"
data-api="https://pulse.ayushojha.com"
data-key="pa_live_YOUR_INGEST_KEY"></script>
Authentication
Pulse uses API key authentication for all data operations and bearer-token authentication for admin endpoints.
API Key Authentication
Pass your project API key in one of two ways:
| Method | Example |
|---|---|
| Header (preferred) | X-Pulse-Key: pa_live_YOUR_KEY |
| Query parameter | ?key=pa_live_YOUR_KEY |
Admin Token Authentication
Administrative endpoints (creating projects, managing keys) require the admin bearer token:
Authorization: Bearer <PULSE_ADMIN_TOKEN>
API Key Scopes
Each API key has one or more scopes that determine its permissions:
| Scope | Permissions | Typical Use |
|---|---|---|
ingest | Write tracking data (pageviews, events, errors, etc.) | Frontend tracking script |
query | Read analytics data (stats, reports, exports) | Dashboard access, API queries |
admin | Full access including key management | Backend administration |
Module Restrictions
API keys can optionally be restricted to specific modules via the allowed_modules field. When set, the key can only access the listed modules. When null or empty, the key has access to all enabled modules for the project.
Module System
Pulse features a configurable module system that lets you enable or disable feature sets per project. Each module controls access to related API endpoints and data collection. Modules have access levels: read, write, or all (both).
Available Modules
Pulse ships with 33 modules across five categories:
Core
core
Core analytics: pageviews, sessions, events, devices, geo, referrers, realtime
identity
User profiles, IDs, aliases, traits, accounts, and SCIM provisioning
Analysis
segments
Saved behavioral and identity-based visitor segments
dashboards
Custom dashboards, saved reports, query explorer, and product insights
funnels
Multi-step conversion funnels
goals
Goal and conversion tracking
retention
User retention cohort analysis
cohorts
Grouped cohort metric comparison
paths
User navigation path analysis
bi
Safe SQL, embeds, external connections, semantic metrics, visual queries, and CSV uploads
Tracking
utm
UTM campaign parameter tracking
webvitals
Core Web Vitals (LCP, FCP, CLS, INP, TTFB)
scroll
Scroll depth measurement per page
revenue
Revenue and ecommerce event tracking
search
Internal site search query tracking
outlinks
External link clicks and file download tracking
error_tracking
JavaScript error capture and grouping
logs
Application log ingestion with release filtering
Experience & Experimentation
feature_flags
Feature flags, remote config, targeting rules, and rollout evaluation
ab_testing
A/B experiment management and results
session_replay
Privacy-masked session recording and playback
heatmaps
Click heatmap data collection
surveys
In-app survey builder and response collection
ai_queries
Natural-language analytics answers, generated insights, and query history
predictions
Predictive analytics and churn probability
Platform
exports
CSV data export for all report types
integrations
Integrations marketplace catalog for sources, destinations, SDKs, and imports
sources
Source catalog, webhook collection, ingestion audit, and source tokens
destinations
Destination catalog, event routing, retries, and dead letters
sharing
Password-protected shared dashboards
governance
Tracking plans, event schemas, data dictionary, and quality monitoring
email_reports
Scheduled analytics digests via delivery webhook
alerts
Threshold-based alert rules and notifications
Module Admin Endpoints
List all modules and their current status for a project.
curl -H "Authorization: Bearer <ADMIN_TOKEN>" \
https://pulse.ayushojha.com/api/admin/projects/4c3654c3-9274-4fea-bc3e-30b8edcd7f7a/modules
{
"modules": [
{ "name": "pageviews", "enabled": true, "access": "all" },
{ "name": "events", "enabled": true, "access": "all" },
{ "name": "funnels", "enabled": false, "access": "read" },
{ "name": "ab_testing", "enabled": false, "access": "read" }
]
}
Bulk update module settings for a project.
curl -X PUT \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"modules": [
{"name": "funnels", "enabled": true, "access": "all"},
{"name": "ab_testing", "enabled": true, "access": "all"},
{"name": "heatmaps", "enabled": false}
]
}' \
https://pulse.ayushojha.com/api/admin/projects/4c3654c3-9274-4fea-bc3e-30b8edcd7f7a/modules
Enable a single module.
curl -X POST \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
https://pulse.ayushojha.com/api/admin/projects/4c3654c3-9274-4fea-bc3e-30b8edcd7f7a/modules/funnels/enable
Disable a single module. Existing data is preserved but API access is revoked.
curl -X POST \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
https://pulse.ayushojha.com/api/admin/projects/4c3654c3-9274-4fea-bc3e-30b8edcd7f7a/modules/heatmaps/disable
Set the access level for a module: read, write, or all.
curl -X PUT \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"access": "read"}' \
https://pulse.ayushojha.com/api/admin/projects/4c3654c3-9274-4fea-bc3e-30b8edcd7f7a/modules/surveys/access
Tracking Script
The easiest way to integrate Pulse is with the lightweight JavaScript tracking script. It automatically captures pageviews, handles SPAs, and supports optional modules like Web Vitals, scroll depth, outbound link tracking, and more.
HTML Snippet Installation
<script defer
src="https://pulse.ayushojha.com/api/script.js"
data-api="https://pulse.ayushojha.com"
data-key="pa_live_YOUR_INGEST_KEY"
data-utm="true"
data-vitals="true"
data-scroll="true"
data-outlinks="true"
data-errors="true"
data-clicks="true"
data-replay="true"
data-replay-sample="0.25"
data-replay-mask="true"
data-search="true"
data-search-param="q"
data-consent-mode="analytics"
data-consent-granted="true"
data-release="2026.05.09"
data-environment="production"
data-dnt="true"></script>
Data Attributes
| Attribute | Default | Description |
|---|---|---|
data-key | — | Required. Your project ingest API key. |
data-api | https://pulse.ayushojha.com | API base URL. Override for self-hosted instances. |
data-utm | false | Capture UTM parameters from query strings. |
data-vitals | false | Collect Core Web Vitals (LCP, FCP, CLS, INP, TTFB). |
data-scroll | false | Track maximum scroll depth per page. |
data-outlinks | false | Track clicks on outbound links. |
data-errors | false | Capture unhandled JavaScript errors. |
data-clicks | false | Record click coordinates for heatmaps. |
data-replay | false | Record privacy-masked session replay events. |
data-replay-sample | 1 | Replay sampling rate from 0 to 1. |
data-replay-mask | true | Mask form input values in replay events. |
data-search | false | Track internal site search queries. |
data-search-param | q | URL query parameter name for search queries. |
data-consent-mode | analytics | Consent mode sent with collection requests. |
data-consent-granted | true | Set to false until a visitor grants consent when consent is required. |
data-release | — | Release/version tag attached to captured errors and logs. |
data-environment | production | Environment tag attached to captured errors and logs. |
data-dnt | true | Respect browser Do Not Track setting. |
JavaScript API
Use the global pulse() function to send custom data programmatically:
Custom Event Tracking
// Track a custom event
pulse("event", {
name: "button_click",
data: { button_id: "cta-hero", variant: "blue" }
});
// Track an event with revenue
pulse("event", {
name: "purchase",
revenue_amount: 49.99,
revenue_currency: "USD",
data: { plan: "pro", billing: "annual" }
});
Search Query Tracking
// Track a search query
pulse("search", {
query: "deployment guide",
results_count: 12
});
Application Log Submission
// Submit an application log with release metadata from the script config
pulse("log", "warn", "Checkout retry", {
order_id: "ord_123",
retry_count: 2
});
Survey Response Submission
// Submit survey response
pulse("survey_response", {
survey_id: "c7f3e8a2-91b4-4d6e-b2f1-8a3c9d4e5f6a",
answers: [
{ question_id: "q1", value: "Very satisfied" },
{ question_id: "q2", value: 9 }
],
completed: true
});
TypeScript SDK
Client-side (Browser)
npm install @ayushojha/pulse-analytics
import { PulseClient } from '@ayushojha/pulse-analytics';
const pulse = new PulseClient({
apiKey: 'pa_live_YOUR_INGEST_KEY',
apiUrl: 'https://pulse.ayushojha.com',
trackUtm: true,
trackWebVitals: true,
trackScrollDepth: true
});
// Track custom events
pulse.event('signup_complete', { method: 'google' });
// Track revenue
pulse.event('purchase', { plan: 'pro' }, 29.99, 'USD');
Server-side (Node.js)
import { PulseServerClient } from '@ayushojha/pulse-analytics/server';
const pulse = new PulseServerClient({
apiKey: 'pa_live_YOUR_INGEST_KEY',
apiUrl: 'https://pulse.ayushojha.com'
});
// Server-side event
await pulse.trackEvent({
visitorId: 'visitor_123',
eventName: 'subscription_renewed',
data: { plan: 'enterprise', mrr: 499 }
});
React / Vue / Next.js helpers
import { PulseProvider, usePulsePageview } from '@ayushojha/pulse-analytics/react';
function App({ children }) {
return (
<PulseProvider config={{ apiKey: 'pa_live_YOUR_INGEST_KEY', apiUrl: 'https://pulse.ayushojha.com' }}>
{children}
</PulseProvider>
);
}
function Page() {
usePulsePageview();
}
import { createApp } from 'vue';
import { createPulseVue, usePulsePageview } from '@ayushojha/pulse-analytics/vue';
const app = createApp(App);
app.use(createPulseVue({
config: { apiKey: 'pa_live_YOUR_INGEST_KEY', apiUrl: 'https://pulse.ayushojha.com' }
}));
export default {
setup() {
usePulsePageview();
}
};
import Script from 'next/script';
import { getPulseScriptProps } from '@ayushojha/pulse-analytics/next';
<Script
{...getPulseScriptProps({
apiKey: 'pa_live_YOUR_INGEST_KEY',
apiUrl: 'https://pulse.ayushojha.com',
trackWebVitals: true,
strategy: 'afterInteractive'
})}
/>
React Native mobile SDK
import { createPulseNative } from '@ayushojha/pulse-analytics/react-native';
const pulse = createPulseNative({
apiKey: 'pa_live_YOUR_INGEST_KEY',
apiUrl: 'https://pulse.ayushojha.com',
visitorId: 'device_or_user_scoped_id',
environment: 'production'
});
await pulse.screen('Home');
await pulse.event('purchase', { plan: 'pro' }, 29.99, 'USD');
await pulse.identify('user_123', { plan: 'pro' });
Ingestion API
All tracking data flows through a single universal collection endpoint. The payload type determines which module processes the data.
Universal data collection endpoint. Accepts any payload type.
| Header | Value |
|---|---|
X-Pulse-Key | Your ingest-scoped API key |
Content-Type | application/json |
Payload Types
POST pageview
Record a page view. Sent automatically by the tracking script.
curl -X POST https://pulse.ayushojha.com/api/collect \
-H "X-Pulse-Key: pa_live_8B57VGhehP5C2R8rnP535YYs" \
-H "Content-Type: application/json" \
-d '{
"type": "pageview",
"path": "/pricing",
"title": "Pricing - Acme Corp",
"referrer": "https://google.com",
"screen": "1920x1080",
"language": "en-US",
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "spring_sale",
"utm_content": "banner_a",
"utm_term": "analytics tool"
}'
{ "ok": true }
POST event
Track a custom event with optional metadata and revenue.
curl -X POST https://pulse.ayushojha.com/api/collect \
-H "X-Pulse-Key: pa_live_8B57VGhehP5C2R8rnP535YYs" \
-H "Content-Type: application/json" \
-d '{
"type": "event",
"name": "add_to_cart",
"path": "/products/widget-pro",
"data": {
"product_id": "prod_8x92k",
"product_name": "Widget Pro",
"quantity": 2
},
"revenue_amount": 59.98,
"revenue_currency": "USD"
}'
POST identify
Persist a user profile for the current visitor. Include user_id when the visitor is known; anonymous trait-only identifies are also stored.
curl -X POST https://pulse.ayushojha.com/api/collect \
-H "X-Pulse-Key: pa_live_8B57VGhehP5C2R8rnP535YYs" \
-H "Content-Type: application/json" \
-d '{
"type": "identify",
"visitor_id": "v_7fz9k2",
"payload": {
"user_id": "user_123",
"traits": {
"plan": "pro",
"company": "Acme Corp",
"role": "admin",
"signed_up": "2025-08-14"
}
}
}'
POST web_vital
Submit a Core Web Vital measurement.
curl -X POST https://pulse.ayushojha.com/api/collect \
-H "X-Pulse-Key: pa_live_8B57VGhehP5C2R8rnP535YYs" \
-H "Content-Type: application/json" \
-d '{
"type": "web_vital",
"name": "LCP",
"value": 1842.5,
"rating": "good",
"path": "/home"
}'
POST scroll_depth
Report the maximum scroll depth reached on a page (0-100).
curl -X POST https://pulse.ayushojha.com/api/collect \
-H "X-Pulse-Key: pa_live_8B57VGhehP5C2R8rnP535YYs" \
-H "Content-Type: application/json" \
-d '{
"type": "scroll_depth",
"path": "/blog/getting-started",
"max_depth": 87
}'
POST search_query
Track an internal site search query and result count.
curl -X POST https://pulse.ayushojha.com/api/collect \
-H "X-Pulse-Key: pa_live_8B57VGhehP5C2R8rnP535YYs" \
-H "Content-Type: application/json" \
-d '{
"type": "search_query",
"query": "pricing plans",
"results_count": 7,
"path": "/search"
}'
POST outlink
Track an outbound link click.
curl -X POST https://pulse.ayushojha.com/api/collect \
-H "X-Pulse-Key: pa_live_8B57VGhehP5C2R8rnP535YYs" \
-H "Content-Type: application/json" \
-d '{
"type": "outlink",
"url": "https://github.com/acme/widget",
"link_type": "external",
"path": "/docs"
}'
POST js_error
Report a JavaScript error with stack trace.
curl -X POST https://pulse.ayushojha.com/api/collect \
-H "X-Pulse-Key: pa_live_8B57VGhehP5C2R8rnP535YYs" \
-H "Content-Type: application/json" \
-d '{
"type": "js_error",
"visitor_id": "v_7fz9k2",
"payload": {
"message": "TypeError: Cannot read properties of null (reading '\''id'\'')",
"stack": "TypeError: Cannot read properties of null\n at handleClick (app.js:142:18)\n at onClick (react-dom.js:3905:14)",
"filename": "https://acme.com/assets/app.js",
"lineno": 142,
"colno": 18,
"path": "/dashboard",
"release": "2026.05.09",
"environment": "production"
}
}'
POST log
Submit an application log entry for release-aware troubleshooting.
curl -X POST https://pulse.ayushojha.com/api/collect \
-H "X-Pulse-Key: pa_live_8B57VGhehP5C2R8rnP535YYs" \
-H "Content-Type: application/json" \
-d '{
"type": "log",
"visitor_id": "v_7fz9k2",
"payload": {
"level": "warn",
"message": "Checkout retry",
"body": { "order_id": "ord_123", "retry_count": 2 },
"path": "/checkout",
"release": "2026.05.09",
"environment": "production"
}
}'
POST click_event
Record a click event with coordinates for heatmap generation.
curl -X POST https://pulse.ayushojha.com/api/collect \
-H "X-Pulse-Key: pa_live_8B57VGhehP5C2R8rnP535YYs" \
-H "Content-Type: application/json" \
-d '{
"type": "click_event",
"path": "/pricing",
"x": 482,
"y": 1203,
"element_selector": "button.cta-primary",
"viewport_width": 1440,
"viewport_height": 900
}'
POST survey_response
Submit a user’s response to an active survey.
curl -X POST https://pulse.ayushojha.com/api/collect \
-H "X-Pulse-Key: pa_live_8B57VGhehP5C2R8rnP535YYs" \
-H "Content-Type: application/json" \
-d '{
"type": "survey_response",
"visitor_id": "v_7fz9k2",
"payload": {
"survey_id": "c7f3e8a2-91b4-4d6e-b2f1-8a3c9d4e5f6a",
"answers": [
{"question_id": "q1", "value": "Very satisfied"},
{"question_id": "q2", "value": 9},
{"question_id": "q3", "value": "Love the real-time dashboard!"}
],
"completed": true,
"path": "/app/settings"
}
}'
Core Analytics API
These endpoints are always available regardless of module configuration. They provide the fundamental analytics data for your project. All endpoints require a query-scoped API key.
start_at (ISO 8601), end_at (ISO 8601), limit (default 10), and offset (default 0) unless otherwise noted.Overview metrics for the specified date range, with comparison to the previous period of equal length.
| Parameter | Type | Description |
|---|---|---|
start_at | string | Period start (ISO 8601). Default: 30 days ago. |
end_at | string | Period end (ISO 8601). Default: now. |
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/stats?start_at=2026-03-01T00:00:00Z&end_at=2026-03-22T23:59:59Z"
{
"current": {
"pageviews": 14832,
"visitors": 3241,
"sessions": 4567,
"bounce_rate": 42.3,
"avg_duration": 187.5,
"events": 2891
},
"previous": {
"pageviews": 12104,
"visitors": 2890,
"sessions": 3921,
"bounce_rate": 45.1,
"avg_duration": 162.8,
"events": 2340
}
}
Daily time series of core metrics within the date range.
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/stats/timeseries?start_at=2026-03-15&end_at=2026-03-22"
{
"data": [
{ "date": "2026-03-15", "pageviews": 687, "visitors": 198, "sessions": 245 },
{ "date": "2026-03-16", "pageviews": 524, "visitors": 161, "sessions": 203 },
{ "date": "2026-03-17", "pageviews": 731, "visitors": 212, "sessions": 278 },
{ "date": "2026-03-18", "pageviews": 812, "visitors": 234, "sessions": 301 },
{ "date": "2026-03-19", "pageviews": 695, "visitors": 189, "sessions": 256 },
{ "date": "2026-03-20", "pageviews": 903, "visitors": 267, "sessions": 342 },
{ "date": "2026-03-21", "pageviews": 778, "visitors": 221, "sessions": 289 },
{ "date": "2026-03-22", "pageviews": 411, "visitors": 134, "sessions": 167 }
]
}
Top pages ranked by views.
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/pages?limit=5"
{
"data": [
{ "path": "/", "views": 4821, "unique_views": 2190, "avg_duration": 45.2 },
{ "path": "/pricing", "views": 2314, "unique_views": 1820, "avg_duration": 92.7 },
{ "path": "/docs/getting-started", "views": 1892, "unique_views": 1456, "avg_duration": 214.3 },
{ "path": "/blog/analytics-guide", "views": 1203, "unique_views": 987, "avg_duration": 312.1 },
{ "path": "/signup", "views": 891, "unique_views": 834, "avg_duration": 67.8 }
],
"total": 47
}
Traffic sources ranked by visitor count.
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/referrers?limit=5"
{
"data": [
{ "source": "(direct)", "visitors": 1245, "pageviews": 3891 },
{ "source": "google.com", "visitors": 892, "pageviews": 2104 },
{ "source": "twitter.com", "visitors": 341, "pageviews": 567 },
{ "source": "github.com", "visitors": 287, "pageviews": 445 },
{ "source": "reddit.com", "visitors": 198, "pageviews": 312 }
]
}
Custom events ranked by count.
{
"data": [
{ "name": "signup_complete", "count": 423, "unique": 412 },
{ "name": "add_to_cart", "count": 312, "unique": 287 },
{ "name": "purchase", "count": 89, "unique": 84 },
{ "name": "newsletter_subscribe", "count": 67, "unique": 65 }
]
}
Visitor breakdown by browser, operating system, and device type.
{
"browsers": [
{ "name": "Chrome", "visitors": 1842, "percentage": 56.8 },
{ "name": "Safari", "visitors": 723, "percentage": 22.3 },
{ "name": "Firefox", "visitors": 412, "percentage": 12.7 }
],
"operating_systems": [
{ "name": "Windows", "visitors": 1456, "percentage": 44.9 },
{ "name": "macOS", "visitors": 987, "percentage": 30.5 },
{ "name": "iOS", "visitors": 534, "percentage": 16.5 }
],
"device_types": [
{ "name": "Desktop", "visitors": 2198, "percentage": 67.8 },
{ "name": "Mobile", "visitors": 845, "percentage": 26.1 },
{ "name": "Tablet", "visitors": 198, "percentage": 6.1 }
]
}
Visitor distribution by country.
{
"data": [
{ "country": "US", "visitors": 1567, "percentage": 48.3 },
{ "country": "GB", "visitors": 412, "percentage": 12.7 },
{ "country": "DE", "visitors": 298, "percentage": 9.2 },
{ "country": "IN", "visitors": 234, "percentage": 7.2 },
{ "country": "CA", "visitors": 189, "percentage": 5.8 }
]
}
Count of active visitors on the site right now (within the last 5 minutes).
{
"active_visitors": 23
}
Identity
Requires the identity module. Identify calls create or update visitor profiles, merge traits, record aliases when a stable user_id is provided, and can attach visitors to account or company records with account-level analytics. Local SCIM provisioning APIs can create users and groups without depending on a live external identity provider.
List stored user profiles. Supports limit and offset.
{
"data": [
{
"visitor_id": "v_7fz9k2",
"user_id": "user_123",
"traits": { "plan": "pro" },
"last_seen_at": "2026-05-09T18:22:14Z"
}
]
}
Fetch one visitor profile and its merged traits.
List visitor IDs aliased to a known user ID.
Return visitor, user, and account nodes plus alias, identify, and membership edges. Provide one or more of visitor_id, user_id, or account_id; optional limit caps graph expansion.
List account or company profiles captured from identify calls. Supports limit and offset.
Fetch one account profile with merged account traits.
List visitors and user IDs associated with an account, including role and last-seen timestamps.
Return account-level members, identified users, sessions, pageviews, events, and revenue for a date range.
List locally provisioned SCIM users. Supports limit and offset. Provisioned users are also synced into identity profiles with visitor IDs like scim:{id}.
Create a provisioned user with normalized profile fields, email array, active state, and arbitrary traits.
{
"user_name": "alice@example.com",
"external_id": "idp_123",
"active": true,
"display_name": "Alice Example",
"emails": [{ "value": "alice@example.com", "primary": true }],
"traits": { "department": "Engineering" }
}
Fetch, update, or delete one provisioned user. Updates refresh the synced identity profile.
List locally provisioned groups. Supports limit and offset.
Create a provisioned group and replace its member list with existing SCIM user IDs.
{
"display_name": "Engineering",
"external_id": "group_eng",
"traits": { "cost_center": "eng" },
"members": ["6d0aa190-5b2a-4b0e-9c8d-df7608e7aa8f"]
}
Fetch one provisioned group with expanded members, replace its group details and membership, or delete it.
UTM / Campaign Tracking
Requires the utm module to be enabled. Provides campaign-level analytics from UTM parameters captured during pageviews.
Campaign performance metrics grouped by UTM campaign name.
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/campaigns?start_at=2026-03-01&end_at=2026-03-22"
{
"data": [
{
"campaign": "spring_sale",
"visitors": 892,
"pageviews": 2341,
"bounce_rate": 38.2,
"avg_duration": 142.5
},
{
"campaign": "product_launch",
"visitors": 456,
"pageviews": 1023,
"bounce_rate": 44.7,
"avg_duration": 98.3
}
]
}
Top UTM sources (e.g., google, newsletter, twitter).
{
"data": [
{ "source": "google", "visitors": 1234, "pageviews": 3456 },
{ "source": "newsletter", "visitors": 567, "pageviews": 892 },
{ "source": "twitter", "visitors": 345, "pageviews": 512 }
]
}
Top UTM mediums (e.g., cpc, email, social).
{
"data": [
{ "medium": "cpc", "visitors": 1102, "pageviews": 2891 },
{ "medium": "email", "visitors": 678, "pageviews": 1234 },
{ "medium": "social", "visitors": 445, "pageviews": 678 }
]
}
Daily time series for a specific UTM source.
| Parameter | Type | Description |
|---|---|---|
utm_source | string | Required. Filter by UTM source. |
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/campaigns/timeseries?utm_source=google&start_at=2026-03-18&end_at=2026-03-22"
{
"data": [
{ "date": "2026-03-18", "visitors": 89, "pageviews": 234 },
{ "date": "2026-03-19", "visitors": 102, "pageviews": 287 },
{ "date": "2026-03-20", "visitors": 78, "pageviews": 198 },
{ "date": "2026-03-21", "visitors": 95, "pageviews": 256 },
{ "date": "2026-03-22", "visitors": 67, "pageviews": 178 }
]
}
Marketing Analytics
Requires the utm module. Marketing analytics adds channel grouping, attribution models, ecommerce revenue reports, AI referrer detection, and vendor-export imports for Google Analytics, Google Ads, and Search Console style data.
Group traffic into Direct, Organic Search, Paid Search, Organic Social, Paid Social, Email, Display, Affiliate, AI Referrals, Referral, Paid Other, and Other. Supports start_at and end_at.
Attribute revenue events by channel, source, and campaign. Supports model values first_touch, last_touch, and linear.
Return total orders, revenue, average order value, currency breakdown, and top revenue products from events with revenue_amount.
Detect traffic from ChatGPT/OpenAI, Perplexity, Claude/Anthropic, Gemini, and Copilot referrers.
List imported marketing export batches. Optional provider filters support google_analytics, google_ads, and search_console; pagination uses limit and offset.
Import rows from GA4, Google Ads, or Search Console exports without requiring live Google OAuth. Each row stores a date, dimension object, numeric metrics, and the original raw row for auditability.
{
"provider": "google_ads",
"name": "May brand campaigns",
"rows": [
{
"date": "2026-05-01",
"dimensions": { "campaign": "brand", "source": "google" },
"metrics": { "impressions": 12000, "clicks": 420, "cost": 318.44, "conversions": 31 },
"raw_row": { "Campaign": "brand", "Clicks": "420" }
}
],
"metadata": { "source": "csv_export" }
}
Page through imported rows for one batch. Use DELETE /api/v1/marketing/imports/{id} to remove a batch and all rows.
Summarize imported rows by date range and optional provider, returning rows, impressions, clicks, cost, conversions, revenue, sessions, and users.
Segments
Requires the segments module. Save reusable visitor definitions from identity traits, session properties, pageviews, events, and behavioral metrics, then evaluate, compare, and break them down by key properties.
Segment Definition
A segment definition has a match mode of all or any, plus a list of conditions. Supported sources are profile, session, pageview, event, and metric. Supported operators are exists, not_exists, eq, neq, contains, starts_with, ends_with, gt, gte, lt, lte, and in.
{
"match": "all",
"conditions": [
{
"source": "profile",
"field": "traits.plan",
"op": "eq",
"value": "pro"
},
{
"source": "event",
"event": "purchase",
"field": "event_data.amount",
"op": "gte",
"value": 100
}
]
}
List saved segments for the project.
{
"data": [
{
"id": "9f3d2e74-0a2b-45b7-a1d4-3b9fc6e4f2c8",
"name": "High-value pro users",
"description": "Pro users with recent purchases over $100",
"definition": { "match": "all", "conditions": [] },
"is_active": true
}
]
}
Create a saved segment.
curl -X POST -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
-H "Content-Type: application/json" \
-d '{"name":"High-value pro users","description":"Pro users with recent purchases","definition":{"match":"all","conditions":[{"source":"profile","field":"traits.plan","op":"eq","value":"pro"},{"source":"event","event":"purchase","field":"event_data.amount","op":"gte","value":100}]}}' \
https://pulse.ayushojha.com/api/v1/segments
Fetch one saved segment.
Update a segment’s name, description, definition, or active state.
Delete a saved segment.
Evaluate a segment over a date range and return matching visitor IDs. Supports start_at, end_at, limit, and offset.
{
"segment_id": "9f3d2e74-0a2b-45b7-a1d4-3b9fc6e4f2c8",
"total_visitors": 128,
"visitors": ["v_7fz9k2", "v_h3ab11"]
}
Compare traffic and conversion metrics across multiple saved segments. Pass comma-separated IDs via segment_ids.
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/segments/compare?segment_ids=9f3d2e74-0a2b-45b7-a1d4-3b9fc6e4f2c8,37b29685-1f73-4b72-88db-f6c71da79081&start_at=2026-04-01T00:00:00Z&end_at=2026-05-01T00:00:00Z"
Break down a segment by country, device, browser, os, path, event, or identity traits such as trait:plan. Supports start_at, end_at, and limit.
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/segments/9f3d2e74-0a2b-45b7-a1d4-3b9fc6e4f2c8/breakdown?property=trait:plan"
{
"data": [
{ "value": "pro", "visitors": 93 },
{ "value": "business", "visitors": 35 }
]
}
Funnels
Requires the funnels module. Define multi-step conversion funnels to understand where users drop off in key flows.
List all funnels for the project.
{
"data": [
{
"id": "f1a2b3c4-5678-9abc-def0-1234567890ab",
"name": "Signup Flow",
"steps": 4,
"created_at": "2026-02-14T10:30:00Z"
}
]
}
Create a new funnel. Steps are evaluated in order.
curl -X POST \
-H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
-H "Content-Type: application/json" \
-d '{
"name": "Signup Flow",
"steps": [
{"type": "pageview", "value": "/", "label": "Homepage"},
{"type": "pageview", "value": "/pricing", "label": "Pricing Page"},
{"type": "pageview", "value": "/signup", "label": "Signup Page"},
{"type": "event", "value": "signup_complete", "label": "Signup Complete"}
]
}' \
https://pulse.ayushojha.com/api/v1/funnels
{
"id": "f1a2b3c4-5678-9abc-def0-1234567890ab",
"name": "Signup Flow",
"steps": [
{ "type": "pageview", "value": "/", "label": "Homepage" },
{ "type": "pageview", "value": "/pricing", "label": "Pricing Page" },
{ "type": "pageview", "value": "/signup", "label": "Signup Page" },
{ "type": "event", "value": "signup_complete", "label": "Signup Complete" }
],
"created_at": "2026-03-22T14:30:00Z"
}
Get a specific funnel definition.
Update a funnel’s name or steps.
curl -X PUT \
-H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
-H "Content-Type: application/json" \
-d '{
"name": "Signup Flow v2",
"steps": [
{"type": "pageview", "value": "/", "label": "Homepage"},
{"type": "pageview", "value": "/signup", "label": "Signup Page"},
{"type": "event", "value": "signup_complete", "label": "Signup Complete"}
]
}' \
https://pulse.ayushojha.com/api/v1/funnels/f1a2b3c4-5678-9abc-def0-1234567890ab
Delete a funnel. Returns 204 No Content on success.
Analyze funnel performance. Returns visitor counts and drop-off rates for each step.
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/funnels/f1a2b3c4-5678-9abc-def0-1234567890ab/analyze?start_at=2026-03-01&end_at=2026-03-22"
{
"funnel_id": "f1a2b3c4-5678-9abc-def0-1234567890ab",
"name": "Signup Flow",
"steps": [
{ "label": "Homepage", "visitors": 3241, "drop_off": 0, "conversion_rate": 100.0 },
{ "label": "Pricing Page", "visitors": 1820, "drop_off": 1421, "conversion_rate": 56.2 },
{ "label": "Signup Page", "visitors": 834, "drop_off": 986, "conversion_rate": 45.8 },
{ "label": "Signup Complete", "visitors": 412, "drop_off": 422, "conversion_rate": 49.4 }
],
"overall_conversion": 12.7
}
Goals / Conversions
Requires the goals module. Define conversion goals based on pageviews, events, session duration, or pages per session, and track their performance.
List all configured goals.
{
"data": [
{
"id": "g9a8b7c6-5432-1fed-cba0-987654321012",
"name": "Completed Purchase",
"goal_type": "event",
"config": { "event_name": "purchase" },
"created_at": "2026-01-20T08:00:00Z"
},
{
"id": "g1b2c3d4-5678-9abc-def0-abcdef123456",
"name": "Visited Pricing",
"goal_type": "pageview",
"config": { "path": "/pricing" },
"created_at": "2026-01-20T08:15:00Z"
}
]
}
Create a new goal. Supported types: pageview, event, duration, pages_per_session.
curl -X POST \
-H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
-H "Content-Type: application/json" \
-d '{
"name": "Completed Purchase",
"goal_type": "event",
"config": {
"event_name": "purchase"
}
}' \
https://pulse.ayushojha.com/api/v1/goals
curl -X POST \
-H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
-H "Content-Type: application/json" \
-d '{
"name": "Engaged Session (>2min)",
"goal_type": "duration",
"config": {
"threshold_seconds": 120
}
}' \
https://pulse.ayushojha.com/api/v1/goals
Get a specific goal definition.
Update a goal’s name or configuration.
Delete a goal. Returns 204 No Content.
Get conversion statistics for a specific goal.
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/goals/g9a8b7c6-5432-1fed-cba0-987654321012/stats?start_at=2026-03-01&end_at=2026-03-22"
{
"goal_id": "g9a8b7c6-5432-1fed-cba0-987654321012",
"name": "Completed Purchase",
"conversions": 89,
"unique_visitors": 84,
"total_revenue": 4287.56,
"conversion_rate": 2.59
}
Retention
Requires the retention module. Analyze how well your product retains users over time with cohort-based retention tables.
Get retention cohorts showing return rates at various intervals.
| Parameter | Type | Description |
|---|---|---|
period | string | Cohort period: daily, weekly (default), or monthly. |
start_at | string | Period start (ISO 8601). |
end_at | string | Period end (ISO 8601). |
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/retention?period=weekly&start_at=2026-02-01&end_at=2026-03-22"
{
"period": "weekly",
"cohorts": [
{
"cohort": "2026-02-03",
"initial_visitors": 412,
"D1": 68.2,
"D7": 42.5,
"D14": 31.8,
"D30": 22.1,
"D60": 14.3,
"D90": null
},
{
"cohort": "2026-02-10",
"initial_visitors": 387,
"D1": 71.0,
"D7": 45.2,
"D14": 33.4,
"D30": 24.8,
"D60": null,
"D90": null
},
{
"cohort": "2026-02-17",
"initial_visitors": 445,
"D1": 65.8,
"D7": 39.7,
"D14": 28.9,
"D30": 19.6,
"D60": null,
"D90": null
}
]
}
Cohorts
Requires the cohorts module. Group visitors into cohorts and compare metrics across time periods.
Get cohort analysis data grouped by week or month.
| Parameter | Type | Description |
|---|---|---|
group_by | string | Grouping period: week (default) or month. |
metric | string | Metric to compare: pageviews, sessions, events, or revenue. |
start_at | string | Period start (ISO 8601). |
end_at | string | Period end (ISO 8601). |
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/cohorts?group_by=month&metric=sessions&start_at=2026-01-01&end_at=2026-03-22"
{
"group_by": "month",
"metric": "sessions",
"cohorts": [
{ "period": "2026-01", "visitors": 2890, "total": 3921, "avg_per_visitor": 1.36 },
{ "period": "2026-02", "visitors": 3105, "total": 4234, "avg_per_visitor": 1.36 },
{ "period": "2026-03", "visitors": 3241, "total": 4567, "avg_per_visitor": 1.41 }
]
}
Path Analysis
Requires the paths module. Discover the most common navigation flows before or after a given page.
Get page flow data showing where visitors go to or come from.
| Parameter | Type | Description |
|---|---|---|
path | string | Required. The pivot page path (e.g., /pricing). |
direction | string | forward (default) — where visitors go next. backward — where they came from. |
limit | integer | Number of paths to return. Default: 10. |
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/paths?path=/pricing&direction=forward&limit=5"
{
"path": "/pricing",
"direction": "forward",
"flows": [
{ "next_path": "/signup", "visitors": 456, "percentage": 25.1 },
{ "next_path": "/", "visitors": 312, "percentage": 17.1 },
{ "next_path": "/features", "visitors": 234, "percentage": 12.9 },
{ "next_path": "/docs", "visitors": 178, "percentage": 9.8 },
{ "next_path": "(exit)", "visitors": 640, "percentage": 35.2 }
]
}
Dashboards / Reports
Requires the dashboards module. Build custom dashboard layouts, persist report definitions, and run a safe query explorer over built-in analytics datasets. Supported report types are stats, timeseries, pages, referrers, events, devices, geo, and campaigns.
List custom dashboards for the project.
Create a dashboard layout with a validated widget array.
{
"name": "Growth Overview",
"description": "Acquisition and conversion health",
"layout": { "columns": 12 },
"widgets": [
{ "id": "trend", "report_type": "timeseries", "x": 0, "y": 0, "w": 8, "h": 4 },
{ "id": "sources", "report_type": "referrers", "x": 8, "y": 0, "w": 4, "h": 4 }
],
"is_default": true
}
Fetch one dashboard. Use PUT /api/v1/dashboards/{id} to update it, or DELETE /api/v1/dashboards/{id} to remove it.
List saved report definitions.
Save a reusable report definition for dashboards, sharing workflows, or API clients.
{
"name": "Top pages",
"report_type": "pages",
"params": {
"start_at": "2026-05-01T00:00:00Z",
"end_at": "2026-05-09T23:59:59Z",
"limit": 25
},
"visualization": "table",
"is_active": true
}
Fetch one saved report. Use PUT /api/v1/reports/{id} to update it, or DELETE /api/v1/reports/{id} to remove it.
Run a saved report. Optional start_at and end_at query parameters override the saved date range.
Run an ad hoc safe analytics query. The explorer does not accept raw SQL.
{
"report_type": "campaigns",
"start_at": "2026-05-01T00:00:00Z",
"end_at": "2026-05-09T23:59:59Z",
"limit": 20,
"offset": 0
}
{
"run": {
"id": "41078344-1d28-4c3a-80f6-b460f8718d4f",
"report_type": "campaigns",
"row_count": 8,
"result": { "data": [] }
},
"summary": "Returned 8 campaign rows."
}
List prior explorer runs. Supports limit and offset.
Product Insights
Requires the dashboards module. Product insight endpoints compute lifecycle, activation, stickiness, and before/after impact metrics from existing pageview, event, session, and error data.
Return DAU, WAU, MAU, DAU/WAU, WAU/MAU, DAU/MAU, and daily active visitor periods. Supports start_at and end_at.
Break active visitors into new, returning, resurrected, and dormant groups by comparing the selected range with the immediately preceding range.
Measure the share of active visitors who completed all required events and page paths in a date range.
{
"start_at": "2026-05-01T00:00:00Z",
"end_at": "2026-05-09T23:59:59Z",
"event_names": ["signup_completed", "workspace_created"],
"paths": ["/onboarding/done"]
}
Compare equal before/after windows around a launch, release, campaign, or experiment date. Supported metrics are pageviews, visitors, sessions, events, and errors.
{
"metric": "events",
"event_name": "checkout_completed",
"split_at": "2026-05-09T00:00:00Z",
"window_days": 7
}
BI Layer
Requires the bi module. The BI layer provides governed semantic metrics, external Postgres connections, embedded analytics links, row-level policies, saved read-only SQL, query run history, a visual query builder over approved datasets, drill-through detail rows, and JSON-row CSV uploads.
List semantic metric definitions. Use POST /api/v1/bi/metrics to create one with key, name, dataset, and expression.
Fetch one metric. Use PUT /api/v1/bi/metrics/{id} to update it, or DELETE /api/v1/bi/metrics/{id} to remove it.
List external BI database connections. Responses include a masked connection string, allowed schemas, status, last test time, and last error. Use POST /api/v1/bi/connections to register a Postgres connection.
Create a Postgres connection for external warehouse queries. Use least-privileged read-only credentials; Pulse runs external SQL in a read-only transaction and applies the configured search path.
{
"name": "Warehouse",
"database_type": "postgres",
"connection_string": "postgresql://readonly:secret@warehouse.example.com/analytics",
"allowed_schemas": ["public", "analytics"],
"is_active": true
}
Fetch one external connection. Use PUT /api/v1/bi/connections/{id} to rotate credentials or update schemas, or DELETE /api/v1/bi/connections/{id} to remove it.
Open the external database, set a read-only transaction and search path, run SELECT 1, and persist last_tested_at plus any connection error.
Run read-only external SQL against a registered connection. SQL must start with SELECT or WITH, cannot include comments, separators, mutating keywords, or {{project_id}}; each run is stored as external_sql history.
{
"sql_text": "SELECT account_id, plan, mrr FROM accounts ORDER BY mrr DESC",
"limit": 100
}
List white-label BI embed definitions. Responses include resource type, origin allowlist, theme, token prefix, access count, and last access time, but never the full token.
Create an embeddable dashboard, report, saved SQL query, visual query, or metric. The full embed token is returned once; store it securely and use the returned embed_url in an iframe or server-side proxy.
{
"name": "Partner KPI embed",
"resource_type": "visual_query",
"resource_config": {
"dataset": "pageviews",
"dimensions": ["path"],
"metrics": ["count"],
"limit": 25
},
"allowed_origins": ["https://app.example.com"],
"theme": { "brand": "Acme", "primary_color": "#2563eb" },
"expires_at": "2026-12-31T23:59:59Z"
}
Fetch one embed. Use PUT /api/v1/bi/embeds/{id} to update resource settings, origin allowlists, theme, status, or expiration; use DELETE /api/v1/bi/embeds/{id} to revoke it.
Rotate an embed token. The new full token is returned once, and the previous token immediately stops resolving.
Public embed resolver. Pulse verifies the token, expiration, active status, and request origin, increments access counters, and returns the embed definition plus its resource and optional query result.
List row-level permission policies. Active policies are enforced on visual queries and drill-through queries for matching datasets.
Create a row policy using an approved dataset field and operator: eq, neq, in, or not_in.
{
"name": "US and Canada only",
"dataset": "pageviews",
"field": "country",
"operator": "in",
"values": ["US", "CA"],
"is_active": true
}
Update a row policy. Use DELETE /api/v1/bi/row-policies/{id} to remove it.
Run ad hoc read-only SQL. SQL must start with SELECT or WITH, cannot include mutating keywords, and must include {{project_id}} so Pulse can enforce tenant scoping.
{
"sql_text": "SELECT path, COUNT(*) FROM pageviews WHERE project_id = {{project_id}} GROUP BY path ORDER BY 2 DESC",
"limit": 100
}
List saved SQL queries. Use POST /api/v1/bi/sql-queries to save a validated query, and POST /api/v1/bi/sql-queries/{id}/run to execute it.
Run a visual query over approved datasets: pageviews, events, sessions, and daily_stats. Provide dimensions, metrics, date range, and limit.
Return tenant-scoped detail rows behind an aggregate chart. Supports approved datasets and whitelisted filters for pageviews, events, sessions, daily_stats, and csv_uploads; each run is stored as drill_through query history.
{
"dataset": "events",
"filters": {
"event_name": "signup",
"path": ["/pricing", "/signup"]
},
"start_at": "2026-05-01T00:00:00Z",
"end_at": "2026-05-09T23:59:59Z",
"limit": 100
}
List SQL, saved SQL, visual, drill-through, and external SQL executions with status, row count, duration, and error details.
List CSV uploads. Use POST /api/v1/bi/csv-uploads with columns and JSON object rows to store external tabular data.
Page through uploaded CSV rows. Use DELETE /api/v1/bi/csv-uploads/{id} to remove an upload and its rows.
AI Analytics
Requires the ai_queries module. Pulse includes a deterministic query assistant that maps natural-language questions to safe built-in analytics queries, stores query runs, generates heuristic insights, and tracks LLM traces, generations, evals, cost, latency, and token usage.
Ask a natural-language analytics question. Supported intents include overview, top pages, referrers, events, devices, geography, traffic trend, and errors.
{
"question": "What changed in traffic this month?",
"start_at": "2026-05-01T00:00:00Z",
"end_at": "2026-05-09T23:59:59Z",
"limit": 10
}
{
"id": "6e4f28b4-5e1a-4c1d-9df0-6b2e3b2587c1",
"intent": "overview",
"answer": "Pulse saw 12420 pageviews, 4021 visitors, 4580 sessions, and 932 custom events...",
"result": {
"stats": {
"pageviews": 12420,
"visitors": 4021,
"pageview_change_percent": 18.4
}
},
"insights": [
{
"title": "Traffic is concentrated",
"severity": "info",
"metric": "pages"
}
]
}
Generate heuristic insights for a date range, including traffic spikes/drops, elevated bounce rate, and concentrated page traffic. Supports start_at and end_at.
List stored AI query runs. Supports limit and offset.
LLM Traces, Generations, and Evals
Create or update an LLM trace for an agent run, workflow, chat, or generation chain. Use GET /api/v1/ai/llm/traces to list recent traces.
{
"trace_key": "checkout-agent-2026-05-09T12:00:00Z",
"name": "Checkout support agent",
"user_id": "user_123",
"metadata": { "workflow": "checkout_support" },
"status": "started"
}
Fetch one stored LLM trace by id.
Record one LLM generation with provider/model, token usage, latency, cost, prompt/output payloads, status, and metadata. Use GET /api/v1/ai/llm/generations to list recent generations.
{
"trace_key": "checkout-agent-2026-05-09T12:00:00Z",
"provider": "openai",
"model": "gpt-4.1-mini",
"operation": "chat_completion",
"input_tokens": 812,
"output_tokens": 146,
"latency_ms": 1180,
"cost_usd": 0.0042,
"status": "success"
}
Record an eval result for a generation or trace, including evaluator name, metric, score, label, pass/fail, and metadata. Use GET /api/v1/ai/llm/evaluations to list recent evals.
Return LLM generation volume, error count, token usage, average latency, total cost, eval count, and eval pass rate for a date range.
Web Vitals
Requires the webvitals module. Monitor Core Web Vitals performance across your site with percentile breakdowns.
Summary of all Web Vitals with p50, p75, and p99 percentiles.
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/webvitals?start_at=2026-03-01&end_at=2026-03-22"
{
"vitals": {
"LCP": { "p50": 1240, "p75": 2180, "p99": 5420, "rating": "good" },
"FCP": { "p50": 820, "p75": 1450, "p99": 3890, "rating": "good" },
"CLS": { "p50": 0.04, "p75": 0.09, "p99": 0.32, "rating": "good" },
"INP": { "p50": 120, "p75": 198, "p99": 512, "rating": "good" },
"TTFB": { "p50": 280, "p75": 520, "p99": 1890, "rating": "good" }
}
}
Web Vitals broken down by page path.
{
"data": [
{
"path": "/",
"LCP_p75": 1890,
"FCP_p75": 1120,
"CLS_p75": 0.05,
"INP_p75": 145,
"TTFB_p75": 380,
"samples": 1842
},
{
"path": "/dashboard",
"LCP_p75": 2890,
"FCP_p75": 1680,
"CLS_p75": 0.12,
"INP_p75": 234,
"TTFB_p75": 620,
"samples": 567
}
]
}
Daily p75 values for a specific Web Vital metric.
| Parameter | Type | Description |
|---|---|---|
metric | string | Required. One of: LCP, FCP, CLS, INP, TTFB. |
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/webvitals/timeseries?metric=LCP&start_at=2026-03-18&end_at=2026-03-22"
{
"metric": "LCP",
"data": [
{ "date": "2026-03-18", "p75": 2120 },
{ "date": "2026-03-19", "p75": 2045 },
{ "date": "2026-03-20", "p75": 2310 },
{ "date": "2026-03-21", "p75": 1980 },
{ "date": "2026-03-22", "p75": 2180 }
]
}
Error & Log Analytics
Requires the error_tracking and logs modules. Capture JavaScript errors, group them by stable fingerprint, attach releases and environments, register source-map artifacts, and query application logs.
Get grouped error fingerprints ranked by occurrence count. Groups include release, environment, latest path/browser, and whether a matching source-map artifact exists.
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/errors?start_at=2026-03-01&end_at=2026-03-22&limit=5"
{
"data": [
{
"fingerprint": "1d5b154e8fb6d613a52bc2f6e8bf6bc5",
"message": "TypeError: Cannot read properties of null (reading 'id')",
"count": 142,
"affected_visitors": 98,
"release": "2026.05.09",
"environment": "production",
"source_map_configured": true,
"last_seen": "2026-03-22T11:42:00Z",
"first_seen": "2026-03-05T14:23:00Z"
}
]
}
Get individual error instances for a specific error message or fingerprint.
| Parameter | Type | Description |
|---|---|---|
message | string | Error message to look up. |
fingerprint | string | Error fingerprint to look up. Either message or fingerprint is required. |
limit | integer | Number of instances to return. Default: 20. |
{
"data": [
{
"created_at": "2026-03-22T11:42:00Z",
"path": "/dashboard",
"filename": "https://acme.com/assets/app.js",
"lineno": 142,
"colno": 18,
"stack": "TypeError: Cannot read properties of null\n at handleClick (app.js:142:18)",
"browser": "Chrome 122",
"os": "Windows 11",
"release": "2026.05.09",
"matched_source_map": {
"minified_url": "https://acme.com/assets/app.js",
"source_map_url": "s3://artifacts/app.js.map"
}
}
]
}
Daily error count over time.
{
"data": [
{ "date": "2026-03-20", "count": 34 },
{ "date": "2026-03-21", "count": 28 },
{ "date": "2026-03-22", "count": 19 }
]
}
Aggregate error statistics for the period.
{
"total_errors": 342,
"unique_errors": 18,
"affected_visitors": 215,
"releases": [
{ "release": "2026.05.09", "count": 188 }
]
}
List application releases used for release-aware error and log filtering. Supports limit and offset.
Create or update a release record.
{
"version": "2026.05.09",
"environment": "production",
"commit_sha": "9f4c2a1",
"deployed_at": "2026-05-09T18:00:00Z",
"metadata": { "service": "web" }
}
Delete a release record. Source-map records remain available but are detached from the release row.
List source-map artifact metadata. Filter by release_version when needed.
Register a source-map artifact for a minified JavaScript URL and release. Error detail responses surface the matching artifact when the filename and release match.
{
"release_version": "2026.05.09",
"environment": "production",
"minified_url": "https://acme.com/assets/app.js",
"source_map_url": "s3://artifacts/app.js.map",
"artifacts": { "debug_id": "web-20260509" }
}
Delete source-map artifact metadata.
List application logs. Supports start_at, end_at, level, release, environment, search, limit, and offset.
Get log totals grouped by level and release for the requested date range.
Session Replay
Requires the session_replay module. The browser SDK records sampled, privacy-masked interaction events and stores them by session for later playback.
List recorded sessions. Supports start_at, end_at, limit, and offset.
{
"data": [
{
"id": "rec-f4a7c2",
"visitor_id": "v_7fz9k2",
"events_count": 84,
"entry_page": "/pricing",
"duration_ms": 128000,
"is_complete": true
}
]
}
Fetch a recording with its ordered event stream for playback.
Heatmaps
Requires the heatmaps module. Visualize where users click, label selectors as semantic events, evaluate those labels retroactively, and detect rage-click friction from repeated clicks on the same selector.
Get click coordinate data for a specific page.
| Parameter | Type | Description |
|---|---|---|
path | string | Required. Page path to get heatmap data for. |
start_at | string | Period start (ISO 8601). |
end_at | string | Period end (ISO 8601). |
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
"https://pulse.ayushojha.com/api/v1/heatmaps?path=/pricing"
{
"data": [
{ "x": 482, "y": 320, "element_selector": "button.cta-primary", "count": 234 },
{ "x": 720, "y": 580, "element_selector": "a.plan-enterprise", "count": 156 },
{ "x": 240, "y": 580, "element_selector": "a.plan-starter", "count": 98 }
]
}
Pages ranked by total click count.
{
"data": [
{ "path": "/", "total_clicks": 3421 },
{ "path": "/pricing", "total_clicks": 892 },
{ "path": "/docs", "total_clicks": 567 }
]
}
Visual Event Labels
List visual event labels that map a page pattern and element selector to a semantic event name.
Create a visual label for retroactive event definition from historical click data.
{
"name": "Pricing hero CTA",
"event_name": "pricing_hero_cta_click",
"path_pattern": "/pricing*",
"element_selector": "button.cta-primary",
"properties": { "area": "hero" },
"status": "active"
}
Evaluate all active visual labels against historical clicks. Supports start_at, end_at, and limit.
Update a visual label. Use DELETE /api/v1/heatmaps/labels/{id} to remove it.
Evaluate one visual label against historical clicks for a date range.
Detect rage-click clusters from click events. A signal is returned when a visitor clicks the same page and selector at least three times inside a five-second window. Supports optional path, start_at, end_at, and limit.
Feature Flags / Remote Config
Requires the feature_flags module. Create typed feature flags and remote config entries with targeting rules, stable percentage rollouts, optional weighted variants, guardrail metadata, and experiment-backed assignments.
Targeting Rules
Targeting rules use match (all or any) plus conditions against visitor_id, user_id, traits.*, or arbitrary context.* fields. Supported operators are exists, not_exists, eq, neq, contains, starts_with, ends_with, gt, gte, lt, lte, and in.
List feature flags for the project.
Create a feature flag. Use experiment_id to tie evaluation to an existing running experiment assignment.
{
"key": "checkout_redesign",
"name": "Checkout Redesign",
"enabled": true,
"flag_type": "boolean",
"default_value": false,
"rollout_percentage": 25,
"targeting_rules": {
"match": "all",
"conditions": [
{ "field": "traits.plan", "op": "in", "value": ["pro", "business"] },
{ "field": "context.country", "op": "eq", "value": "US" }
]
},
"guardrail_metrics": ["checkout_error_rate", "purchase_conversion"]
}
Fetch one feature flag.
Update a feature flag definition, rollout, targeting rules, experiment binding, or guardrail metadata.
Delete a feature flag and its evaluation history.
Evaluate a flag for a visitor. Evaluation is stable for percentage rollouts and weighted variants, and each evaluation is recorded.
{
"visitor_id": "v_7fz9k2",
"user_id": "user_123",
"traits": { "plan": "pro" },
"context": { "country": "US", "device": "desktop" }
}
{
"key": "checkout_redesign",
"enabled": true,
"matched": true,
"variant": null,
"value": true,
"reason": "match"
}
List recent flag evaluations. Supports limit and offset.
Remote Config
List remote config entries.
Create a remote config value with optional targeting.
{
"key": "checkout_copy",
"value": { "headline": "Finish your secure checkout" },
"targeting_rules": { "match": "all", "conditions": [] },
"is_active": true
}
Fetch one remote config entry.
Update a remote config value, targeting rules, or active state.
Delete a remote config entry.
Evaluate a remote config entry for a visitor and return the value when targeting matches.
A/B Testing
Requires the ab_testing module. Create and manage experiments with multiple variants, assign visitors, and measure results against goals with lift, confidence, p-values, and significant winner detection.
List all experiments.
{
"data": [
{
"id": "exp-a1b2c3d4-5678-9012-efab-cd3456789012",
"name": "CTA Button Color",
"status": "running",
"variants": 3,
"created_at": "2026-03-10T09:00:00Z"
}
]
}
Create a new experiment. Variant weights should sum to 100.
curl -X POST \
-H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
-H "Content-Type: application/json" \
-d '{
"name": "CTA Button Color",
"description": "Test whether blue, green, or orange CTA converts best",
"variants": [
{"name": "control_blue", "weight": 34},
{"name": "variant_green", "weight": 33},
{"name": "variant_orange", "weight": 33}
],
"goal_id": "g9a8b7c6-5432-1fed-cba0-987654321012"
}' \
https://pulse.ayushojha.com/api/v1/experiments
{
"id": "exp-a1b2c3d4-5678-9012-efab-cd3456789012",
"name": "CTA Button Color",
"status": "draft",
"variants": [
{ "name": "control_blue", "weight": 34 },
{ "name": "variant_green", "weight": 33 },
{ "name": "variant_orange", "weight": 33 }
],
"goal_id": "g9a8b7c6-5432-1fed-cba0-987654321012",
"created_at": "2026-03-22T14:30:00Z"
}
Get a specific experiment and its configuration.
Update experiment status. Valid transitions: draft → running → paused → running → completed.
curl -X PUT \
-H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
-H "Content-Type: application/json" \
-d '{"status": "running"}' \
https://pulse.ayushojha.com/api/v1/experiments/exp-a1b2c3d4-5678-9012-efab-cd3456789012/status
Delete an experiment. Only allowed for draft or completed experiments.
Get experiment results with per-variant conversion data, lift versus baseline, p-values, confidence, and significant winner detection. The first configured variant is used as the baseline.
{
"experiment_id": "exp-a1b2c3d4-5678-9012-efab-cd3456789012",
"baseline_variant": "control_blue",
"winner": "variant_green",
"variants": [
{
"name": "control_blue",
"assignments": 1102,
"conversions": 34,
"conversion_rate": 3.09,
"lift_percent": null,
"p_value": null,
"confidence": null,
"significant": false,
"is_baseline": true
},
{
"name": "variant_green",
"assignments": 1067,
"conversions": 41,
"conversion_rate": 3.84,
"lift_percent": 24.3,
"p_value": 0.041,
"confidence": 95.9,
"significant": true,
"is_baseline": false
}
]
}
Assign a visitor to a variant. Uses stable weighted assignment and returns the same variant for repeat calls with the same visitor.
curl -X POST \
-H "X-Pulse-Key: pa_live_8B57VGhehP5C2R8rnP535YYs" \
-H "Content-Type: application/json" \
-d '{ "visitor_id": "v_7fz9k2" }' \
https://pulse.ayushojha.com/api/v1/experiments/exp-a1b2c3d4-5678-9012-efab-cd3456789012/assign
{
"variant": "variant_green"
}
Surveys
Requires the surveys module. Build in-app surveys and adoption guides with customizable triggers, appearance, targeting, and analytics. Collect feedback, NPS, sentiment, tour completion, tooltip engagement, and onboarding outcomes.
List all surveys for the project.
{
"data": [
{
"id": "srv-b2c3d4e5-6789-0abc-def1-234567890abc",
"name": "NPS Survey",
"status": "active",
"responses": 142,
"created_at": "2026-03-01T10:00:00Z"
}
]
}
Create a new survey with questions, trigger configuration, and appearance settings.
curl -X POST \
-H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
-H "Content-Type: application/json" \
-d '{
"name": "NPS Survey",
"questions": [
{
"id": "q1",
"type": "rating",
"text": "How likely are you to recommend us?",
"min": 0,
"max": 10
},
{
"id": "q2",
"type": "text",
"text": "What could we improve?",
"required": false
}
],
"trigger_config": {
"type": "time_on_page",
"delay_seconds": 30,
"pages": ["/dashboard", "/app/*"],
"show_once": true
},
"appearance": {
"position": "bottom-right",
"theme": "dark",
"primary_color": "#6366f1"
},
"response_limit": 500
}' \
https://pulse.ayushojha.com/api/v1/surveys
Get a specific survey with its full configuration.
Update a survey’s configuration. Only allowed for draft or paused surveys.
Delete a survey and all its responses. Returns 204.
Update survey status. Valid values: draft, active, paused, archived.
curl -X PUT \
-H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
-H "Content-Type: application/json" \
-d '{"status": "active"}' \
https://pulse.ayushojha.com/api/v1/surveys/srv-b2c3d4e5-6789-0abc-def1-234567890abc/status
Get individual responses for a survey.
{
"data": [
{
"id": "resp-1234",
"answers": [
{ "question_id": "q1", "value": 9 },
{ "question_id": "q2", "value": "Love the dashboard!" }
],
"completed": true,
"path": "/dashboard",
"submitted_at": "2026-03-22T14:12:00Z"
}
],
"total": 142
}
Aggregated response statistics.
{
"survey_id": "srv-b2c3d4e5-6789-0abc-def1-234567890abc",
"total_responses": 142,
"completed_responses": 128,
"completion_rate": 90.1,
"questions": [
{
"id": "q1",
"text": "How likely are you to recommend us?",
"avg_value": 8.3,
"distribution": { "0-6": 12, "7-8": 38, "9-10": 92 }
}
]
}
Calculate NPS from completed responses. Optionally pass question_id; otherwise Pulse uses the first numeric answer in the 0-10 range.
Run deterministic sentiment scoring over text answers. Optionally pass question_id to target a specific open-text question.
Get all active surveys for the frontend. Used by the tracking script to display surveys to visitors. Requires an ingest-scoped key.
curl -H "X-Pulse-Key: pa_live_8B57VGhehP5C2R8rnP535YYs" \
"https://pulse.ayushojha.com/api/v1/surveys/active"
{
"data": [
{
"id": "srv-b2c3d4e5-6789-0abc-def1-234567890abc",
"name": "NPS Survey",
"questions": [ /* ... */ ],
"trigger_config": { /* ... */ },
"appearance": { /* ... */ }
}
]
}
Guides, Tooltips, and Tours
List in-app guides, onboarding flows, product tours, tooltips, announcements, and checklists.
Create a guide with ordered steps, targeting rules, visual appearance, and priority.
{
"name": "New dashboard tour",
"guide_type": "tour",
"steps": [
{ "id": "welcome", "title": "Welcome", "body": "Start here." },
{ "id": "filters", "selector": "[data-tour='filters']", "body": "Filter your analysis." }
],
"targeting": { "paths": ["/dashboard"], "segments": ["new_users"] },
"appearance": { "theme": "dark", "position": "bottom-right" },
"priority": 10
}
Return active guides ordered by priority. Frontend renderers can apply the returned targeting and appearance metadata.
Fetch one guide. Use PUT /api/v1/guides/{id} to update it or DELETE /api/v1/guides/{id} to remove it.
Set guide status to draft, active, paused, or archived.
Record guide events such as shown, started, step_viewed, completed, dismissed, and converted. Use GET /api/v1/guides/{id}/events for visitor event history.
Return shown, started, completed, dismissed, converted, completion-rate, and dismissal-rate metrics.
CSV Exports
Requires the exports module. Download analytics data as CSV files for use in spreadsheets or data pipelines.
Export data as a CSV file. Returns a file download with Content-Disposition header.
| Parameter | Type | Description |
|---|---|---|
type | string (path) | Required. One of: stats, pages, referrers, events, devices, geo, campaigns. |
start_at | string | Period start (ISO 8601). |
end_at | string | Period end (ISO 8601). |
curl -H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
-o pages_export.csv \
"https://pulse.ayushojha.com/api/v1/exports/pages?start_at=2026-03-01&end_at=2026-03-22"
Content-Type: text/csv
Content-Disposition: attachment; filename="pages_2026-03-01_2026-03-22.csv"
path,views,unique_views,avg_duration
/,4821,2190,45.2
/pricing,2314,1820,92.7
/docs/getting-started,1892,1456,214.3
/blog/analytics-guide,1203,987,312.1
/signup,891,834,67.8
Integrations
Requires the integrations module. The integrations catalog lists available and planned source, destination, SDK, framework, BI, and marketing integrations with capabilities and setup metadata.
List integrations. Supports category, capability, and status filters.
Fetch one integration by key, including its capabilities and setup metadata.
Sources
Requires the sources module. Sources register server-side or external systems that send JSON events into Pulse through source-specific tokens. Accepted source events are audited and routed to matching destinations.
List event sources for the project. Responses include the source token prefix but never the full token.
Create an event source. The full source token is returned once in the creation response.
{
"name": "Stripe",
"source_type": "stripe.webhook",
"description": "Billing and subscription webhooks",
"schema": { "required": ["id", "type"] },
"config": { "environment": "production" },
"is_active": true
}
Fetch one source. Use PUT /api/v1/sources/{id} to update metadata or active status, or DELETE /api/v1/sources/{id} to remove it.
List recent source ingestion attempts with payload, sanitized headers, event type, destination delivery count, and received timestamp. Supports limit and offset.
Public source ingestion endpoint. Authenticate with X-Pulse-Source-Token or Authorization: Bearer .... Pulse derives the event type from event_type, type, event, or name, then routes the normalized event to destinations.
curl -X POST "https://pulse.ayushojha.com/api/source/7c2f0f06-9df7-48f0-a91c-4db0e0574cc3/collect" \
-H "Content-Type: application/json" \
-H "X-Pulse-Source-Token: psrc_..." \
-d '{"event_type":"checkout.session.completed","customer_id":"cus_123","amount":4900}'
Destinations
Requires the destinations module. Destinations route collected events to external systems through a reliable outbox with retries, dead-letter status, signed webhook delivery, and health reporting.
List event destinations for the project.
Create a webhook destination. Leave event_types empty to receive every collected event type. Use transform to shape the payload stored in the delivery outbox for this destination.
{
"name": "Warehouse ingest",
"destination_type": "webhook",
"endpoint_url": "https://warehouse.example.com/pulse/events",
"secret": "whsec_...",
"headers": { "X-Team": "growth" },
"event_types": ["pageview", "event", "identify"],
"transform": {
"include": ["event_type", "payload.customer_id", "payload.amount"],
"rename": { "payload.customer_id": "customer.id" },
"drop_fields": ["payload.card_token"],
"static_fields": { "source": "pulse" },
"wrap": "data"
},
"is_active": true
}
| Transform key | Description |
|---|---|
include / include_fields | Whitelist dot-path fields from the original payload. |
exclude / drop_fields | Remove dot-path fields from the destination payload. |
rename / rename_fields | Move fields from old dot paths to new dot paths. |
set / static_fields | Add static values at dot-path keys. |
wrap / wrap_key | Wrap the transformed payload under one top-level key. |
Fetch one destination. Use PUT /api/v1/destinations/{id} to update it, or DELETE /api/v1/destinations/{id} to remove it.
List outbox deliveries. Supports status, limit, and offset. Status values are pending, retry, delivered, and dead_letter.
Move a failed or dead-letter delivery back to the pending queue.
Return per-destination delivery counts, failure timestamps, and health status.
Governance
Requires the governance module. Governance lets teams define tracking plans, approve event schemas, validate required properties and types at ingest time, maintain a data dictionary, and monitor instrumentation health.
Tracking Plans
A project can have active tracking plans in observe mode, which records violations without blocking ingestion, or reject mode, which rejects invalid custom events after logging the validation issue.
List tracking plans for the project.
Create a tracking plan. enforcement_mode must be observe or reject.
{
"name": "Production Tracking Plan",
"description": "Approved production web events",
"enforcement_mode": "observe",
"is_active": true
}
Fetch one tracking plan.
Update a tracking plan’s name, description, enforcement mode, or active state.
Delete a tracking plan and its plan-scoped schemas.
Event Schemas
Event schemas define the approved event catalog. property_schema is a JSON object where each key is a property path and each value is either a type string or an object with type, required, and optional descriptive metadata. Supported types are string, number, integer, boolean, object, array, timestamp, and any.
List event schemas. Optionally filter with tracking_plan_id.
Create an event schema. Status values are draft, approved, and deprecated.
{
"tracking_plan_id": "b8f7de26-79b7-4d59-9cd0-7d1a2fe034a2",
"event_name": "purchase",
"description": "Completed checkout event",
"status": "approved",
"required_properties": ["amount", "currency"],
"property_schema": {
"amount": "number",
"currency": { "type": "string", "required": true },
"metadata.coupon": "string"
}
}
Fetch one event schema.
Update an event schema definition.
Move an event schema through the approval workflow by setting draft, approved, or deprecated.
Delete an event schema.
Data Dictionary
List data dictionary entries. Optionally filter by entry_type: event, property, metric, or dimension.
Create a data dictionary entry.
{
"entry_type": "property",
"name": "purchase.amount",
"data_type": "number",
"description": "Checkout total before tax",
"owner": "growth",
"is_pii": false
}
Update a data dictionary entry.
Delete a data dictionary entry.
Quality Monitoring
List ingestion quality violations. Supports event_name, violation_type, limit, and offset.
Summarize instrumentation health for the last 24 hours, including event coverage and violation counts.
{
"status": "warning",
"observed_events_24h": 14,
"covered_events_24h": 12,
"coverage_ratio": 0.86,
"violations_24h": 7,
"top_violations": [
{ "event_name": "purchase", "violation_type": "missing_required_property", "count": 3 }
]
}
Privacy / Audit
Admin-scoped endpoints for runtime privacy settings, DSAR export/delete workflows, and audit trail review. Ingestion can anonymize IP addresses before GeoIP lookup, strip city/region precision, respect DNT and Sec-GPC, filter bots, and require explicit consent modes.
Return project privacy controls. Defaults enable IP anonymization, DNT/Sec-GPC handling, and bot filtering.
Update privacy controls. Supported fields are anonymize_ip, respect_dnt, bot_filtering, consent_required, allowed_consent_modes, and blocked_user_agents.
{
"anonymize_ip": true,
"respect_dnt": true,
"bot_filtering": true,
"consent_required": true,
"allowed_consent_modes": ["analytics", "measurement"],
"blocked_user_agents": ["synthetic-monitor"]
}
Export identity, sessions, pageviews, events, surveys, experiments, replay recordings, and telemetry for one visitor.
Delete stored visitor data across analytics tables and write an audit log entry.
List project audit logs. Supports limit and offset.
Email Reports
Requires the email_reports module. Configure scheduled daily, weekly, or monthly digests. Delivery is handled by posting a normalized email payload to EMAIL_REPORT_WEBHOOK_URL.
List report configurations and whether delivery is configured.
Create a scheduled report.
{
"name": "Weekly Growth",
"recipients": ["team@example.com"],
"schedule": "weekly",
"modules": ["core", "goals"],
"is_active": true
}
Update report recipients, schedule, modules, or active state.
Send a test report immediately through the configured delivery webhook.
Delete a report configuration. Returns 204.
Alerts
Requires the alerts module. Set up threshold-based alert rules that notify webhook channels when metrics cross specified boundaries.
List all alert rules for the project.
{
"data": [
{
"id": "alt-c3d4e5f6-7890-1234-abcd-ef0123456789",
"name": "Traffic Spike Alert",
"project_id": "a7b8c9d0-1234-5678-9abc-def012345678",
"module": "traffic",
"metric": "visitors",
"operator": "gt",
"threshold": 500,
"window_minutes": 60,
"cooldown_minutes": 360,
"notify_channels": [
{"type": "webhook", "url": "https://hooks.example.com/pulse"}
],
"is_active": true,
"last_triggered_at": "2026-03-20T14:30:00Z"
}
]
}
Create a new alert rule.
| Field | Type | Description |
|---|---|---|
name | string | Human-readable name for the alert. |
module | string | Label for the area being monitored (e.g., traffic, error_tracking). |
metric | string | Supported values: pageviews, visitors, bounce_rate, error_count, avg_duration. |
operator | string | Comparison: gt, lt, gte, lte, eq. |
threshold | number | Value to compare against. |
window_minutes | integer | Rolling window size in minutes. |
cooldown_minutes | integer | Minimum time between repeated alerts. |
notify_channels | array | Webhook targets. Each item supports type: "webhook", url, and optional secret for HMAC signatures. |
curl -X POST \
-H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
-H "Content-Type: application/json" \
-d '{
"name": "Error Spike Alert",
"module": "error_tracking",
"metric": "error_count",
"operator": "gt",
"threshold": 50,
"window_minutes": 15,
"cooldown_minutes": 60,
"notify_channels": [
{"type": "webhook", "url": "https://hooks.slack.com/services/T00/B00/xxx", "secret": "optional-signing-secret"}
]
}' \
https://pulse.ayushojha.com/api/v1/alerts
alert_triggered JSON payload to each webhook channel. If secret is set, the request includes an X-Pulse-Signature HMAC-SHA256 signature over the raw JSON body.{
"event": "alert_triggered",
"project_id": "a7b8c9d0-1234-5678-9abc-def012345678",
"triggered_at": "2026-05-09T18:22:14Z",
"metric_value": 73,
"alert": {
"id": "alt-c3d4e5f6-7890-1234-abcd-ef0123456789",
"name": "Error Spike Alert",
"module": "error_tracking",
"metric": "error_count",
"operator": "gt",
"threshold": 50,
"window_minutes": 15,
"cooldown_minutes": 60
}
}
Update an alert rule’s configuration.
Delete an alert rule. Returns 204.
Enable or disable an alert rule without deleting it.
curl -X POST \
-H "X-Pulse-Key: pa_live_wYxrlD97_Oy1UpLAyi_TwPTG" \
https://pulse.ayushojha.com/api/v1/alerts/alt-c3d4e5f6-7890-1234-abcd-ef0123456789/toggle
{
"id": "alt-c3d4e5f6-7890-1234-abcd-ef0123456789",
"name": "Error Spike Alert",
"module": "error_tracking",
"metric": "error_count",
"is_active": false,
"updated_at": "2026-05-09T18:23:01Z"
}
Admin API
Administrative endpoints for managing projects and API keys. All admin endpoints require the admin bearer token.
Authorization: Bearer <PULSE_ADMIN_TOKEN>. Do not expose the admin token in frontend code.Register a new project.
curl -X POST \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"name": "My SaaS App",
"domain": "app.example.com"
}' \
https://pulse.ayushojha.com/api/admin/projects
{
"id": "a7b8c9d0-1234-5678-9abc-def012345678",
"name": "My SaaS App",
"domain": "app.example.com",
"created_at": "2026-03-22T16:00:00Z"
}
List all registered projects.
{
"data": [
{
"id": "a7b8c9d0-1234-5678-9abc-def012345678",
"name": "My SaaS App",
"domain": "app.example.com",
"created_at": "2026-03-22T16:00:00Z"
}
]
}
Get details for a specific project.
Create an API key for a project.
curl -X POST \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"name": "Production Ingest",
"scopes": ["ingest"],
"expires_at": "2027-01-01T00:00:00Z",
"allowed_modules": null
}' \
https://pulse.ayushojha.com/api/admin/projects/a7b8c9d0-1234-5678-9abc-def012345678/keys
{
"id": "key-f1e2d3c4-b5a6-9870-fedc-ba0987654321",
"key": "pa_live_xK9mP2vQr7nL4wJ8bY6tZ3sA",
"name": "Production Ingest",
"scopes": ["ingest"],
"allowed_modules": null,
"expires_at": "2027-01-01T00:00:00Z",
"created_at": "2026-03-22T16:05:00Z"
}
key value is only returned once at creation time. Store it securely — it cannot be retrieved later.List all API keys for a project. Key values are masked.
{
"data": [
{
"id": "key-f1e2d3c4-b5a6-9870-fedc-ba0987654321",
"name": "Production Ingest",
"key_prefix": "pa_live_xK9m...",
"scopes": ["ingest"],
"allowed_modules": null,
"expires_at": "2027-01-01T00:00:00Z",
"created_at": "2026-03-22T16:05:00Z",
"last_used_at": "2026-03-22T16:42:00Z"
}
]
}
Revoke an API key. The key immediately stops working. Returns 204.
Webhooks
Configure webhook integrations to receive real-time notifications when specific events occur in your analytics data.
Create a new webhook subscription.
| Field | Type | Description |
|---|---|---|
url | string | Required. HTTPS endpoint to receive webhook payloads. |
events | array | Required. Event types to subscribe to. |
secret | string | Shared secret for HMAC-SHA256 signature verification. |
Supported event types:
| Event | Description |
|---|---|
traffic_spike | Triggered when active visitors exceed 2x the rolling average. |
zero_traffic | Triggered when no pageviews are recorded for 30+ minutes. |
daily_summary | Sent daily at midnight UTC with the day’s aggregate stats. |
curl -X POST \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"url": "https://hooks.slack.com/services/T00/B00/xxxxx",
"events": ["traffic_spike", "zero_traffic"],
"secret": "whsec_my_signing_secret_2026"
}' \
https://pulse.ayushojha.com/api/admin/projects/a7b8c9d0-1234-5678-9abc-def012345678/webhooks
{
"id": "wh-d4e5f6a7-8901-2345-bcde-f01234567890",
"url": "https://hooks.slack.com/services/T00/B00/xxxxx",
"events": ["traffic_spike", "zero_traffic"],
"created_at": "2026-03-22T16:30:00Z"
}
List all webhooks for a project.
Update a webhook’s URL, events, or secret.
curl -X PUT \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"events": ["traffic_spike", "zero_traffic", "daily_summary"]
}' \
https://pulse.ayushojha.com/api/admin/projects/a7b8c9d0-1234-5678-9abc-def012345678/webhooks/wh-d4e5f6a7-8901-2345-bcde-f01234567890
Remove a webhook subscription. Returns 204.
Fire a test payload to the webhook URL to verify connectivity.
curl -X POST \
-H "Authorization: Bearer <ADMIN_TOKEN>" \
https://pulse.ayushojha.com/api/admin/projects/a7b8c9d0-1234-5678-9abc-def012345678/webhooks/wh-d4e5f6a7-8901-2345-bcde-f01234567890/test
{
"success": true,
"status_code": 200,
"response_time_ms": 142
}
Webhook Payload Format
All webhook payloads follow the same envelope structure:
{
"event": "traffic_spike",
"project_id": "a7b8c9d0-1234-5678-9abc-def012345678",
"timestamp": "2026-03-22T14:30:00Z",
"data": {
"active_visitors": 187,
"rolling_avg": 45,
"spike_multiplier": 4.16
}
}
X-Pulse-Signature header. Verify it by computing HMAC-SHA256(secret, raw_body) and comparing.Rate Limiting
Pulse enforces rate limits per project to ensure fair usage and system stability.
| Scope | Limit | Window |
|---|---|---|
| Ingest endpoints | 100 requests/second | Per project |
| Query endpoints | 100 requests/second | Per project |
| Admin endpoints | 20 requests/second | Per admin token |
When you exceed the rate limit, the API returns a 429 Too Many Requests response with a Retry-After header indicating how many seconds to wait.
HTTP/1.1 429 Too Many Requests
Retry-After: 1
Content-Type: application/json
{
"error": "Rate limit exceeded. Retry after 1 second."
}
Error Codes
All API errors follow a consistent JSON format. The HTTP status code indicates the error category.
{
"error": "Human-readable error message describing what went wrong."
}
Status Codes
| Code | Meaning | Common Causes |
|---|---|---|
200 |
OK | Request succeeded. Response body contains the requested data. |
201 |
Created | Resource created successfully (projects, keys, funnels, etc.). |
204 |
No Content | Delete operations completed successfully. No response body. |
400 |
Bad Request | Invalid JSON, missing required fields, invalid parameter values. |
401 |
Unauthorized | Missing or invalid API key / admin token. |
403 |
Forbidden | API key lacks the required scope, or the target module is disabled. |
404 |
Not Found | The requested resource (project, funnel, goal, etc.) does not exist. |
429 |
Too Many Requests | Rate limit exceeded. Check the Retry-After header. |
500 |
Internal Server Error | Unexpected server error. Contact support if it persists. |
Common Error Examples
Missing API Key
{
"error": "Missing API key. Provide it via X-Pulse-Key header or ?key= query parameter."
}
Invalid API Key
{
"error": "Invalid API key."
}
Insufficient Scope
{
"error": "API key does not have the required 'query' scope for this endpoint."
}
Module Disabled
{
"error": "Module 'funnels' is not enabled for this project."
}
Invalid Request Body
{
"error": "Invalid request body: missing required field 'name'."
}
Resource Not Found
{
"error": "Funnel 'f1a2b3c4-5678-9abc-def0-1234567890ab' not found."
}