PostHog endpoints give you something most analytics setups can’t: a direct line from your raw event data to any dashboard — no middleware, no BI tool license, no stale exports. Most analytics dashboards are built on pre-aggregated data, bolt-on tools, and CSVs that are already outdated by the time anyone opens them.
PostHog endpoints change that by letting you query your event data directly, serve it through a personal API key, and build dashboards that reflect what’s actually happening — so you can make faster decisions without waiting on a data engineer.
Oh, and as of March 2026 — PostHog endpoints are completely free. Pricing is coming, but right now you can build all of this at no cost.
I’m JJ Reynolds, founder of VisionLabs. We’re a product and web analytics agency. We’ve built dashboards like this for real clients, and this tutorial walks through exactly how we do it
What are PostHog Endpoints and how do they work?
PostHog endpoints are a newer feature (currently in beta as of March 2026) that let you expose HogQL queries as HTTP endpoints. Think of it as turning a SQL query into a mini API.
HogQL is PostHog’s SQL dialect — documented in full in the PostHog HogQL reference. It queries your event data directly, so you can join page views, lead events, session counts, feature flag usage, and traffic sources — all in one query, from one source.
The output is a JSON response you can plug into any frontend you’re already using.
So you can skip the “export data → paste into Sheets → rebuild every Monday” loop.
When should you use PostHog Endpoints for a custom dashboard
This approach works best for teams who already have:
- A clean event structure. Consistent naming, reliable tracking, no duplicate events firing.
- CDP understanding. You know how PostHog ingests and routes data. (If not, read the PostHog as a CDP guide first.)
- Product data feeding the platform. Feature flags, lead events, conversion signals — not just page views.
If your event tracking is messy, fix that before building a dashboard on top of it. A custom dashboard on bad data is just bad data with better formatting.
Why should you plan your data structure before touching PostHog?
Before touching PostHog, open a Google Sheet. Map out the exact columns your dashboard needs.
For the web analytics dashboard I built using PostHog endpoints, those columns were:
- Date
- Users
- Sessions
- Page views
- Lead events (form fills, demo requests, etc.)
- Traffic source
- Landing page
- Feature flag usage
- Total events
This planning step takes 15 minutes. Skipping it costs you hours of query rewrites. Know what questions you’re trying to answer — what I call the “buy questions” — before you write a single line of SQL.
Step 2: Enable PostHog Endpoints
In PostHog, navigate to:
All Apps → Enable Beta/Alpha → Tools → Endpoints
If you don’t see it, make sure beta features are toggled on in your workspace settings. This feature is still rolling out — but as of March 2026, that’s where it lives.
How do you write your first HogQL query for PostHog endpoints?
Click New Endpoint and open the SQL editor.
PostHog includes an AI query builder (HogQL AI). Honestly? In my experience it has not worked more times than it has. It understands your event schema in theory and can draft a query in seconds — but don’t treat what it spits out as production-ready. Use it to generate the skeleton, then expect to rewrite most of it.
A few things to know about the generated query:
- The WHERE clause will default to a short date range. Remove it temporarily to validate your query returns data at all.
- Column names from HogQL don’t always match PostHog’s UI labels. When something returns null, check the actual property name in your event inspector.
- HogQL AI is good at starting queries. It’s bad at optimization. Don’t expect it to write production-ready SQL on the first pass.
A basic query for a web analytics PostHog endpoint looks like this:
SELECT
toDate(timestamp) AS date,
uniq(distinct_id) AS users,
uniq(session_id) AS sessions,
countIf(event = '$pageview') AS page_views,
countIf(event = 'lead_submitted') AS lead_events,
properties.$referring_domain AS source,
properties.$current_url AS landing_page,
count() AS total_events
FROM events
WHERE toDate(timestamp) BETWEEN {start_date} AND {end_date}
GROUP BY date, source, landing_page
ORDER BY date DESC
The {start_date} and {end_date} are SQL variables. You’ll set those up in the next step.
Step 4: Add SQL Variables for Date Filtering
Dynamic date ranges are what make a dashboard useful vs. a static report.
In the PostHog endpoints editor, click Manage SQL Variables and add:
start_date— type: Dateend_date— type: Date
Once added, PostHog expects those variables when you call the endpoint. During testing, populate them with explicit date strings (e.g., 2026-01-01 and 2026-03-31) to confirm the query returns the right rows.
Common error at this stage: the variable exists but the WHERE clause uses it incorrectly. If you’re getting a parse error, wrap date fields in toDate() to normalize the format.
WHERE toDate(timestamp) BETWEEN toDate({start_date}) AND toDate({end_date})
That one-line fix resolves most date-related query failures.
Step 5: Save and Call the Endpoint
Once the query runs cleanly, save the endpoint. PostHog generates a URL you can call with a personal API key via a standard GET request.
The call looks like:
GET https://app.posthog.com/api/projects/{project_id}/query/endpoints/{endpoint_id}?start_date=2026-01-01&end_date=2026-03-31
Authorization: Bearer <your_personal_api_key>
Test it in Postman or your browser dev tools before wiring it into a dashboard. Confirm the JSON structure matches what your frontend expects.
Cache age setting: PostHog caches endpoint results. For dashboards that don’t need real-time data, set cache age to 1 hour or more. It speeds up load times significantly.
How do materialized views make PostHog endpoint queries faster?
Here’s where most tutorials stop. Don’t.
If your PostHog endpoint queries the raw events table on every load, it will get slow — fast. Especially once your event volume climbs past a few million rows.
The fix: materialized views.
A materialized view is a pre-computed table PostHog stores and reuses. Instead of re-scanning every event on each API call, the query reads from a cached result. Faster for your dashboard. Cheaper on compute. PostHog runs on ClickHouse, which handles this kind of pre-aggregation natively — that’s why the speed gains are significant, not marginal.
How do you create a materialized view in PostHog?
- Go to the SQL Editor (not the Endpoints editor).
- Write your aggregation query — same logic as your endpoint query, but without date variables. Materialized views can’t use variables.
- Save it as a materialized view and set the sync frequency:
- Daily — good for most web analytics dashboards
- Hourly — use when fresher data matters
- Every 5 minutes — for near-real-time product monitoring
The query for your materialized view is the same logic as your PostHog endpoint, just without the {start_date} / {end_date} placeholders:
SELECT
toDate(timestamp) AS date,
uniq(distinct_id) AS users,
uniq(session_id) AS sessions,
countIf(event = '$pageview') AS page_views,
countIf(event = 'lead_submitted') AS lead_events,
properties.$referring_domain AS source,
properties.$current_url AS landing_page,
count() AS total_events
FROM events
GROUP BY date, source, landing_page
ORDER BY date DESC
PostHog runs this on the schedule you set and stores the output.
Step 7: Swap Your Endpoint to Query the Materialized View
Go back to your PostHog endpoint. Update the FROM clause:
SELECT *
FROM your_materialized_view_name
WHERE toDate(date) BETWEEN toDate({start_date}) AND toDate({end_date})
Now the endpoint reads pre-aggregated rows instead of scanning raw events. Dashboard load time drops. Query cost drops. The date variables still work because the filter runs against the materialized view’s date column, not raw event timestamps.
This is the setup behind the demo dashboard I showed in the video — date selector, metric toggle, source filter, page views, lead events, all pulling from a single materialized view through one PostHog endpoint.
What does a complete PostHog endpoint query structure look like?
The actual materialized view backing that demo dashboard captures:
| Column | What It Measures |
|---|---|
date | Day of activity |
users | Unique visitors (by distinct_id) |
sessions | Unique sessions |
page_views | Total $pageview events |
lead_events | Conversion events (form fills, demo requests) |
source | Referring domain / UTM source |
landing_page | First URL in session |
feature_flag_use | Whether a flag was active for the user |
total_events | All events for context |
One materialized view. One PostHog endpoint. Everything your web analytics dashboard needs.
How does PostHog Endpoints connect to the rest of your PostHog stack?
PostHog endpoints don’t exist in isolation. They’re most powerful when the rest of your PostHog setup is solid.
- Funnel analysis: If your endpoint tracks lead events, you can cross-reference those users in PostHog’s funnel builder to see drop-off points between traffic source and conversion.
- Cohort segmentation: Endpoint data can complement cohort and group analysis — for example, segmenting dashboard metrics by high-intent user cohorts.
- Session recordings: When your dashboard flags an anomaly in lead events, session recordings let you dig into the actual user behavior behind the number.
- Alerts: Pair your endpoint data with PostHog Alerts so you’re notified when key metrics drop below a threshold — no manual dashboard checks required.
- Workflows: PostHog Workflows let you automate actions based on the same event data your endpoints surface.
For a full grounding in PostHog’s capabilities, the PostHog Complete Course 2026 covers all of this in sequence.
What are the most common PostHog endpoint mistakes?
Skipping the materialized view. Querying raw events at dashboard load is fine for testing. It’s not fine for production. Build the materialized view before you put a dashboard in front of anyone.
Trusting HogQL AI too much. The AI drafts SQL fast. In my experience it has not worked more times than it has — it doesn’t know your event schema perfectly, doesn’t optimize joins, and won’t catch edge cases. Review every query it generates before you ship anything.
Inconsistent event naming. If lead_submitted fires as Lead Submitted in some sessions and lead_submitted in others, your countIf query will undercount. Audit your event names before you build.
Missing toDate() wrappers. PostHog stores timestamps as DateTime. When you filter by date in a PostHog endpoint, wrap both sides of the comparison in toDate(). Without it, date filtering behaves inconsistently across time zones.
Who should use PostHog endpoints for custom dashboards?
Best for: Product-led growth teams, SaaS companies, and marketing teams who want a single, customizable analytics view without paying for a separate BI tool.
Stack: PostHog (product + web analytics) + any frontend that can call a REST API.
Not the right fit if: Your event tracking is inconsistent, you don’t have a defined set of KPIs, or you’re looking for a plug-and-play dashboard with no SQL involved. In that case, PostHog’s built-in dashboards are the faster starting point.
Want help with your PostHog setup?
If you want the dashboard — not the tutorial — VisionLabs builds and implements PostHog analytics setups for teams who need it done right the first time.
We’ve done this across dozens of client stacks. We know where the edge cases live, which query patterns break at scale, and how to connect PostHog endpoint data to the metrics that actually drive decisions.
Book a scoping call at visionlabs.com/posthog — we’ll audit your current setup and map out exactly what it takes to get a dashboard like this live.