creating-an-endpoint
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCreating an endpoint
创建端点
This skill walks through creating a new endpoint with the right configuration. Endpoints expose
saved HogQL or insight queries as callable HTTP routes — the configuration choices made at
creation time determine cost, latency, and how callers integrate.
The materialisation deep-dive lives at . Pull it in when the
materialisation decision is non-obvious.
references/materializing.md本指南将逐步介绍如何创建配置正确的新端点。端点可将已保存的HogQL或洞察查询暴露为可调用的HTTP路由——创建时做出的配置选择将决定成本、延迟以及调用方的集成方式。
关于物化的深入说明请查看。当物化决策不明确时,可参考该文档。
references/materializing.mdWhen to use this skill
何时使用本指南
- "Create an endpoint for [query]"
- "Expose this insight as an API"
- "Help me turn this HogQL into a callable endpoint"
- A new caller (mobile app, customer-facing dashboard, downstream pipeline) needs PostHog data and the user is choosing how to deliver it
- "为[查询]创建一个端点"
- "将此洞察暴露为API"
- "帮我将这个HogQL转换为可调用的端点"
- 新的调用方(移动应用、面向客户的仪表板、下游管道)需要PostHog数据,且用户正在选择数据交付方式
Decisions to make in order
需依次做出的决策
1. Should this even be an endpoint?
1. 是否真的需要创建端点?
Endpoints are right when:
- An external system (someone else's code) needs to call PostHog for data
- The query is stable — not exploratory analysis
- The shape is reusable — same query with different parameters
Endpoints are wrong when:
- An internal PostHog dashboard or insight needs the data — use the insight directly; an endpoint only adds an external API surface you don't need internally
- One-off, exploratory analysis — use the tool (or the SQL editor) directly
execute-sql
Heavy aggregation is not a reason to avoid an endpoint. Endpoints are themselves saved
queries, and a heavy, frequently-called aggregation is often the best case for an endpoint with
materialisation turned on.
If the user is unsure, ask what's calling the endpoint and what shape they expect.
适合创建端点的场景:
- 外部系统(第三方代码)需要调用PostHog获取数据
- 查询是稳定的——不是探索性分析
- 数据格式具有可复用性——相同查询可传入不同参数
不适合创建端点的场景:
- PostHog内部仪表板或洞察需要数据——直接使用洞察即可;创建端点只会增加不必要的外部API接口
- 一次性探索性分析——直接使用工具(或SQL编辑器)
execute-sql
大量聚合操作不是避免创建端点的理由。端点本身就是已保存的查询,对于频繁调用的复杂聚合操作,启用物化的端点往往是最佳选择。
若用户不确定,可询问调用端点的系统是什么,以及期望的数据格式。
2. Pick a name
2. 选择名称
Names are URL-safe (letters, numbers, hyphens, underscores), start with a letter, max 128 chars,
must be unique within the project. Lean toward:
- Descriptive over generic — over
weekly_active_users_by_orgmetrics - Snake_case — matches how the name appears in code paths and URLs
- No version in the name — versions are managed by the endpoint itself
- No "endpoint" in the name — redundant
The name appears in the URL: . It's not
trivially renameable later (callers depend on the path) — get it right at creation.
/api/projects/{team_id}/endpoints/{name}/run名称需符合URL安全规范(字母、数字、连字符、下划线),以字母开头,最长128字符,且在项目内必须唯一。建议遵循以下原则:
- 描述性优先于通用性——使用而非
weekly_active_users_by_orgmetrics - 采用蛇形命名法(Snake_case)——与代码路径和URL中的名称格式一致
- 名称中不包含版本号——版本由端点自身管理
- 名称中不包含"endpoint"——属于冗余信息
名称会出现在URL中:。后续修改名称并非易事(调用方依赖该路径)——因此创建时务必确定合适的名称。
/api/projects/{team_id}/endpoints/{name}/run3. Pick the query kind
3. 选择查询类型
Two options exist:
- HogQL () — raw SQL written by the user. Variables defined via
HogQLQuerysyntax, matched on{variables.x}. Recommended for new endpoints when the caller cares about the exact column shape of the response.code_name - Insight — wraps an existing insight definition. Best supported for ,
TrendsQuery, andLifecycleQuery: these can be materialised, and the breakdown can act as a variable (Trends and Retention only; Lifecycle has no breakdown). Other insight kinds such asRetentionQuerycan run inline but cannot be materialised and don't expose breakdown variables — rewrite those as HogQL if you need either.FunnelsQuery
HogQL is the more flexible choice. Pick insight only when the user is genuinely re-publishing an
existing insight (see "Creating from an existing insight" below) rather than building a new query.
有两种选项:
- HogQL()——用户编写的原始SQL。通过
HogQLQuery语法定义变量,匹配{variables.x}。当调用方关心响应的精确列格式时,建议为新端点选择此类型。code_name - 洞察——封装现有洞察定义。对、
TrendsQuery和LifecycleQuery支持最佳:这些查询可被物化,且细分维度可作为变量(仅适用于Trends和Retention;Lifecycle无细分维度)。其他洞察类型如RetentionQuery可直接运行,但无法被物化且不暴露细分维度变量——若需要物化或变量功能,需将其重写为HogQL。FunnelsQuery
HogQL是更灵活的选择。仅当用户确实需要重新发布现有洞察时(见下文“从现有洞察创建”),才选择洞察类型,而非构建新查询。
4. Decide which inputs become variables
4. 确定哪些输入作为变量
Anything that should change per-caller goes in variables; the rest is hard-coded in the query.
For HogQL endpoints, variables are declared in the query payload with , ,
and . Each execution call passes .
code_nametypedefault{ "variables": { "<code_name>": value } }Common patterns:
- Time windows: ,
date_from, or a singledate_tointegerlookback_days - Identity filters: ,
user_id,account_idteam_id - Pagination control beyond /
limit(these are first-class on the run endpoint already)offset
For insight endpoints, the breakdown property acts as the variable (Trends and Retention
only — Lifecycle has no breakdown). Pass the breakdown property name as the key. /
are accepted as variables only on non-materialised insight endpoints — a materialised
endpoint bakes its date range into the view, so callers can't shift the window.
date_fromdate_toAvoid:
- Variables that change the shape of the result — keep the columns stable. If callers need fundamentally different result shapes, ship separate endpoints.
- Variables that bypass safety — don't expose a variable that lets callers inject arbitrary SQL.
where_clause
所有需要随调用方变化的内容都应设为变量;其余内容硬编码到查询中。
对于HogQL端点,变量在查询负载中通过、和声明。每次执行调用需传入。
code_nametypedefault{ "variables": { "<code_name>": value } }常见模式:
- 时间窗口:、
date_from,或单个整数变量date_tolookback_days - 身份过滤:、
user_id、account_idteam_id - 超出/
limit的分页控制(这些是运行端点的原生参数)offset
对于洞察端点,细分维度属性作为变量(仅适用于Trends和Retention——Lifecycle无细分维度)。传入细分维度属性名称作为键。/仅在非物化洞察端点中可作为变量——物化端点会将日期范围固化到视图中,调用方无法调整时间窗口。
date_fromdate_to需避免:
- 会改变结果格式的变量——保持列稳定。若调用方需要完全不同的结果格式,应创建单独的端点。
- 存在安全风险的变量——不要暴露变量,以免调用方注入任意SQL。
where_clause
Creating from an existing insight
从现有洞察创建
There's no server-side "make an endpoint from insight N" operation. To do it: read the insight's
query (via the insight tools), pass that query to , and set
to the insight's short id so the origin is recorded. The endpoint then owns its own copy of
the query — later edits to the insight don't propagate. Starting from scratch instead? Build the
query first with the insight / tools, then create the endpoint from it.
endpoint-createderived_from_insightsql-variables目前没有服务器端“从洞察N创建端点”的操作。实现方法:通过洞察工具读取洞察的查询,将该查询传入,并将设为洞察的短ID,以记录来源。此时端点会拥有自己的查询副本——后续对洞察的编辑不会同步到端点。若要从零开始构建?先使用洞察/工具构建查询,再基于该查询创建端点。
endpoint-createderived_from_insightsql-variables5. Set data_freshness_seconds
data_freshness_seconds5. 设置data_freshness_seconds
data_freshness_secondsThis one field does two jobs, so set it deliberately:
- Cache TTL — results are served from cache until they're this many seconds old.
- Materialisation refresh frequency — on a materialised endpoint, this is also how often the warehouse recomputes the materialised view.
So a lower value means fresher data and more frequent recompute/refresh cost; a higher value is
cheaper on both counts but staler.
The value must be one of a fixed set: (15 min), (30 min), (1 h),
(6 h), (12 h), (24 h, default), (7 d). There is no sub-15-minute
option — is the floor.
90018003600216004320086400604800900 | When to pick it |
|---|---|
| 900–1800 | Freshest available — dashboards where staleness is visible |
| 3600–43200 | Most cases — fresh enough for product usage, cheap to recompute |
| 86400–604800 | Reports, weekly/daily metrics, anything aggregated over long periods |
Bias toward higher values unless the user explicitly needs fresher data. On a materialised
endpoint, remember this also sets the refresh cadence.
该字段承担两项功能,需谨慎设置:
- 缓存TTL——结果会从缓存中返回,直到缓存数据超过该秒数。
- 物化刷新频率——对于物化端点,该值同时决定数据仓库重新计算物化视图的频率。
因此,值越小意味着数据越新鲜,但重新计算/刷新的成本越高;值越大则成本越低,但数据越陈旧。
该值必须是以下固定值之一:(15分钟)、(30分钟)、(1小时)、(6小时)、(12小时)、(24小时,默认值)、(7天)。没有低于15分钟的选项——是最小值。
90018003600216004320086400604800900 | 适用场景 |
|---|---|
| 900–1800 | 最实时的数据——对数据陈旧度敏感的仪表板 |
| 3600–43200 | 大多数场景——数据新鲜度满足产品使用需求,重新计算成本低 |
| 86400–604800 | 报表、周/日度指标、任何长期聚合的数据 |
除非用户明确需要更实时的数据,否则优先选择较大的值。对于物化端点,需记住该值同时设置了刷新频率。
6. Decide on day-one materialisation
6. 决定是否在创建初期启用物化
See for the full decision tree. Short version:
references/materializing.md- Recommend materialisation when the endpoint will be called frequently, latency matters, and the user can tolerate staleness equal to the refresh interval (typically 5-15 minutes for scheduled materialisation, or hourly).
- Skip materialisation for low-traffic endpoints, exploratory new endpoints (you don't know yet if it'll get called), and queries where freshness is critical.
If unsure, create unmaterialised and add later once usage stabilises.
That avoids paying for materialisation on a query nobody ends up calling.
is_materialized: true完整的决策树请查看。简要说明:
references/materializing.md- 建议启用物化:当端点会被频繁调用、延迟至关重要,且用户可接受与刷新间隔相当的数据陈旧度(通常计划物化的间隔为5-15分钟,或每小时)。
- 不启用物化:低流量端点、新的探索性端点(尚不确定是否会被调用),以及对数据新鲜度要求极高的查询。
若不确定,可先创建非物化端点,待使用稳定后再添加。这样可避免为无人调用的查询支付物化成本。
is_materialized: trueWorkflow
工作流程
- Confirm the use case (step 1 above). If it's not actually a fit for an endpoint, recommend the alternative.
- Agree a name with the user.
- Walk through the query — confirm it's HogQL or insight, and that the columns/shape make sense.
- Identify what should be a variable. Show the user the variable declaration syntax.
- Pick based on the user's freshness requirement (ask if not clear) — remembering it also sets the materialisation refresh cadence.
data_freshness_seconds - Make the materialisation call. If on the fence, ship without and revisit later.
- Call with the agreed config.
endpoint-create - Confirm by calling with a sample payload to verify the response shape.
endpoint-run - Hand off to if the user is about to wire it up.
consuming-endpoints-from-client-code
- 确认使用场景(上述第1步)。若不适合创建端点,推荐替代方案。
- 与用户商定端点名称。
- 梳理查询——确认是HogQL还是洞察类型,且列/格式合理。
- 确定哪些内容应设为变量。向用户展示变量声明语法。
- 根据用户的新鲜度需求选择(若不明确则询问)——记住该值同时设置物化刷新频率。
data_freshness_seconds - 做出物化决策。若犹豫不决,先不启用,后续再重新考虑。
- 使用商定的配置调用。
endpoint-create - 通过调用并传入示例负载来验证响应格式,确认创建成功。
endpoint-run - 若用户即将进行客户端代码集成,可转交至指南。
consuming-endpoints-from-client-code
Example interaction
示例交互
text
User: "I want to expose our monthly active users count as an API
for our analytics partner"
Agent:
- "Quick check: is the partner going to call this on demand, or
should we be pushing data to them? Endpoints are pull-only."
- User: "On demand"
- "Got it. A few choices:
- Name: how about monthly_active_users? Lowercase, descriptive,
no version baggage.
- The query — is it HogQL or are you exposing an existing insight?
HogQL gives you exact column control; insight reuses what you've
already built.
- What should the partner be able to filter by? Org, time window,
both?
- How fresh? If MAU drifts within a day is fine, we can cache
results for 1-24 hours and serve almost everything from cache.
- Materialisation: if the partner is going to hit this many times
per day, materialising it would make responses near-instant.
The trade-off is ~10-15 minute staleness.
What's your starting point on these?"
[user picks: HogQL, lookback_days + org_id variables, 3600s TTL,
not materialised yet]
- endpoint-create monthly_active_users {query, variables, ...}
- endpoint-run with sample payload {org_id: "test", lookback_days: 30}
- "Created and tested. Want help wiring up the client code?
That's consuming-endpoints-from-client-code."text
用户:"我想将我们的月活跃用户数暴露为API,供我们的分析合作伙伴使用"
Agent:
- "快速确认:合作伙伴是按需调用,还是我们需要主动推送数据?端点仅支持拉取模式。"
- 用户:"按需调用"
- "明白了。有几个选项:
- 名称:使用monthly_active_users怎么样?小写、描述性强,无版本冗余。
- 查询类型——是HogQL还是暴露现有洞察?HogQL可让你精确控制列;洞察类型可复用已构建的内容。
- 合作伙伴需要按什么维度过滤?组织、时间窗口,还是两者都要?
- 数据新鲜度要求?如果月活跃用户数在一天内的波动可接受,我们可以将结果缓存1-24小时,几乎所有请求都从缓存返回。
- 物化:如果合作伙伴每天多次调用该端点,启用物化可让响应近乎即时。代价是数据会有~10-15分钟的延迟。
你对这些选项的初步想法是什么?"
[用户选择:HogQL,lookback_days + org_id变量,3600秒TTL,暂不启用物化]
- 调用endpoint-create创建monthly_active_users {query, variables, ...}
- 使用示例负载{org_id: "test", lookback_days: 30}调用endpoint-run
- "已创建并测试完成。需要帮助编写客户端代码吗?可参考consuming-endpoints-from-client-code指南。"Important notes
重要注意事项
- The name lives in the URL. Changing it later requires migrating callers. Pick well.
- HogQL endpoints are more flexible than insight endpoints. Default to HogQL unless the user has a specific reason to wrap an existing insight.
- Variables with no default fail at call time. Always set defaults during creation so the endpoint is testable from the playground without specifying every variable.
- Materialised endpoints require all variables to be passed. Calls without them are
rejected — this is intentional (security: prevents returning unfiltered data). Pair the
materialisation recommendation with a note to the user about which variables become required.
(Optional/partial variables on materialised endpoints are a known limitation the PostHog team
plans to lift — if it's blocking the user, nudge them via the tool.)
agent-feedback - Don't enable materialisation on a query that isn't eligible. Use
first to confirm eligibility and see the rejection reason if any.
endpoints-materialization-preview - Endpoints are not stable forever. When the user changes the query, a new version is created
automatically (the old version stays accessible via ).
?version=Nand materialisation are per-version. Adjust as the endpoint evolves.data_freshness_seconds - Recommend callers pin to a version. Tell the user to call with rather than relying on "latest" — that way a future query edit (which cuts a new version) can't silently change their results. They bump the pinned version deliberately once they've validated the new one.
?version=N - Share friction via . If a limitation gets in the way (eligibility rules, required variables, the TTL enum), send the PostHog team a note — it's how the product and these tools improve.
agent-feedback
- 名称会出现在URL中。后续修改名称需要迁移所有调用方。务必谨慎选择。
- HogQL端点比洞察端点更灵活。除非用户有特定理由封装现有洞察,否则默认选择HogQL。
- 无默认值的变量会导致调用失败。创建时务必设置默认值,以便在测试环境中无需指定所有变量即可测试端点。
- 物化端点要求传入所有变量。未传入变量的调用会被拒绝——这是有意设计的(安全考量:防止返回未过滤的数据)。在推荐物化时,需告知用户哪些变量会变为必填项。(物化端点的可选/部分变量是PostHog团队计划解决的已知限制——若该限制阻碍了用户,可通过工具反馈。)
agent-feedback - 不要对不符合条件的查询启用物化。先使用确认是否符合条件,若不符合可查看拒绝原因。
endpoints-materialization-preview - 端点并非永久稳定。当用户修改查询时,会自动创建新版本(旧版本仍可通过访问)。
?version=N和物化设置是按版本管理的。可随着端点的演进调整这些设置。data_freshness_seconds - 建议调用方固定版本。告知用户调用时使用,而非依赖“最新版本”——这样未来的查询编辑(会创建新版本)不会悄无声息地改变结果。用户可在验证新版本后,主动升级固定的版本号。
?version=N - 通过反馈问题。若遇到限制(如资格规则、必填变量、TTL枚举)阻碍使用,请向PostHog团队发送反馈——这有助于产品和工具的改进。
agent-feedback