[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-posthog-consuming-endpoints-from-client-code":3,"mdc--7unn09-key":49,"related-repo-posthog-consuming-endpoints-from-client-code":1832,"related-org-posthog-consuming-endpoints-from-client-code":1936},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":23,"repoUrl":24,"updatedAt":25,"license":26,"forks":27,"topics":28,"repo":44,"sourceUrl":47,"mdContent":48},"consuming-endpoints-from-client-code","integrate PostHog endpoints into client applications","Wire a PostHog endpoint into a client app or SDK. Covers fetching the OpenAPI spec, generating a typed client with openapi-generator or @hey-api\u002Fopenapi-ts, sending the right auth header, shaping the variables payload (HogQL code_name vs insight breakdown property), handling rate-limit and materialised-endpoint error responses. Use when the user says \"how do I call my endpoint\", \"generate a client for this\", or \"what auth header do I use\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"posthog","PostHog","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fposthog.png",[12,14,17,20],{"name":9,"slug":8,"type":13},"tag",{"name":15,"slug":16,"type":13},"API Development","api-development",{"name":18,"slug":19,"type":13},"SDK","sdk",{"name":21,"slug":22,"type":13},"Frontend","frontend",35568,"https:\u002F\u002Fgithub.com\u002FPostHog\u002Fposthog","2026-06-08T08:08:34.929454",null,2977,[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"ab-testing","ai-analytics","analytics","cdp","data-warehouse","experiments","feature-flags","javascript","product-analytics","python","react","session-replay","surveys","typescript","web-analytics",{"repoUrl":24,"stars":23,"forks":27,"topics":45,"description":46},[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"🦔 PostHog is an all-in-one developer platform for building successful products. We offer product analytics, web analytics, session replay, error tracking, feature flags, experimentation, surveys, data warehouse, a CDP, and an AI product assistant to help debug your code, ship features faster, and keep all your usage and customer data in one stack.","https:\u002F\u002Fgithub.com\u002FPostHog\u002Fposthog\u002Ftree\u002FHEAD\u002Fproducts\u002Fendpoints\u002Fskills\u002Fconsuming-endpoints-from-client-code","---\nname: consuming-endpoints-from-client-code\ndescription: >\n  Wire a PostHog endpoint into a client app or SDK. Covers fetching the OpenAPI spec, generating a\n  typed client with openapi-generator or @hey-api\u002Fopenapi-ts, sending the right auth header,\n  shaping the variables payload (HogQL code_name vs insight breakdown property), handling\n  rate-limit and materialised-endpoint error responses. Use when the user says \"how do I call my\n  endpoint\", \"generate a client for this\", or \"what auth header do I use\".\n---\n\n# Consuming endpoints from client code\n\nThis skill is the **caller-side** counterpart to `creating-an-endpoint`. It helps integrate an\nexisting endpoint into a separate codebase — a mobile app, server backend, customer dashboard,\nor downstream pipeline. No PostHog code is modified here.\n\n## When to use this skill\n\n- \"How do I call my endpoint?\" \u002F \"What does a request look like?\"\n- \"Generate a typed TypeScript \u002F Python \u002F Go client for this endpoint\"\n- \"I'm getting a 401 calling the endpoint\" \u002F auth questions\n- \"The endpoint rejects my call when I omit `user_id`\" → materialised-endpoint variable\n  questions\n- \"How do I handle rate limits?\"\n\nIf the user is **creating** the endpoint, use `creating-an-endpoint` first.\n\n## Available tools\n\n| Tool                    | Purpose                                                                                                    |\n| ----------------------- | ---------------------------------------------------------------------------------------------------------- |\n| `endpoint-get`          | Full config for a named endpoint, including the query shape and required variables                         |\n| `endpoint-openapi-spec` | OpenAPI 3.0 spec for one endpoint, ready to feed to a code generator                                       |\n| `endpoint-run`          | A live call against the endpoint — useful to confirm a payload works before sharing it with the user's app |\n\n## The endpoint URL\n\n```text\n\u002Fapi\u002Fprojects\u002F{team_id}\u002Fendpoints\u002F{name}\u002Frun\n```\n\n- `team_id` is the project ID (numeric). Available in PostHog under project settings, or via\n  `projects-get` if the user doesn't know it.\n- `name` is the endpoint name — see `endpoints-get-all` if the user isn't sure.\n- The trailing `\u002Frun` is required.\n\n`POST` is the canonical method. `GET` also works for simple cases without a request body but\nPOST is preferred — variables go in the body.\n\n## Auth\n\nEndpoints are authenticated with a **personal API key**. The header is:\n\n```http\nAuthorization: Bearer \u003Ckey>\n```\n\nKeys are scoped — for endpoints, the key needs at least `endpoint:read`. If the user gets a 403,\nthey're usually missing the scope; if they get a 401, the key is missing or malformed.\n\nNever put a personal API key in client-side code that's shipped to end users (mobile apps,\nbrowser JS). Personal API keys grant scoped account access. For customer-facing apps, route\nthrough the user's own backend, which holds the key.\n\n## The request payload\n\n```json\n{\n  \"variables\": { \"code_name_1\": value, \"code_name_2\": value },\n  \"limit\": 100,\n  \"offset\": 0,\n  \"refresh\": \"cache\"\n}\n```\n\n| Field       | Notes                                                                                                                                                                     |\n| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `variables` | Keyed by `code_name` for HogQL endpoints; for insight endpoints with breakdowns, key is the **breakdown property name**                                                   |\n| `limit`     | Max rows returned.                                                                                                                                                        |\n| `offset`    | Skip rows. Only HogQL endpoints                                                                                                                                           |\n| `refresh`   | `\"cache\"` (return cached results if fresh enough), `\"force\"` (always recalculate), `\"direct\"` (bypass materialisation, materialised endpoints only). Default is `\"cache\"` |\n\nCall `endpoint-get` to see the exact variable shape. The response includes the query definition\nwith declared variables — each variable's `code_name` is what the client should send.\n\n## Materialised endpoints: all variables are required\n\nIf `endpoint-get` shows `is_materialized: true` on the current version, the endpoint requires\n**every declared variable** to be passed on each call. This is a security boundary — without\nfilters, a single call would return the entire pre-aggregated dataset.\n\nCommon symptom: the user's app worked when the endpoint was unmaterialised, then started\nreturning 400 errors after materialisation was enabled. The error message lists which variables\nare missing.\n\nOptional\u002Fpartial variables on materialised endpoints are a known limitation the PostHog team plans\nto lift. If requiring every variable is blocking the user's use case, send a note via the\n`agent-feedback` tool — that demand signal is how the team prioritises it.\n\n## Generating a typed client\n\nThe endpoint exposes its own OpenAPI 3.0 spec via `endpoint-openapi-spec`. Feed that into a code\ngenerator:\n\n| Language   | Tool                    | Command shape                                                                    |\n| ---------- | ----------------------- | -------------------------------------------------------------------------------- |\n| TypeScript | `@hey-api\u002Fopenapi-ts`   | `openapi-ts -i spec.json -o .\u002Fgenerated`                                         |\n| TypeScript | `openapi-generator-cli` | `openapi-generator-cli generate -i spec.json -g typescript-fetch -o .\u002Fgenerated` |\n| Python     | `openapi-generator-cli` | `openapi-generator-cli generate -i spec.json -g python -o .\u002Fgenerated`           |\n| Go         | `oapi-codegen`          | `oapi-codegen -package=client spec.json > client.go`                             |\n\nThe generated client gives the user types for the variables payload and the response shape. Re-\ngenerate when the endpoint's query changes (each new version may have different variables).\n\nIf the user has multiple endpoints, generate a spec per endpoint and either combine them, or\ngenerate one client per endpoint and use them side-by-side.\n\n## Response shape\n\nA typical successful response:\n\n```json\n{\n  \"results\": [[...], [...]],\n  \"columns\": [\"col_a\", \"col_b\"],\n  \"types\": [\"Int64\", \"String\"],\n  \"hasMore\": false,\n  \"name\": \"endpoint_name\",\n  \"endpoint_version\": 4,\n  \"endpoint_version_created_at\": \"2026-01-15T...\"\n}\n```\n\n- `results` is an array of rows; each row is an array of cell values in the order of `columns`.\n- `endpoint_version` tells the client which version actually ran — useful for logging and for\n  pinning to a known version with `?version=N`.\n\nFor insight endpoints, the response shape depends on the query kind (`TrendsQuery`,\n`LifecycleQuery`, `RetentionQuery`) — the OpenAPI spec captures the right shape for the current\nversion. Insight kinds that can't be materialised (e.g. `FunnelsQuery`) still return their inline\nresult shape.\n\n## Calling from the PostHog CLI\n\nFor local testing, scripts, or CI, the repo's `posthog-cli` calls endpoints without hand-rolling\nHTTP:\n\n- `posthog-cli exp endpoints run` — execute an endpoint (from a local YAML definition)\n- `posthog-cli exp endpoints {list,get,pull,push,diff}` — inspect endpoints, or manage them as YAML\n  files in version control (GitOps-style)\n\nAuth uses the same personal API key, via `posthog-cli login` or the `POSTHOG_CLI_API_KEY` \u002F\n`POSTHOG_CLI_PROJECT_ID` \u002F `POSTHOG_CLI_HOST` env vars. (These live under `exp` — experimental, may\nchange.)\n\n## Error responses to handle\n\n| Status | When                                                                           | Handling                                                                         |\n| ------ | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- |\n| 400    | Missing required variable on a materialised endpoint, or invalid variable type | Surface the error message; fix the call                                          |\n| 401    | Missing \u002F wrong personal API key                                               | Check the Authorization header                                                   |\n| 403    | Key lacks `endpoint:read` scope, or endpoint is in another project             | Adjust key scopes                                                                |\n| 404    | Endpoint name typo, or endpoint not active                                     | Confirm name; check `is_active`                                                  |\n| 429    | Rate limited — limits are per team, not per endpoint (see note below)          | Exponential backoff; cache responses client-side if possible                     |\n| 5xx    | Query execution failure (ClickHouse error, timeout, etc.)                      | Retry with backoff. If persistent, hand off to `diagnosing-endpoint-performance` |\n\n## Workflow\n\n1. Confirm endpoint name. If unknown, list them with `execute-sql` on\n   `system.data_modeling_endpoints` (or `endpoints-get-all`).\n2. `endpoint-get` to see the full shape: variables, materialisation status, query kind.\n3. Decide the auth posture: personal API key on a server, never client-side.\n4. If the user wants generated types, call `endpoint-openapi-spec`, hand them the spec, and\n   recommend a generator for their language.\n5. Build a sample request payload from the variable declarations and walk through a test call.\n6. Optionally call `endpoint-run` from this skill to confirm the payload works.\n7. Wrap up with handling notes: the materialised-variables rule, the rate-limit shape, and\n   pinning to a version with `?version=N`.\n\n## Example interaction\n\n```text\nUser: \"I want to call monthly_active_users from my Node.js backend.\n       Can you help me wire it up with types?\"\n\nAgent steps:\n- endpoint-get monthly_active_users → HogQL, variables: lookback_days\n  (int, default 30), org_id (string, no default), is_materialized: true\n- \"Two things to know upfront:\n   1. This endpoint is materialised, so both lookback_days and org_id\n      must be passed on every call. Calls without them will be rejected.\n   2. You'll need a personal API key with endpoint:read scope. Set it\n      as PH_API_KEY in your server env — never ship it in client code.\"\n\n- endpoint-openapi-spec monthly_active_users → returns spec\n\n- \"Here's the spec. Drop it in your repo and run:\n     pnpm dlx @hey-api\u002Fopenapi-ts -i spec.json -o .\u002Fgenerated\u002Fposthog\n   That gives you typed client functions.\n\n   A minimum call looks like:\n     POST \u002Fapi\u002Fprojects\u002F12345\u002Fendpoints\u002Fmonthly_active_users\u002Frun\n     Authorization: Bearer \u003CPH_API_KEY>\n     Content-Type: application\u002Fjson\n\n     { 'variables': { 'org_id': 'acme', 'lookback_days': 30 } }\n\n   The response includes columns and rows — your client will pick that\n   up from the generated types.\n\n   Want me to do a sample call to verify the payload works?\"\n```\n\n## Important notes\n\n- **Personal API keys are server-side only.** Never ship them in mobile apps or browser JS.\n- **Re-generate the client when the query changes.** Each new endpoint version may add or\n  remove variables — keep types in sync by re-fetching the spec.\n- **Materialised endpoints reject calls missing variables.** This is intentional. If the user\n  reports a 400 after materialisation was enabled, the fix is in the call, not in the endpoint.\n- **Pin to a version — don't rely on \"latest\".** Always call with `?version=N`. Without it the\n  latest active version runs, so a future query edit (which cuts a new version) can silently change\n  a caller's results. Bump the pinned version deliberately once you've validated the new one.\n- **Caching on the client side is fair game.** The endpoint already caches via\n  `data_freshness_seconds`, but the client can layer another cache on top for hot paths. Be\n  mindful of total staleness (endpoint cache + client cache).\n- **Rate limits are per team, by category — not per endpoint.** Calls to non-materialised\n  endpoints share the team-wide API-query budget (~240\u002Fmin burst, ~2400\u002Fhour sustained) with all\n  other query traffic; materialised endpoints draw on a separate, higher shared bucket\n  (~1200\u002Fmin, ~12000\u002Fhour). There is no per-endpoint-name limit, so hammering one endpoint can\n  starve others on the same team. Heavy callers should batch where possible and back off on 429.\n- **Pricing.** Calling endpoints isn't billed today, but it will be once endpoints ship alongside\n  the [managed warehouse](https:\u002F\u002Fposthog.com\u002Fdata-stack\u002Fmanaged-warehouse). Flag this to the user\n  if they're planning high-volume usage so the future cost isn't a surprise.\n- **Tell PostHog what's missing.** If an error, a limit, or a missing capability gets in the way,\n  use the `agent-feedback` tool — it's the main signal the team uses to improve endpoints and these\n  tools.\n",{"data":50,"body":51},{"name":4,"description":6},{"type":52,"children":53},"root",[54,62,85,92,130,149,155,234,240,252,306,325,331,343,362,375,380,386,598,724,743,749,776,781,794,800,812,940,945,950,956,961,1274,1311,1347,1353,1366,1391,1436,1442,1596,1602,1689,1695,1704,1710,1826],{"type":55,"tag":56,"props":57,"children":58},"element","h1",{"id":4},[59],{"type":60,"value":61},"text","Consuming endpoints from client code",{"type":55,"tag":63,"props":64,"children":65},"p",{},[66,68,74,76,83],{"type":60,"value":67},"This skill is the ",{"type":55,"tag":69,"props":70,"children":71},"strong",{},[72],{"type":60,"value":73},"caller-side",{"type":60,"value":75}," counterpart to ",{"type":55,"tag":77,"props":78,"children":80},"code",{"className":79},[],[81],{"type":60,"value":82},"creating-an-endpoint",{"type":60,"value":84},". It helps integrate an\nexisting endpoint into a separate codebase — a mobile app, server backend, customer dashboard,\nor downstream pipeline. No PostHog code is modified here.",{"type":55,"tag":86,"props":87,"children":89},"h2",{"id":88},"when-to-use-this-skill",[90],{"type":60,"value":91},"When to use this skill",{"type":55,"tag":93,"props":94,"children":95},"ul",{},[96,102,107,112,125],{"type":55,"tag":97,"props":98,"children":99},"li",{},[100],{"type":60,"value":101},"\"How do I call my endpoint?\" \u002F \"What does a request look like?\"",{"type":55,"tag":97,"props":103,"children":104},{},[105],{"type":60,"value":106},"\"Generate a typed TypeScript \u002F Python \u002F Go client for this endpoint\"",{"type":55,"tag":97,"props":108,"children":109},{},[110],{"type":60,"value":111},"\"I'm getting a 401 calling the endpoint\" \u002F auth questions",{"type":55,"tag":97,"props":113,"children":114},{},[115,117,123],{"type":60,"value":116},"\"The endpoint rejects my call when I omit ",{"type":55,"tag":77,"props":118,"children":120},{"className":119},[],[121],{"type":60,"value":122},"user_id",{"type":60,"value":124},"\" → materialised-endpoint variable\nquestions",{"type":55,"tag":97,"props":126,"children":127},{},[128],{"type":60,"value":129},"\"How do I handle rate limits?\"",{"type":55,"tag":63,"props":131,"children":132},{},[133,135,140,142,147],{"type":60,"value":134},"If the user is ",{"type":55,"tag":69,"props":136,"children":137},{},[138],{"type":60,"value":139},"creating",{"type":60,"value":141}," the endpoint, use ",{"type":55,"tag":77,"props":143,"children":145},{"className":144},[],[146],{"type":60,"value":82},{"type":60,"value":148}," first.",{"type":55,"tag":86,"props":150,"children":152},{"id":151},"available-tools",[153],{"type":60,"value":154},"Available tools",{"type":55,"tag":156,"props":157,"children":158},"table",{},[159,178],{"type":55,"tag":160,"props":161,"children":162},"thead",{},[163],{"type":55,"tag":164,"props":165,"children":166},"tr",{},[167,173],{"type":55,"tag":168,"props":169,"children":170},"th",{},[171],{"type":60,"value":172},"Tool",{"type":55,"tag":168,"props":174,"children":175},{},[176],{"type":60,"value":177},"Purpose",{"type":55,"tag":179,"props":180,"children":181},"tbody",{},[182,200,217],{"type":55,"tag":164,"props":183,"children":184},{},[185,195],{"type":55,"tag":186,"props":187,"children":188},"td",{},[189],{"type":55,"tag":77,"props":190,"children":192},{"className":191},[],[193],{"type":60,"value":194},"endpoint-get",{"type":55,"tag":186,"props":196,"children":197},{},[198],{"type":60,"value":199},"Full config for a named endpoint, including the query shape and required variables",{"type":55,"tag":164,"props":201,"children":202},{},[203,212],{"type":55,"tag":186,"props":204,"children":205},{},[206],{"type":55,"tag":77,"props":207,"children":209},{"className":208},[],[210],{"type":60,"value":211},"endpoint-openapi-spec",{"type":55,"tag":186,"props":213,"children":214},{},[215],{"type":60,"value":216},"OpenAPI 3.0 spec for one endpoint, ready to feed to a code generator",{"type":55,"tag":164,"props":218,"children":219},{},[220,229],{"type":55,"tag":186,"props":221,"children":222},{},[223],{"type":55,"tag":77,"props":224,"children":226},{"className":225},[],[227],{"type":60,"value":228},"endpoint-run",{"type":55,"tag":186,"props":230,"children":231},{},[232],{"type":60,"value":233},"A live call against the endpoint — useful to confirm a payload works before sharing it with the user's app",{"type":55,"tag":86,"props":235,"children":237},{"id":236},"the-endpoint-url",[238],{"type":60,"value":239},"The endpoint URL",{"type":55,"tag":241,"props":242,"children":247},"pre",{"className":243,"code":245,"language":60,"meta":246},[244],"language-text","\u002Fapi\u002Fprojects\u002F{team_id}\u002Fendpoints\u002F{name}\u002Frun\n","",[248],{"type":55,"tag":77,"props":249,"children":250},{"__ignoreMap":246},[251],{"type":60,"value":245},{"type":55,"tag":93,"props":253,"children":254},{},[255,274,293],{"type":55,"tag":97,"props":256,"children":257},{},[258,264,266,272],{"type":55,"tag":77,"props":259,"children":261},{"className":260},[],[262],{"type":60,"value":263},"team_id",{"type":60,"value":265}," is the project ID (numeric). Available in PostHog under project settings, or via\n",{"type":55,"tag":77,"props":267,"children":269},{"className":268},[],[270],{"type":60,"value":271},"projects-get",{"type":60,"value":273}," if the user doesn't know it.",{"type":55,"tag":97,"props":275,"children":276},{},[277,283,285,291],{"type":55,"tag":77,"props":278,"children":280},{"className":279},[],[281],{"type":60,"value":282},"name",{"type":60,"value":284}," is the endpoint name — see ",{"type":55,"tag":77,"props":286,"children":288},{"className":287},[],[289],{"type":60,"value":290},"endpoints-get-all",{"type":60,"value":292}," if the user isn't sure.",{"type":55,"tag":97,"props":294,"children":295},{},[296,298,304],{"type":60,"value":297},"The trailing ",{"type":55,"tag":77,"props":299,"children":301},{"className":300},[],[302],{"type":60,"value":303},"\u002Frun",{"type":60,"value":305}," is required.",{"type":55,"tag":63,"props":307,"children":308},{},[309,315,317,323],{"type":55,"tag":77,"props":310,"children":312},{"className":311},[],[313],{"type":60,"value":314},"POST",{"type":60,"value":316}," is the canonical method. ",{"type":55,"tag":77,"props":318,"children":320},{"className":319},[],[321],{"type":60,"value":322},"GET",{"type":60,"value":324}," also works for simple cases without a request body but\nPOST is preferred — variables go in the body.",{"type":55,"tag":86,"props":326,"children":328},{"id":327},"auth",[329],{"type":60,"value":330},"Auth",{"type":55,"tag":63,"props":332,"children":333},{},[334,336,341],{"type":60,"value":335},"Endpoints are authenticated with a ",{"type":55,"tag":69,"props":337,"children":338},{},[339],{"type":60,"value":340},"personal API key",{"type":60,"value":342},". The header is:",{"type":55,"tag":241,"props":344,"children":348},{"className":345,"code":346,"language":347,"meta":246,"style":246},"language-http shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","Authorization: Bearer \u003Ckey>\n","http",[349],{"type":55,"tag":77,"props":350,"children":351},{"__ignoreMap":246},[352],{"type":55,"tag":353,"props":354,"children":357},"span",{"class":355,"line":356},"line",1,[358],{"type":55,"tag":353,"props":359,"children":360},{},[361],{"type":60,"value":346},{"type":55,"tag":63,"props":363,"children":364},{},[365,367,373],{"type":60,"value":366},"Keys are scoped — for endpoints, the key needs at least ",{"type":55,"tag":77,"props":368,"children":370},{"className":369},[],[371],{"type":60,"value":372},"endpoint:read",{"type":60,"value":374},". If the user gets a 403,\nthey're usually missing the scope; if they get a 401, the key is missing or malformed.",{"type":55,"tag":63,"props":376,"children":377},{},[378],{"type":60,"value":379},"Never put a personal API key in client-side code that's shipped to end users (mobile apps,\nbrowser JS). Personal API keys grant scoped account access. For customer-facing apps, route\nthrough the user's own backend, which holds the key.",{"type":55,"tag":86,"props":381,"children":383},{"id":382},"the-request-payload",[384],{"type":60,"value":385},"The request payload",{"type":55,"tag":241,"props":387,"children":391},{"className":388,"code":389,"language":390,"meta":246,"style":246},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"variables\": { \"code_name_1\": value, \"code_name_2\": value },\n  \"limit\": 100,\n  \"offset\": 0,\n  \"refresh\": \"cache\"\n}\n","json",[392],{"type":55,"tag":77,"props":393,"children":394},{"__ignoreMap":246},[395,404,491,523,553,589],{"type":55,"tag":353,"props":396,"children":397},{"class":355,"line":356},[398],{"type":55,"tag":353,"props":399,"children":401},{"style":400},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[402],{"type":60,"value":403},"{\n",{"type":55,"tag":353,"props":405,"children":407},{"class":355,"line":406},2,[408,413,419,424,429,434,439,445,449,453,459,464,468,473,477,481,486],{"type":55,"tag":353,"props":409,"children":410},{"style":400},[411],{"type":60,"value":412},"  \"",{"type":55,"tag":353,"props":414,"children":416},{"style":415},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[417],{"type":60,"value":418},"variables",{"type":55,"tag":353,"props":420,"children":421},{"style":400},[422],{"type":60,"value":423},"\"",{"type":55,"tag":353,"props":425,"children":426},{"style":400},[427],{"type":60,"value":428},":",{"type":55,"tag":353,"props":430,"children":431},{"style":400},[432],{"type":60,"value":433}," {",{"type":55,"tag":353,"props":435,"children":436},{"style":400},[437],{"type":60,"value":438}," \"",{"type":55,"tag":353,"props":440,"children":442},{"style":441},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[443],{"type":60,"value":444},"code_name_1",{"type":55,"tag":353,"props":446,"children":447},{"style":400},[448],{"type":60,"value":423},{"type":55,"tag":353,"props":450,"children":451},{"style":400},[452],{"type":60,"value":428},{"type":55,"tag":353,"props":454,"children":456},{"style":455},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[457],{"type":60,"value":458}," value",{"type":55,"tag":353,"props":460,"children":461},{"style":400},[462],{"type":60,"value":463},",",{"type":55,"tag":353,"props":465,"children":466},{"style":400},[467],{"type":60,"value":438},{"type":55,"tag":353,"props":469,"children":470},{"style":441},[471],{"type":60,"value":472},"code_name_2",{"type":55,"tag":353,"props":474,"children":475},{"style":400},[476],{"type":60,"value":423},{"type":55,"tag":353,"props":478,"children":479},{"style":400},[480],{"type":60,"value":428},{"type":55,"tag":353,"props":482,"children":483},{"style":455},[484],{"type":60,"value":485}," value ",{"type":55,"tag":353,"props":487,"children":488},{"style":400},[489],{"type":60,"value":490},"},\n",{"type":55,"tag":353,"props":492,"children":494},{"class":355,"line":493},3,[495,499,504,508,512,518],{"type":55,"tag":353,"props":496,"children":497},{"style":400},[498],{"type":60,"value":412},{"type":55,"tag":353,"props":500,"children":501},{"style":415},[502],{"type":60,"value":503},"limit",{"type":55,"tag":353,"props":505,"children":506},{"style":400},[507],{"type":60,"value":423},{"type":55,"tag":353,"props":509,"children":510},{"style":400},[511],{"type":60,"value":428},{"type":55,"tag":353,"props":513,"children":515},{"style":514},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[516],{"type":60,"value":517}," 100",{"type":55,"tag":353,"props":519,"children":520},{"style":400},[521],{"type":60,"value":522},",\n",{"type":55,"tag":353,"props":524,"children":526},{"class":355,"line":525},4,[527,531,536,540,544,549],{"type":55,"tag":353,"props":528,"children":529},{"style":400},[530],{"type":60,"value":412},{"type":55,"tag":353,"props":532,"children":533},{"style":415},[534],{"type":60,"value":535},"offset",{"type":55,"tag":353,"props":537,"children":538},{"style":400},[539],{"type":60,"value":423},{"type":55,"tag":353,"props":541,"children":542},{"style":400},[543],{"type":60,"value":428},{"type":55,"tag":353,"props":545,"children":546},{"style":514},[547],{"type":60,"value":548}," 0",{"type":55,"tag":353,"props":550,"children":551},{"style":400},[552],{"type":60,"value":522},{"type":55,"tag":353,"props":554,"children":556},{"class":355,"line":555},5,[557,561,566,570,574,578,584],{"type":55,"tag":353,"props":558,"children":559},{"style":400},[560],{"type":60,"value":412},{"type":55,"tag":353,"props":562,"children":563},{"style":415},[564],{"type":60,"value":565},"refresh",{"type":55,"tag":353,"props":567,"children":568},{"style":400},[569],{"type":60,"value":423},{"type":55,"tag":353,"props":571,"children":572},{"style":400},[573],{"type":60,"value":428},{"type":55,"tag":353,"props":575,"children":576},{"style":400},[577],{"type":60,"value":438},{"type":55,"tag":353,"props":579,"children":581},{"style":580},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[582],{"type":60,"value":583},"cache",{"type":55,"tag":353,"props":585,"children":586},{"style":400},[587],{"type":60,"value":588},"\"\n",{"type":55,"tag":353,"props":590,"children":592},{"class":355,"line":591},6,[593],{"type":55,"tag":353,"props":594,"children":595},{"style":400},[596],{"type":60,"value":597},"}\n",{"type":55,"tag":156,"props":599,"children":600},{},[601,617],{"type":55,"tag":160,"props":602,"children":603},{},[604],{"type":55,"tag":164,"props":605,"children":606},{},[607,612],{"type":55,"tag":168,"props":608,"children":609},{},[610],{"type":60,"value":611},"Field",{"type":55,"tag":168,"props":613,"children":614},{},[615],{"type":60,"value":616},"Notes",{"type":55,"tag":179,"props":618,"children":619},{},[620,649,665,681],{"type":55,"tag":164,"props":621,"children":622},{},[623,631],{"type":55,"tag":186,"props":624,"children":625},{},[626],{"type":55,"tag":77,"props":627,"children":629},{"className":628},[],[630],{"type":60,"value":418},{"type":55,"tag":186,"props":632,"children":633},{},[634,636,642,644],{"type":60,"value":635},"Keyed by ",{"type":55,"tag":77,"props":637,"children":639},{"className":638},[],[640],{"type":60,"value":641},"code_name",{"type":60,"value":643}," for HogQL endpoints; for insight endpoints with breakdowns, key is the ",{"type":55,"tag":69,"props":645,"children":646},{},[647],{"type":60,"value":648},"breakdown property name",{"type":55,"tag":164,"props":650,"children":651},{},[652,660],{"type":55,"tag":186,"props":653,"children":654},{},[655],{"type":55,"tag":77,"props":656,"children":658},{"className":657},[],[659],{"type":60,"value":503},{"type":55,"tag":186,"props":661,"children":662},{},[663],{"type":60,"value":664},"Max rows returned.",{"type":55,"tag":164,"props":666,"children":667},{},[668,676],{"type":55,"tag":186,"props":669,"children":670},{},[671],{"type":55,"tag":77,"props":672,"children":674},{"className":673},[],[675],{"type":60,"value":535},{"type":55,"tag":186,"props":677,"children":678},{},[679],{"type":60,"value":680},"Skip rows. Only HogQL endpoints",{"type":55,"tag":164,"props":682,"children":683},{},[684,692],{"type":55,"tag":186,"props":685,"children":686},{},[687],{"type":55,"tag":77,"props":688,"children":690},{"className":689},[],[691],{"type":60,"value":565},{"type":55,"tag":186,"props":693,"children":694},{},[695,701,703,709,711,717,719],{"type":55,"tag":77,"props":696,"children":698},{"className":697},[],[699],{"type":60,"value":700},"\"cache\"",{"type":60,"value":702}," (return cached results if fresh enough), ",{"type":55,"tag":77,"props":704,"children":706},{"className":705},[],[707],{"type":60,"value":708},"\"force\"",{"type":60,"value":710}," (always recalculate), ",{"type":55,"tag":77,"props":712,"children":714},{"className":713},[],[715],{"type":60,"value":716},"\"direct\"",{"type":60,"value":718}," (bypass materialisation, materialised endpoints only). Default is ",{"type":55,"tag":77,"props":720,"children":722},{"className":721},[],[723],{"type":60,"value":700},{"type":55,"tag":63,"props":725,"children":726},{},[727,729,734,736,741],{"type":60,"value":728},"Call ",{"type":55,"tag":77,"props":730,"children":732},{"className":731},[],[733],{"type":60,"value":194},{"type":60,"value":735}," to see the exact variable shape. The response includes the query definition\nwith declared variables — each variable's ",{"type":55,"tag":77,"props":737,"children":739},{"className":738},[],[740],{"type":60,"value":641},{"type":60,"value":742}," is what the client should send.",{"type":55,"tag":86,"props":744,"children":746},{"id":745},"materialised-endpoints-all-variables-are-required",[747],{"type":60,"value":748},"Materialised endpoints: all variables are required",{"type":55,"tag":63,"props":750,"children":751},{},[752,754,759,761,767,769,774],{"type":60,"value":753},"If ",{"type":55,"tag":77,"props":755,"children":757},{"className":756},[],[758],{"type":60,"value":194},{"type":60,"value":760}," shows ",{"type":55,"tag":77,"props":762,"children":764},{"className":763},[],[765],{"type":60,"value":766},"is_materialized: true",{"type":60,"value":768}," on the current version, the endpoint requires\n",{"type":55,"tag":69,"props":770,"children":771},{},[772],{"type":60,"value":773},"every declared variable",{"type":60,"value":775}," to be passed on each call. This is a security boundary — without\nfilters, a single call would return the entire pre-aggregated dataset.",{"type":55,"tag":63,"props":777,"children":778},{},[779],{"type":60,"value":780},"Common symptom: the user's app worked when the endpoint was unmaterialised, then started\nreturning 400 errors after materialisation was enabled. The error message lists which variables\nare missing.",{"type":55,"tag":63,"props":782,"children":783},{},[784,786,792],{"type":60,"value":785},"Optional\u002Fpartial variables on materialised endpoints are a known limitation the PostHog team plans\nto lift. If requiring every variable is blocking the user's use case, send a note via the\n",{"type":55,"tag":77,"props":787,"children":789},{"className":788},[],[790],{"type":60,"value":791},"agent-feedback",{"type":60,"value":793}," tool — that demand signal is how the team prioritises it.",{"type":55,"tag":86,"props":795,"children":797},{"id":796},"generating-a-typed-client",[798],{"type":60,"value":799},"Generating a typed client",{"type":55,"tag":63,"props":801,"children":802},{},[803,805,810],{"type":60,"value":804},"The endpoint exposes its own OpenAPI 3.0 spec via ",{"type":55,"tag":77,"props":806,"children":808},{"className":807},[],[809],{"type":60,"value":211},{"type":60,"value":811},". Feed that into a code\ngenerator:",{"type":55,"tag":156,"props":813,"children":814},{},[815,835],{"type":55,"tag":160,"props":816,"children":817},{},[818],{"type":55,"tag":164,"props":819,"children":820},{},[821,826,830],{"type":55,"tag":168,"props":822,"children":823},{},[824],{"type":60,"value":825},"Language",{"type":55,"tag":168,"props":827,"children":828},{},[829],{"type":60,"value":172},{"type":55,"tag":168,"props":831,"children":832},{},[833],{"type":60,"value":834},"Command shape",{"type":55,"tag":179,"props":836,"children":837},{},[838,864,889,914],{"type":55,"tag":164,"props":839,"children":840},{},[841,846,855],{"type":55,"tag":186,"props":842,"children":843},{},[844],{"type":60,"value":845},"TypeScript",{"type":55,"tag":186,"props":847,"children":848},{},[849],{"type":55,"tag":77,"props":850,"children":852},{"className":851},[],[853],{"type":60,"value":854},"@hey-api\u002Fopenapi-ts",{"type":55,"tag":186,"props":856,"children":857},{},[858],{"type":55,"tag":77,"props":859,"children":861},{"className":860},[],[862],{"type":60,"value":863},"openapi-ts -i spec.json -o .\u002Fgenerated",{"type":55,"tag":164,"props":865,"children":866},{},[867,871,880],{"type":55,"tag":186,"props":868,"children":869},{},[870],{"type":60,"value":845},{"type":55,"tag":186,"props":872,"children":873},{},[874],{"type":55,"tag":77,"props":875,"children":877},{"className":876},[],[878],{"type":60,"value":879},"openapi-generator-cli",{"type":55,"tag":186,"props":881,"children":882},{},[883],{"type":55,"tag":77,"props":884,"children":886},{"className":885},[],[887],{"type":60,"value":888},"openapi-generator-cli generate -i spec.json -g typescript-fetch -o .\u002Fgenerated",{"type":55,"tag":164,"props":890,"children":891},{},[892,897,905],{"type":55,"tag":186,"props":893,"children":894},{},[895],{"type":60,"value":896},"Python",{"type":55,"tag":186,"props":898,"children":899},{},[900],{"type":55,"tag":77,"props":901,"children":903},{"className":902},[],[904],{"type":60,"value":879},{"type":55,"tag":186,"props":906,"children":907},{},[908],{"type":55,"tag":77,"props":909,"children":911},{"className":910},[],[912],{"type":60,"value":913},"openapi-generator-cli generate -i spec.json -g python -o .\u002Fgenerated",{"type":55,"tag":164,"props":915,"children":916},{},[917,922,931],{"type":55,"tag":186,"props":918,"children":919},{},[920],{"type":60,"value":921},"Go",{"type":55,"tag":186,"props":923,"children":924},{},[925],{"type":55,"tag":77,"props":926,"children":928},{"className":927},[],[929],{"type":60,"value":930},"oapi-codegen",{"type":55,"tag":186,"props":932,"children":933},{},[934],{"type":55,"tag":77,"props":935,"children":937},{"className":936},[],[938],{"type":60,"value":939},"oapi-codegen -package=client spec.json > client.go",{"type":55,"tag":63,"props":941,"children":942},{},[943],{"type":60,"value":944},"The generated client gives the user types for the variables payload and the response shape. Re-\ngenerate when the endpoint's query changes (each new version may have different variables).",{"type":55,"tag":63,"props":946,"children":947},{},[948],{"type":60,"value":949},"If the user has multiple endpoints, generate a spec per endpoint and either combine them, or\ngenerate one client per endpoint and use them side-by-side.",{"type":55,"tag":86,"props":951,"children":953},{"id":952},"response-shape",[954],{"type":60,"value":955},"Response shape",{"type":55,"tag":63,"props":957,"children":958},{},[959],{"type":60,"value":960},"A typical successful response:",{"type":55,"tag":241,"props":962,"children":964},{"className":388,"code":963,"language":390,"meta":246,"style":246},"{\n  \"results\": [[...], [...]],\n  \"columns\": [\"col_a\", \"col_b\"],\n  \"types\": [\"Int64\", \"String\"],\n  \"hasMore\": false,\n  \"name\": \"endpoint_name\",\n  \"endpoint_version\": 4,\n  \"endpoint_version_created_at\": \"2026-01-15T...\"\n}\n",[965],{"type":55,"tag":77,"props":966,"children":967},{"__ignoreMap":246},[968,975,1024,1083,1141,1166,1202,1232,1266],{"type":55,"tag":353,"props":969,"children":970},{"class":355,"line":356},[971],{"type":55,"tag":353,"props":972,"children":973},{"style":400},[974],{"type":60,"value":403},{"type":55,"tag":353,"props":976,"children":977},{"class":355,"line":406},[978,982,987,991,995,1000,1005,1010,1015,1019],{"type":55,"tag":353,"props":979,"children":980},{"style":400},[981],{"type":60,"value":412},{"type":55,"tag":353,"props":983,"children":984},{"style":415},[985],{"type":60,"value":986},"results",{"type":55,"tag":353,"props":988,"children":989},{"style":400},[990],{"type":60,"value":423},{"type":55,"tag":353,"props":992,"children":993},{"style":400},[994],{"type":60,"value":428},{"type":55,"tag":353,"props":996,"children":997},{"style":400},[998],{"type":60,"value":999}," [[",{"type":55,"tag":353,"props":1001,"children":1002},{"style":455},[1003],{"type":60,"value":1004},"...",{"type":55,"tag":353,"props":1006,"children":1007},{"style":400},[1008],{"type":60,"value":1009},"],",{"type":55,"tag":353,"props":1011,"children":1012},{"style":400},[1013],{"type":60,"value":1014}," [",{"type":55,"tag":353,"props":1016,"children":1017},{"style":455},[1018],{"type":60,"value":1004},{"type":55,"tag":353,"props":1020,"children":1021},{"style":400},[1022],{"type":60,"value":1023},"]],\n",{"type":55,"tag":353,"props":1025,"children":1026},{"class":355,"line":493},[1027,1031,1036,1040,1044,1048,1052,1057,1061,1065,1069,1074,1078],{"type":55,"tag":353,"props":1028,"children":1029},{"style":400},[1030],{"type":60,"value":412},{"type":55,"tag":353,"props":1032,"children":1033},{"style":415},[1034],{"type":60,"value":1035},"columns",{"type":55,"tag":353,"props":1037,"children":1038},{"style":400},[1039],{"type":60,"value":423},{"type":55,"tag":353,"props":1041,"children":1042},{"style":400},[1043],{"type":60,"value":428},{"type":55,"tag":353,"props":1045,"children":1046},{"style":400},[1047],{"type":60,"value":1014},{"type":55,"tag":353,"props":1049,"children":1050},{"style":400},[1051],{"type":60,"value":423},{"type":55,"tag":353,"props":1053,"children":1054},{"style":580},[1055],{"type":60,"value":1056},"col_a",{"type":55,"tag":353,"props":1058,"children":1059},{"style":400},[1060],{"type":60,"value":423},{"type":55,"tag":353,"props":1062,"children":1063},{"style":400},[1064],{"type":60,"value":463},{"type":55,"tag":353,"props":1066,"children":1067},{"style":400},[1068],{"type":60,"value":438},{"type":55,"tag":353,"props":1070,"children":1071},{"style":580},[1072],{"type":60,"value":1073},"col_b",{"type":55,"tag":353,"props":1075,"children":1076},{"style":400},[1077],{"type":60,"value":423},{"type":55,"tag":353,"props":1079,"children":1080},{"style":400},[1081],{"type":60,"value":1082},"],\n",{"type":55,"tag":353,"props":1084,"children":1085},{"class":355,"line":525},[1086,1090,1095,1099,1103,1107,1111,1116,1120,1124,1128,1133,1137],{"type":55,"tag":353,"props":1087,"children":1088},{"style":400},[1089],{"type":60,"value":412},{"type":55,"tag":353,"props":1091,"children":1092},{"style":415},[1093],{"type":60,"value":1094},"types",{"type":55,"tag":353,"props":1096,"children":1097},{"style":400},[1098],{"type":60,"value":423},{"type":55,"tag":353,"props":1100,"children":1101},{"style":400},[1102],{"type":60,"value":428},{"type":55,"tag":353,"props":1104,"children":1105},{"style":400},[1106],{"type":60,"value":1014},{"type":55,"tag":353,"props":1108,"children":1109},{"style":400},[1110],{"type":60,"value":423},{"type":55,"tag":353,"props":1112,"children":1113},{"style":580},[1114],{"type":60,"value":1115},"Int64",{"type":55,"tag":353,"props":1117,"children":1118},{"style":400},[1119],{"type":60,"value":423},{"type":55,"tag":353,"props":1121,"children":1122},{"style":400},[1123],{"type":60,"value":463},{"type":55,"tag":353,"props":1125,"children":1126},{"style":400},[1127],{"type":60,"value":438},{"type":55,"tag":353,"props":1129,"children":1130},{"style":580},[1131],{"type":60,"value":1132},"String",{"type":55,"tag":353,"props":1134,"children":1135},{"style":400},[1136],{"type":60,"value":423},{"type":55,"tag":353,"props":1138,"children":1139},{"style":400},[1140],{"type":60,"value":1082},{"type":55,"tag":353,"props":1142,"children":1143},{"class":355,"line":555},[1144,1148,1153,1157,1161],{"type":55,"tag":353,"props":1145,"children":1146},{"style":400},[1147],{"type":60,"value":412},{"type":55,"tag":353,"props":1149,"children":1150},{"style":415},[1151],{"type":60,"value":1152},"hasMore",{"type":55,"tag":353,"props":1154,"children":1155},{"style":400},[1156],{"type":60,"value":423},{"type":55,"tag":353,"props":1158,"children":1159},{"style":400},[1160],{"type":60,"value":428},{"type":55,"tag":353,"props":1162,"children":1163},{"style":400},[1164],{"type":60,"value":1165}," false,\n",{"type":55,"tag":353,"props":1167,"children":1168},{"class":355,"line":591},[1169,1173,1177,1181,1185,1189,1194,1198],{"type":55,"tag":353,"props":1170,"children":1171},{"style":400},[1172],{"type":60,"value":412},{"type":55,"tag":353,"props":1174,"children":1175},{"style":415},[1176],{"type":60,"value":282},{"type":55,"tag":353,"props":1178,"children":1179},{"style":400},[1180],{"type":60,"value":423},{"type":55,"tag":353,"props":1182,"children":1183},{"style":400},[1184],{"type":60,"value":428},{"type":55,"tag":353,"props":1186,"children":1187},{"style":400},[1188],{"type":60,"value":438},{"type":55,"tag":353,"props":1190,"children":1191},{"style":580},[1192],{"type":60,"value":1193},"endpoint_name",{"type":55,"tag":353,"props":1195,"children":1196},{"style":400},[1197],{"type":60,"value":423},{"type":55,"tag":353,"props":1199,"children":1200},{"style":400},[1201],{"type":60,"value":522},{"type":55,"tag":353,"props":1203,"children":1205},{"class":355,"line":1204},7,[1206,1210,1215,1219,1223,1228],{"type":55,"tag":353,"props":1207,"children":1208},{"style":400},[1209],{"type":60,"value":412},{"type":55,"tag":353,"props":1211,"children":1212},{"style":415},[1213],{"type":60,"value":1214},"endpoint_version",{"type":55,"tag":353,"props":1216,"children":1217},{"style":400},[1218],{"type":60,"value":423},{"type":55,"tag":353,"props":1220,"children":1221},{"style":400},[1222],{"type":60,"value":428},{"type":55,"tag":353,"props":1224,"children":1225},{"style":514},[1226],{"type":60,"value":1227}," 4",{"type":55,"tag":353,"props":1229,"children":1230},{"style":400},[1231],{"type":60,"value":522},{"type":55,"tag":353,"props":1233,"children":1235},{"class":355,"line":1234},8,[1236,1240,1245,1249,1253,1257,1262],{"type":55,"tag":353,"props":1237,"children":1238},{"style":400},[1239],{"type":60,"value":412},{"type":55,"tag":353,"props":1241,"children":1242},{"style":415},[1243],{"type":60,"value":1244},"endpoint_version_created_at",{"type":55,"tag":353,"props":1246,"children":1247},{"style":400},[1248],{"type":60,"value":423},{"type":55,"tag":353,"props":1250,"children":1251},{"style":400},[1252],{"type":60,"value":428},{"type":55,"tag":353,"props":1254,"children":1255},{"style":400},[1256],{"type":60,"value":438},{"type":55,"tag":353,"props":1258,"children":1259},{"style":580},[1260],{"type":60,"value":1261},"2026-01-15T...",{"type":55,"tag":353,"props":1263,"children":1264},{"style":400},[1265],{"type":60,"value":588},{"type":55,"tag":353,"props":1267,"children":1269},{"class":355,"line":1268},9,[1270],{"type":55,"tag":353,"props":1271,"children":1272},{"style":400},[1273],{"type":60,"value":597},{"type":55,"tag":93,"props":1275,"children":1276},{},[1277,1294],{"type":55,"tag":97,"props":1278,"children":1279},{},[1280,1285,1287,1292],{"type":55,"tag":77,"props":1281,"children":1283},{"className":1282},[],[1284],{"type":60,"value":986},{"type":60,"value":1286}," is an array of rows; each row is an array of cell values in the order of ",{"type":55,"tag":77,"props":1288,"children":1290},{"className":1289},[],[1291],{"type":60,"value":1035},{"type":60,"value":1293},".",{"type":55,"tag":97,"props":1295,"children":1296},{},[1297,1302,1304,1310],{"type":55,"tag":77,"props":1298,"children":1300},{"className":1299},[],[1301],{"type":60,"value":1214},{"type":60,"value":1303}," tells the client which version actually ran — useful for logging and for\npinning to a known version with ",{"type":55,"tag":77,"props":1305,"children":1307},{"className":1306},[],[1308],{"type":60,"value":1309},"?version=N",{"type":60,"value":1293},{"type":55,"tag":63,"props":1312,"children":1313},{},[1314,1316,1322,1323,1329,1331,1337,1339,1345],{"type":60,"value":1315},"For insight endpoints, the response shape depends on the query kind (",{"type":55,"tag":77,"props":1317,"children":1319},{"className":1318},[],[1320],{"type":60,"value":1321},"TrendsQuery",{"type":60,"value":522},{"type":55,"tag":77,"props":1324,"children":1326},{"className":1325},[],[1327],{"type":60,"value":1328},"LifecycleQuery",{"type":60,"value":1330},", ",{"type":55,"tag":77,"props":1332,"children":1334},{"className":1333},[],[1335],{"type":60,"value":1336},"RetentionQuery",{"type":60,"value":1338},") — the OpenAPI spec captures the right shape for the current\nversion. Insight kinds that can't be materialised (e.g. ",{"type":55,"tag":77,"props":1340,"children":1342},{"className":1341},[],[1343],{"type":60,"value":1344},"FunnelsQuery",{"type":60,"value":1346},") still return their inline\nresult shape.",{"type":55,"tag":86,"props":1348,"children":1350},{"id":1349},"calling-from-the-posthog-cli",[1351],{"type":60,"value":1352},"Calling from the PostHog CLI",{"type":55,"tag":63,"props":1354,"children":1355},{},[1356,1358,1364],{"type":60,"value":1357},"For local testing, scripts, or CI, the repo's ",{"type":55,"tag":77,"props":1359,"children":1361},{"className":1360},[],[1362],{"type":60,"value":1363},"posthog-cli",{"type":60,"value":1365}," calls endpoints without hand-rolling\nHTTP:",{"type":55,"tag":93,"props":1367,"children":1368},{},[1369,1380],{"type":55,"tag":97,"props":1370,"children":1371},{},[1372,1378],{"type":55,"tag":77,"props":1373,"children":1375},{"className":1374},[],[1376],{"type":60,"value":1377},"posthog-cli exp endpoints run",{"type":60,"value":1379}," — execute an endpoint (from a local YAML definition)",{"type":55,"tag":97,"props":1381,"children":1382},{},[1383,1389],{"type":55,"tag":77,"props":1384,"children":1386},{"className":1385},[],[1387],{"type":60,"value":1388},"posthog-cli exp endpoints {list,get,pull,push,diff}",{"type":60,"value":1390}," — inspect endpoints, or manage them as YAML\nfiles in version control (GitOps-style)",{"type":55,"tag":63,"props":1392,"children":1393},{},[1394,1396,1402,1404,1410,1412,1418,1420,1426,1428,1434],{"type":60,"value":1395},"Auth uses the same personal API key, via ",{"type":55,"tag":77,"props":1397,"children":1399},{"className":1398},[],[1400],{"type":60,"value":1401},"posthog-cli login",{"type":60,"value":1403}," or the ",{"type":55,"tag":77,"props":1405,"children":1407},{"className":1406},[],[1408],{"type":60,"value":1409},"POSTHOG_CLI_API_KEY",{"type":60,"value":1411}," \u002F\n",{"type":55,"tag":77,"props":1413,"children":1415},{"className":1414},[],[1416],{"type":60,"value":1417},"POSTHOG_CLI_PROJECT_ID",{"type":60,"value":1419}," \u002F ",{"type":55,"tag":77,"props":1421,"children":1423},{"className":1422},[],[1424],{"type":60,"value":1425},"POSTHOG_CLI_HOST",{"type":60,"value":1427}," env vars. (These live under ",{"type":55,"tag":77,"props":1429,"children":1431},{"className":1430},[],[1432],{"type":60,"value":1433},"exp",{"type":60,"value":1435}," — experimental, may\nchange.)",{"type":55,"tag":86,"props":1437,"children":1439},{"id":1438},"error-responses-to-handle",[1440],{"type":60,"value":1441},"Error responses to handle",{"type":55,"tag":156,"props":1443,"children":1444},{},[1445,1466],{"type":55,"tag":160,"props":1446,"children":1447},{},[1448],{"type":55,"tag":164,"props":1449,"children":1450},{},[1451,1456,1461],{"type":55,"tag":168,"props":1452,"children":1453},{},[1454],{"type":60,"value":1455},"Status",{"type":55,"tag":168,"props":1457,"children":1458},{},[1459],{"type":60,"value":1460},"When",{"type":55,"tag":168,"props":1462,"children":1463},{},[1464],{"type":60,"value":1465},"Handling",{"type":55,"tag":179,"props":1467,"children":1468},{},[1469,1487,1505,1530,1554,1572],{"type":55,"tag":164,"props":1470,"children":1471},{},[1472,1477,1482],{"type":55,"tag":186,"props":1473,"children":1474},{},[1475],{"type":60,"value":1476},"400",{"type":55,"tag":186,"props":1478,"children":1479},{},[1480],{"type":60,"value":1481},"Missing required variable on a materialised endpoint, or invalid variable type",{"type":55,"tag":186,"props":1483,"children":1484},{},[1485],{"type":60,"value":1486},"Surface the error message; fix the call",{"type":55,"tag":164,"props":1488,"children":1489},{},[1490,1495,1500],{"type":55,"tag":186,"props":1491,"children":1492},{},[1493],{"type":60,"value":1494},"401",{"type":55,"tag":186,"props":1496,"children":1497},{},[1498],{"type":60,"value":1499},"Missing \u002F wrong personal API key",{"type":55,"tag":186,"props":1501,"children":1502},{},[1503],{"type":60,"value":1504},"Check the Authorization header",{"type":55,"tag":164,"props":1506,"children":1507},{},[1508,1513,1525],{"type":55,"tag":186,"props":1509,"children":1510},{},[1511],{"type":60,"value":1512},"403",{"type":55,"tag":186,"props":1514,"children":1515},{},[1516,1518,1523],{"type":60,"value":1517},"Key lacks ",{"type":55,"tag":77,"props":1519,"children":1521},{"className":1520},[],[1522],{"type":60,"value":372},{"type":60,"value":1524}," scope, or endpoint is in another project",{"type":55,"tag":186,"props":1526,"children":1527},{},[1528],{"type":60,"value":1529},"Adjust key scopes",{"type":55,"tag":164,"props":1531,"children":1532},{},[1533,1538,1543],{"type":55,"tag":186,"props":1534,"children":1535},{},[1536],{"type":60,"value":1537},"404",{"type":55,"tag":186,"props":1539,"children":1540},{},[1541],{"type":60,"value":1542},"Endpoint name typo, or endpoint not active",{"type":55,"tag":186,"props":1544,"children":1545},{},[1546,1548],{"type":60,"value":1547},"Confirm name; check ",{"type":55,"tag":77,"props":1549,"children":1551},{"className":1550},[],[1552],{"type":60,"value":1553},"is_active",{"type":55,"tag":164,"props":1555,"children":1556},{},[1557,1562,1567],{"type":55,"tag":186,"props":1558,"children":1559},{},[1560],{"type":60,"value":1561},"429",{"type":55,"tag":186,"props":1563,"children":1564},{},[1565],{"type":60,"value":1566},"Rate limited — limits are per team, not per endpoint (see note below)",{"type":55,"tag":186,"props":1568,"children":1569},{},[1570],{"type":60,"value":1571},"Exponential backoff; cache responses client-side if possible",{"type":55,"tag":164,"props":1573,"children":1574},{},[1575,1580,1585],{"type":55,"tag":186,"props":1576,"children":1577},{},[1578],{"type":60,"value":1579},"5xx",{"type":55,"tag":186,"props":1581,"children":1582},{},[1583],{"type":60,"value":1584},"Query execution failure (ClickHouse error, timeout, etc.)",{"type":55,"tag":186,"props":1586,"children":1587},{},[1588,1590],{"type":60,"value":1589},"Retry with backoff. If persistent, hand off to ",{"type":55,"tag":77,"props":1591,"children":1593},{"className":1592},[],[1594],{"type":60,"value":1595},"diagnosing-endpoint-performance",{"type":55,"tag":86,"props":1597,"children":1599},{"id":1598},"workflow",[1600],{"type":60,"value":1601},"Workflow",{"type":55,"tag":1603,"props":1604,"children":1605},"ol",{},[1606,1634,1644,1649,1661,1666,1678],{"type":55,"tag":97,"props":1607,"children":1608},{},[1609,1611,1617,1619,1625,1627,1632],{"type":60,"value":1610},"Confirm endpoint name. If unknown, list them with ",{"type":55,"tag":77,"props":1612,"children":1614},{"className":1613},[],[1615],{"type":60,"value":1616},"execute-sql",{"type":60,"value":1618}," on\n",{"type":55,"tag":77,"props":1620,"children":1622},{"className":1621},[],[1623],{"type":60,"value":1624},"system.data_modeling_endpoints",{"type":60,"value":1626}," (or ",{"type":55,"tag":77,"props":1628,"children":1630},{"className":1629},[],[1631],{"type":60,"value":290},{"type":60,"value":1633},").",{"type":55,"tag":97,"props":1635,"children":1636},{},[1637,1642],{"type":55,"tag":77,"props":1638,"children":1640},{"className":1639},[],[1641],{"type":60,"value":194},{"type":60,"value":1643}," to see the full shape: variables, materialisation status, query kind.",{"type":55,"tag":97,"props":1645,"children":1646},{},[1647],{"type":60,"value":1648},"Decide the auth posture: personal API key on a server, never client-side.",{"type":55,"tag":97,"props":1650,"children":1651},{},[1652,1654,1659],{"type":60,"value":1653},"If the user wants generated types, call ",{"type":55,"tag":77,"props":1655,"children":1657},{"className":1656},[],[1658],{"type":60,"value":211},{"type":60,"value":1660},", hand them the spec, and\nrecommend a generator for their language.",{"type":55,"tag":97,"props":1662,"children":1663},{},[1664],{"type":60,"value":1665},"Build a sample request payload from the variable declarations and walk through a test call.",{"type":55,"tag":97,"props":1667,"children":1668},{},[1669,1671,1676],{"type":60,"value":1670},"Optionally call ",{"type":55,"tag":77,"props":1672,"children":1674},{"className":1673},[],[1675],{"type":60,"value":228},{"type":60,"value":1677}," from this skill to confirm the payload works.",{"type":55,"tag":97,"props":1679,"children":1680},{},[1681,1683,1688],{"type":60,"value":1682},"Wrap up with handling notes: the materialised-variables rule, the rate-limit shape, and\npinning to a version with ",{"type":55,"tag":77,"props":1684,"children":1686},{"className":1685},[],[1687],{"type":60,"value":1309},{"type":60,"value":1293},{"type":55,"tag":86,"props":1690,"children":1692},{"id":1691},"example-interaction",[1693],{"type":60,"value":1694},"Example interaction",{"type":55,"tag":241,"props":1696,"children":1699},{"className":1697,"code":1698,"language":60,"meta":246},[244],"User: \"I want to call monthly_active_users from my Node.js backend.\n       Can you help me wire it up with types?\"\n\nAgent steps:\n- endpoint-get monthly_active_users → HogQL, variables: lookback_days\n  (int, default 30), org_id (string, no default), is_materialized: true\n- \"Two things to know upfront:\n   1. This endpoint is materialised, so both lookback_days and org_id\n      must be passed on every call. Calls without them will be rejected.\n   2. You'll need a personal API key with endpoint:read scope. Set it\n      as PH_API_KEY in your server env — never ship it in client code.\"\n\n- endpoint-openapi-spec monthly_active_users → returns spec\n\n- \"Here's the spec. Drop it in your repo and run:\n     pnpm dlx @hey-api\u002Fopenapi-ts -i spec.json -o .\u002Fgenerated\u002Fposthog\n   That gives you typed client functions.\n\n   A minimum call looks like:\n     POST \u002Fapi\u002Fprojects\u002F12345\u002Fendpoints\u002Fmonthly_active_users\u002Frun\n     Authorization: Bearer \u003CPH_API_KEY>\n     Content-Type: application\u002Fjson\n\n     { 'variables': { 'org_id': 'acme', 'lookback_days': 30 } }\n\n   The response includes columns and rows — your client will pick that\n   up from the generated types.\n\n   Want me to do a sample call to verify the payload works?\"\n",[1700],{"type":55,"tag":77,"props":1701,"children":1702},{"__ignoreMap":246},[1703],{"type":60,"value":1698},{"type":55,"tag":86,"props":1705,"children":1707},{"id":1706},"important-notes",[1708],{"type":60,"value":1709},"Important notes",{"type":55,"tag":93,"props":1711,"children":1712},{},[1713,1723,1733,1743,1760,1778,1788,1809],{"type":55,"tag":97,"props":1714,"children":1715},{},[1716,1721],{"type":55,"tag":69,"props":1717,"children":1718},{},[1719],{"type":60,"value":1720},"Personal API keys are server-side only.",{"type":60,"value":1722}," Never ship them in mobile apps or browser JS.",{"type":55,"tag":97,"props":1724,"children":1725},{},[1726,1731],{"type":55,"tag":69,"props":1727,"children":1728},{},[1729],{"type":60,"value":1730},"Re-generate the client when the query changes.",{"type":60,"value":1732}," Each new endpoint version may add or\nremove variables — keep types in sync by re-fetching the spec.",{"type":55,"tag":97,"props":1734,"children":1735},{},[1736,1741],{"type":55,"tag":69,"props":1737,"children":1738},{},[1739],{"type":60,"value":1740},"Materialised endpoints reject calls missing variables.",{"type":60,"value":1742}," This is intentional. If the user\nreports a 400 after materialisation was enabled, the fix is in the call, not in the endpoint.",{"type":55,"tag":97,"props":1744,"children":1745},{},[1746,1751,1753,1758],{"type":55,"tag":69,"props":1747,"children":1748},{},[1749],{"type":60,"value":1750},"Pin to a version — don't rely on \"latest\".",{"type":60,"value":1752}," Always call with ",{"type":55,"tag":77,"props":1754,"children":1756},{"className":1755},[],[1757],{"type":60,"value":1309},{"type":60,"value":1759},". Without it the\nlatest active version runs, so a future query edit (which cuts a new version) can silently change\na caller's results. Bump the pinned version deliberately once you've validated the new one.",{"type":55,"tag":97,"props":1761,"children":1762},{},[1763,1768,1770,1776],{"type":55,"tag":69,"props":1764,"children":1765},{},[1766],{"type":60,"value":1767},"Caching on the client side is fair game.",{"type":60,"value":1769}," The endpoint already caches via\n",{"type":55,"tag":77,"props":1771,"children":1773},{"className":1772},[],[1774],{"type":60,"value":1775},"data_freshness_seconds",{"type":60,"value":1777},", but the client can layer another cache on top for hot paths. Be\nmindful of total staleness (endpoint cache + client cache).",{"type":55,"tag":97,"props":1779,"children":1780},{},[1781,1786],{"type":55,"tag":69,"props":1782,"children":1783},{},[1784],{"type":60,"value":1785},"Rate limits are per team, by category — not per endpoint.",{"type":60,"value":1787}," Calls to non-materialised\nendpoints share the team-wide API-query budget (~240\u002Fmin burst, ~2400\u002Fhour sustained) with all\nother query traffic; materialised endpoints draw on a separate, higher shared bucket\n(~1200\u002Fmin, ~12000\u002Fhour). There is no per-endpoint-name limit, so hammering one endpoint can\nstarve others on the same team. Heavy callers should batch where possible and back off on 429.",{"type":55,"tag":97,"props":1789,"children":1790},{},[1791,1796,1798,1807],{"type":55,"tag":69,"props":1792,"children":1793},{},[1794],{"type":60,"value":1795},"Pricing.",{"type":60,"value":1797}," Calling endpoints isn't billed today, but it will be once endpoints ship alongside\nthe ",{"type":55,"tag":1799,"props":1800,"children":1804},"a",{"href":1801,"rel":1802},"https:\u002F\u002Fposthog.com\u002Fdata-stack\u002Fmanaged-warehouse",[1803],"nofollow",[1805],{"type":60,"value":1806},"managed warehouse",{"type":60,"value":1808},". Flag this to the user\nif they're planning high-volume usage so the future cost isn't a surprise.",{"type":55,"tag":97,"props":1810,"children":1811},{},[1812,1817,1819,1824],{"type":55,"tag":69,"props":1813,"children":1814},{},[1815],{"type":60,"value":1816},"Tell PostHog what's missing.",{"type":60,"value":1818}," If an error, a limit, or a missing capability gets in the way,\nuse the ",{"type":55,"tag":77,"props":1820,"children":1822},{"className":1821},[],[1823],{"type":60,"value":791},{"type":60,"value":1825}," tool — it's the main signal the team uses to improve endpoints and these\ntools.",{"type":55,"tag":1827,"props":1828,"children":1829},"style",{},[1830],{"type":60,"value":1831},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":1833,"total":1935},[1834,1850,1862,1874,1887,1902,1918],{"slug":1835,"name":1835,"fn":1836,"description":1837,"org":1838,"tags":1839,"stars":23,"repoUrl":24,"updatedAt":1849},"analyzing-expensive-users","analyze expensive users in AI observability","Analyze the most expensive users in AI observability and explain why they cost so much. Use when the user asks about top spenders, expensive users, per-user LLM cost, user-level cost drivers, or patterns behind high AI observability spend.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1840,1842,1845,1848],{"name":1841,"slug":31,"type":13},"Analytics",{"name":1843,"slug":1844,"type":13},"Cost Optimization","cost-optimization",{"name":1846,"slug":1847,"type":13},"Observability","observability",{"name":9,"slug":8,"type":13},"2026-07-28T05:34:11.117757",{"slug":1851,"name":1851,"fn":1852,"description":1853,"org":1854,"tags":1855,"stars":23,"repoUrl":24,"updatedAt":1861},"auditing-endpoints","audit PostHog project endpoints","Audit every endpoint in a PostHog project for staleness, failed materialisations, and unused materialised versions. Use when the user asks \"what endpoints can I clean up?\", \"are any of my endpoints broken?\", \"which materialised versions are still being called?\", or wants a one-shot cleanup pass over the Endpoints product. Produces a prioritised report grouped by issue type, with recommended actions but does not modify anything without explicit confirmation.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1856,1857,1860],{"name":1841,"slug":31,"type":13},{"name":1858,"slug":1859,"type":13},"Audit","audit",{"name":9,"slug":8,"type":13},"2026-06-08T08:08:33.693989",{"slug":1863,"name":1863,"fn":1864,"description":1865,"org":1866,"tags":1867,"stars":23,"repoUrl":24,"updatedAt":1873},"auditing-warehouse-source-health","audit PostHog data warehouse source health","Audit the health of a PostHog project's data warehouse sources and syncs — find every broken or degraded source connection, sync schema, and webhook channel. Use when the user asks \"why are my imports failing?\", \"what's broken with my sources?\", \"why is my warehouse data stale?\", or wants a one-shot triage of source\u002Fsync health before deciding where to dig in. Produces a prioritized report grouped by severity, with recommended next steps. For materialized-view health use `auditing-warehouse-view-health`; for a single failing sync use `diagnosing-failed-warehouse-syncs`.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1868,1869,1871,1872],{"name":1858,"slug":1859,"type":13},{"name":1870,"slug":33,"type":13},"Data Warehouse",{"name":1846,"slug":1847,"type":13},{"name":9,"slug":8,"type":13},"2026-06-18T08:22:57.67984",{"slug":1875,"name":1875,"fn":1876,"description":1877,"org":1878,"tags":1879,"stars":23,"repoUrl":24,"updatedAt":1886},"auditing-warehouse-view-health","audit PostHog materialized view health","Audit the health of a PostHog project's materialized views (saved queries) — find every failed materialization and flag unused or stale materialized views that cost storage and compute. Use when the user asks \"which of my views are broken?\", \"why is this materialized view failing?\", \"are any of my views wasting compute?\", or wants a one-shot triage of view health. For source\u002Fsync health use `auditing-warehouse-source-health`.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1880,1881,1882,1885],{"name":1858,"slug":1859,"type":13},{"name":1870,"slug":33,"type":13},{"name":1883,"slug":1884,"type":13},"Performance","performance",{"name":9,"slug":8,"type":13},"2026-06-18T08:25:10.936787",{"slug":1888,"name":1888,"fn":1889,"description":1890,"org":1891,"tags":1892,"stars":23,"repoUrl":24,"updatedAt":1901},"authoring-error-tracking-alerts","author PostHog error tracking alerts","Author error tracking alerts that fire when an issue is created, reopened, or starts spiking. Use when the user asks to set up error notifications, route exceptions to Slack\u002Fwebhook\u002FLinear, or evaluate which error events are worth alerting on. Covers trigger-event selection, integration choice, dedup against existing alerts, and shipping with the canonical message body shape.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1893,1896,1899,1900],{"name":1894,"slug":1895,"type":13},"Alerting","alerting",{"name":1897,"slug":1898,"type":13},"Debugging","debugging",{"name":1846,"slug":1847,"type":13},{"name":9,"slug":8,"type":13},"2026-06-18T08:24:40.318583",{"slug":1903,"name":1903,"fn":1904,"description":1905,"org":1906,"tags":1907,"stars":23,"repoUrl":24,"updatedAt":1917},"authoring-log-alerts","author log alerts in PostHog","Author useful, low-noise log alerts on services in a PostHog project. Use when the user asks to set up alerts for their logs, suggest alerts they should add, or evaluate whether a service is worth monitoring. Covers service triage, baseline characterisation, threshold drafting, back-testing via simulate, and shipping with a notification destination.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1908,1909,1912,1913,1916],{"name":1841,"slug":31,"type":13},{"name":1910,"slug":1911,"type":13},"Monitoring","monitoring",{"name":1846,"slug":1847,"type":13},{"name":1914,"slug":1915,"type":13},"Operations","operations",{"name":9,"slug":8,"type":13},"2026-07-18T05:10:54.430898",{"slug":1919,"name":1919,"fn":1920,"description":1921,"org":1922,"tags":1923,"stars":23,"repoUrl":24,"updatedAt":1934},"building-workflows","build and edit PostHog workflows","Build, edit, test, enable, and monitor PostHog workflows over MCP. Author the action\u002Fedge graph so it runs and opens cleanly in the visual editor, then change drafts surgically with patch operations. Use when asked to build, set up, automate, change, fix, or debug a workflow, campaign, broadcast, drip sequence, or event-triggered automation in the workflows product.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1924,1927,1930,1931],{"name":1925,"slug":1926,"type":13},"Automation","automation",{"name":1928,"slug":1929,"type":13},"MCP","mcp",{"name":9,"slug":8,"type":13},{"name":1932,"slug":1933,"type":13},"Workflow Automation","workflow-automation","2026-07-28T05:34:12.167015",61,{"items":1937,"total":2043},[1938,1945,1951,1958,1965,1972,1980,1987,1999,2006,2016,2034],{"slug":1835,"name":1835,"fn":1836,"description":1837,"org":1939,"tags":1940,"stars":23,"repoUrl":24,"updatedAt":1849},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1941,1942,1943,1944],{"name":1841,"slug":31,"type":13},{"name":1843,"slug":1844,"type":13},{"name":1846,"slug":1847,"type":13},{"name":9,"slug":8,"type":13},{"slug":1851,"name":1851,"fn":1852,"description":1853,"org":1946,"tags":1947,"stars":23,"repoUrl":24,"updatedAt":1861},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1948,1949,1950],{"name":1841,"slug":31,"type":13},{"name":1858,"slug":1859,"type":13},{"name":9,"slug":8,"type":13},{"slug":1863,"name":1863,"fn":1864,"description":1865,"org":1952,"tags":1953,"stars":23,"repoUrl":24,"updatedAt":1873},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1954,1955,1956,1957],{"name":1858,"slug":1859,"type":13},{"name":1870,"slug":33,"type":13},{"name":1846,"slug":1847,"type":13},{"name":9,"slug":8,"type":13},{"slug":1875,"name":1875,"fn":1876,"description":1877,"org":1959,"tags":1960,"stars":23,"repoUrl":24,"updatedAt":1886},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1961,1962,1963,1964],{"name":1858,"slug":1859,"type":13},{"name":1870,"slug":33,"type":13},{"name":1883,"slug":1884,"type":13},{"name":9,"slug":8,"type":13},{"slug":1888,"name":1888,"fn":1889,"description":1890,"org":1966,"tags":1967,"stars":23,"repoUrl":24,"updatedAt":1901},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1968,1969,1970,1971],{"name":1894,"slug":1895,"type":13},{"name":1897,"slug":1898,"type":13},{"name":1846,"slug":1847,"type":13},{"name":9,"slug":8,"type":13},{"slug":1903,"name":1903,"fn":1904,"description":1905,"org":1973,"tags":1974,"stars":23,"repoUrl":24,"updatedAt":1917},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1975,1976,1977,1978,1979],{"name":1841,"slug":31,"type":13},{"name":1910,"slug":1911,"type":13},{"name":1846,"slug":1847,"type":13},{"name":1914,"slug":1915,"type":13},{"name":9,"slug":8,"type":13},{"slug":1919,"name":1919,"fn":1920,"description":1921,"org":1981,"tags":1982,"stars":23,"repoUrl":24,"updatedAt":1934},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1983,1984,1985,1986],{"name":1925,"slug":1926,"type":13},{"name":1928,"slug":1929,"type":13},{"name":9,"slug":8,"type":13},{"name":1932,"slug":1933,"type":13},{"slug":1988,"name":1988,"fn":1989,"description":1990,"org":1991,"tags":1992,"stars":23,"repoUrl":24,"updatedAt":1998},"check-posthog-loading","inspect PostHog SDK loading across URLs","Inspect how the PostHog JavaScript SDK is loaded across a list of URLs. Use to confirm consistent installation across pages, find pages missing the snippet, detect mismatched API keys or hosts between pages, and verify the load method (head snippet vs deferred vs array.js).\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1993,1994,1995,1996,1997],{"name":1841,"slug":31,"type":13},{"name":1897,"slug":1898,"type":13},{"name":21,"slug":22,"type":13},{"name":1846,"slug":1847,"type":13},{"name":9,"slug":8,"type":13},"2026-05-07T05:56:19.828048",{"slug":4,"name":4,"fn":5,"description":6,"org":2000,"tags":2001,"stars":23,"repoUrl":24,"updatedAt":25},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2002,2003,2004,2005],{"name":15,"slug":16,"type":13},{"name":21,"slug":22,"type":13},{"name":9,"slug":8,"type":13},{"name":18,"slug":19,"type":13},{"slug":2007,"name":2007,"fn":2008,"description":2009,"org":2010,"tags":2011,"stars":23,"repoUrl":24,"updatedAt":2015},"copying-endpoints-across-projects","copy PostHog endpoints across projects","Copy a PostHog endpoint (a saved HogQL\u002Finsight query exposed as an API route) to another project in the same organization, or duplicate it under a new name in the same project. Use when the user wants to duplicate an endpoint, promote an endpoint from staging to production, replicate an endpoint's query\u002Fvariables\u002Ffreshness config in another workspace, or clone an endpoint to iterate on it. Unlike feature flags and experiments, endpoints have NO native cross-project copy tool — this skill covers the read-then-recreate flow (endpoint-get then endpoint-create), the active-project switching it requires, name-collision checks, and the safe defaults (land unmaterialised in the target, verify with endpoint-run). Does not cover editing endpoint versions (see managing-endpoint-versions) or authoring a brand-new endpoint from scratch (see creating-an-endpoint).\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2012,2013,2014],{"name":15,"slug":16,"type":13},{"name":1914,"slug":1915,"type":13},{"name":9,"slug":8,"type":13},"2026-07-15T05:29:58.442727",{"slug":2017,"name":2017,"fn":2018,"description":2019,"org":2020,"tags":2021,"stars":23,"repoUrl":24,"updatedAt":2033},"creating-ai-subscription","schedule recurring AI-generated PostHog reports","Create a recurring AI-generated PostHog report — schedule a free-text prompt to run on a cron, with the LLM-synthesized markdown delivered to email or Slack on each tick. Use when the user wants a recurring AI summary of X on any cadence (daily, weekly, monthly, yearly) rather than a one-off report. (To attach an AI summary to an existing insight\u002Fdashboard subscription instead of a free-text prompt, see `managing-subscriptions` and its `summary_enabled` option.)\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2022,2023,2026,2027,2030],{"name":1925,"slug":1926,"type":13},{"name":2024,"slug":2025,"type":13},"Email","email",{"name":9,"slug":8,"type":13},{"name":2028,"slug":2029,"type":13},"Reporting","reporting",{"name":2031,"slug":2032,"type":13},"Slack","slack","2026-06-09T07:32:27.935712",{"slug":82,"name":82,"fn":2035,"description":2036,"org":2037,"tags":2038,"stars":23,"repoUrl":24,"updatedAt":2042},"create PostHog API endpoints","Create a PostHog endpoint with the right shape on the first try — covers query kind choice, name conventions, what to expose as variables (HogQL code_name vs insight breakdown), data_freshness_seconds, and whether to materialise on day one. Use when the user says \"create an endpoint\", \"expose this query as an API\", \"turn this insight into an endpoint\", or asks for help structuring a new endpoint. Steers away from common mistakes: materialising a query with cohort breakdowns or compare mode, inline-only variables on a materialised endpoint, unbounded date ranges, ambiguous names.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[2039,2040,2041],{"name":1841,"slug":31,"type":13},{"name":15,"slug":16,"type":13},{"name":9,"slug":8,"type":13},"2026-06-08T08:08:29.624498",231]