consuming-endpoints-from-client-code

Par posthog · skills

Connectez un endpoint PostHog à une application cliente ou un SDK. Couvre la récupération de la spec OpenAPI, la génération d'un client typé avec openapi-generator ou @hey-api/openapi-ts, l'envoi du bon header d'authentification, la mise en forme du payload variables (propriété HogQL `code_name` vs breakdown d'insight), la gestion des réponses d'erreur liées au rate limit et aux endpoints matérialisés. À utiliser quand l'utilisateur dit « comment appeler mon endpoint », « génère un client pour ça » ou « quel header d'auth dois-je utiliser ».

npx skills add https://github.com/posthog/skills --skill consuming-endpoints-from-client-code

Consommer des endpoints depuis du code client

Cette compétence est l'homologue appelant de creating-an-endpoint. Elle aide à intégrer un endpoint existant dans une base de code distincte — une application mobile, un backend serveur, un tableau de bord client ou un pipeline en aval. Aucun code PostHog n'est modifié ici.

Quand utiliser cette compétence

  • « Comment appeler mon endpoint ? » / « À quoi ressemble une requête ? »
  • « Générer un client TypeScript / Python / Go typé pour cet endpoint »
  • « J'obtiens une 401 en appelant l'endpoint » / questions d'authentification
  • « L'endpoint rejette mon appel quand j'omets user_id » → questions de variables d'endpoint matérialisé
  • « Comment gérer les limites de débit ? »

Si l'utilisateur crée l'endpoint, utilisez d'abord creating-an-endpoint.

Outils disponibles

Outil Objectif
endpoint-get Configuration complète d'un endpoint nommé, incluant la forme de la requête et les variables requises
endpoint-openapi-spec Spec OpenAPI 3.0 pour un endpoint, prête à alimenter un générateur de code
endpoint-run Un appel en direct contre l'endpoint — utile pour confirmer qu'une payload fonctionne avant de la partager à l'appli

L'URL de l'endpoint

/api/projects/{team_id}/endpoints/{name}/run
  • team_id est l'ID du projet (numérique). Disponible dans PostHog sous les paramètres du projet, ou via posthog-get-projects si l'utilisateur ne le connaît pas.
  • name est le nom de l'endpoint — voir endpoints-get-all si l'utilisateur n'est pas sûr.
  • Le /run final est obligatoire.

POST est la méthode canonique. GET fonctionne aussi pour les cas simples sans corps de requête, mais POST est préféré — les variables vont dans le corps.

Authentification

Les endpoints sont authentifiés avec une clé API personnelle. L'en-tête est :

Authorization: Bearer <key>

Les clés sont scopées — pour les endpoints, la clé a besoin au minimum de endpoint:read. Si l'utilisateur obtient une 403, il manque généralement le scope ; si c'est une 401, la clé est manquante ou mal formée.

Ne mettez jamais une clé API personnelle dans du code côté client livré aux utilisateurs finaux (applications mobiles, JS navigateur). Les clés API personnelles accordent un accès scopé au compte. Pour les applications client-facing, routez à travers le backend propre de l'utilisateur, qui détient la clé.

Le payload de la requête

{
  "variables": { "code_name_1": value, "code_name_2": value },
  "limit": 100,
  "offset": 0,
  "refresh": "cache"
}
Champ Notes
variables Clés par code_name pour les endpoints HogQL ; pour les endpoints insight avec breakdowns, la clé est le nom de la propriété de breakdown
limit Nombre maximum de lignes retournées.
offset Sauter des lignes. Endpoints HogQL seulement.
refresh "cache" (retourner les résultats en cache s'ils sont assez frais), "force" (toujours recalculer), "direct" (contourner la matérialisation, endpoints matérialisés seulement). Par défaut "cache"

Appelez endpoint-get pour voir la forme exacte des variables. La réponse inclut la définition de la requête avec les variables déclarées — le code_name de chaque variable est ce que le client doit envoyer.

Endpoints matérialisés : toutes les variables sont requises

Si endpoint-get montre is_materialized: true sur la version courante, l'endpoint requiert que chaque variable déclarée soit passée à chaque appel. C'est une limite de sécurité — sans filtres, un seul appel retournerait l'ensemble du dataset pré-agrégé.

Symptôme courant : l'app de l'utilisateur a fonctionné quand l'endpoint n'était pas matérialisé, puis a commencé à retourner des erreurs 400 après que la matérialisation a été activée. Le message d'erreur liste les variables manquantes.

Les variables optionnelles/partielles sur les endpoints matérialisés sont une limitation connue que l'équipe PostHog prévoit de lever. Si exiger chaque variable bloque le cas d'usage de l'utilisateur, envoyez une note via l'outil agent-feedback — ce signal de demande est comment l'équipe le priorise.

Générer un client typé

L'endpoint expose sa propre spec OpenAPI 3.0 via endpoint-openapi-spec. Alimentez-la dans un générateur de code :

Langage Outil Forme de la commande
TypeScript @hey-api/openapi-ts openapi-ts -i spec.json -o ./generated
TypeScript openapi-generator-cli openapi-generator-cli generate -i spec.json -g typescript-fetch -o ./generated
Python openapi-generator-cli openapi-generator-cli generate -i spec.json -g python -o ./generated
Go oapi-codegen oapi-codegen -package=client spec.json > client.go

Le client généré donne à l'utilisateur les types pour le payload de variables et la forme de la réponse. Régénérez quand la requête de l'endpoint change (chaque nouvelle version peut avoir des variables différentes).

Si l'utilisateur a plusieurs endpoints, générez une spec par endpoint et soit combinez-les, soit générez un client par endpoint et utilisez-les côte à côte.

Forme de la réponse

Une réponse réussie typique :

{
  "results": [[...], [...]],
  "columns": ["col_a", "col_b"],
  "types": ["Int64", "String"],
  "hasMore": false,
  "name": "endpoint_name",
  "endpoint_version": 4,
  "endpoint_version_created_at": "2026-01-15T..."
}
  • results est un tableau de lignes ; chaque ligne est un tableau de valeurs de cellule dans l'ordre de columns.
  • endpoint_version dit au client quelle version a réellement tourné — utile pour la journalisation et pour épingler à une version connue avec ?version=N.

Pour les endpoints insight, la forme de la réponse dépend du type de requête (TrendsQuery, LifecycleQuery, RetentionQuery) — la spec OpenAPI capture la bonne forme pour la version courante. Les types insight qui ne peuvent pas être matérialisés (ex. FunnelsQuery) retournent toujours leur forme de résultat inline.

Appeler depuis la CLI PostHog

Pour les tests locaux, scripts ou CI, le posthog-cli du repo appelle les endpoints sans créer HTTP à la main :

  • posthog-cli exp endpoints run — exécuter un endpoint (depuis une définition YAML locale)
  • posthog-cli exp endpoints {list,get,pull,push,diff} — inspecter les endpoints ou les gérer comme fichiers YAML en contrôle de version (style GitOps)

L'authentification utilise la même clé API personnelle, via posthog-cli login ou les variables d'env POSTHOG_CLI_API_KEY / POSTHOG_CLI_PROJECT_ID / POSTHOG_CLI_HOST. (Ces commandes vivent sous exp — expérimental, peut changer.)

Réponses d'erreur à gérer

Statut Quand Gestion
400 Variable requise manquante sur un endpoint matérialisé, ou type de variable invalide Afficher le message d'erreur ; corriger l'appel
401 Clé API personnelle manquante / incorrecte Vérifier l'en-tête Authorization
403 Clé manquant le scope endpoint:read, ou endpoint dans un autre projet Ajuster les scopes de la clé
404 Typo dans le nom de l'endpoint, ou endpoint non actif Confirmer le nom ; vérifier is_active
429 Limite de débit dépassée — les limites sont par team, pas par endpoint (voir note ci-bas) Backoff exponentiel ; cacher les réponses côté client si possible
5xx Échec d'exécution de requête (erreur ClickHouse, timeout, etc.) Réessayer avec backoff. Si persistant, confier à diagnosing-endpoint-performance

Workflow

  1. Confirmer le nom de l'endpoint. Si inconnu, les lister avec execute-sql sur system.data_modeling_endpoints (ou endpoints-get-all).
  2. endpoint-get pour voir la forme complète : variables, statut de matérialisation, type de requête.
  3. Décider de la posture d'authentification : clé API personnelle sur un serveur, jamais côté client.
  4. Si l'utilisateur veut des types générés, appeler endpoint-openapi-spec, lui donner la spec et recommander un générateur pour son langage.
  5. Construire un payload de requête exemple à partir des déclarations de variables et faire un appel de test.
  6. Optionnellement appeler endpoint-run depuis cette compétence pour confirmer que le payload fonctionne.
  7. Conclure avec les notes de gestion : la règle des variables matérialisées, la forme du rate-limit, et l'épinglage à une version avec ?version=N.

Exemple d'interaction

User: "I want to call monthly_active_users from my Node.js backend.
       Can you help me wire it up with types?"

Agent steps:
- endpoint-get monthly_active_users → HogQL, variables: lookback_days
  (int, default 30), org_id (string, no default), is_materialized: true
- "Two things to know upfront:
   1. This endpoint is materialised, so both lookback_days and org_id
      must be passed on every call. Calls without them will be rejected.
   2. You'll need a personal API key with endpoint:read scope. Set it
      as PH_API_KEY in your server env — never ship it in client code."

- endpoint-openapi-spec monthly_active_users → returns spec

- "Here's the spec. Drop it in your repo and run:
     pnpm dlx @hey-api/openapi-ts -i spec.json -o ./generated/posthog
   That gives you typed client functions.

   A minimum call looks like:
     POST /api/projects/12345/endpoints/monthly_active_users/run
     Authorization: Bearer <PH_API_KEY>
     Content-Type: application/json

     { 'variables': { 'org_id': 'acme', 'lookback_days': 30 } }

   The response includes columns and rows — your client will pick that
   up from the generated types.

   Want me to do a sample call to verify the payload works?"

Notes importantes

  • Les clés API personnelles sont côté serveur seulement. Ne les livrez jamais dans les applications mobiles ou le JS navigateur.
  • Régénérez le client quand la requête change. Chaque nouvelle version d'endpoint peut ajouter ou supprimer des variables — gardez les types synchronisés en re-fetchant la spec.
  • Les endpoints matérialisés rejettent les appels manquant des variables. C'est intentionnel. Si l'utilisateur signale une 400 après que la matérialisation a été activée, la correction est dans l'appel, pas dans l'endpoint.
  • Épinglez à une version — ne vous fiez pas à "latest". Toujours appeler avec ?version=N. Sans cela, la dernière version active tourne, donc une future édition de requête (qui crée une nouvelle version) peut changer silencieusement les résultats d'un appelant. Incrémentez intentionnellement la version épinglée une fois que vous avez validé la nouvelle.
  • Le cache côté client est acceptable. L'endpoint met déjà en cache via data_freshness_seconds, mais le client peut ajouter un autre cache par-dessus pour les chemins chauds. Soyez attentif à la fraîcheur totale (cache endpoint + cache client).
  • Les limites de débit sont par team, par catégorie — pas par endpoint. Les appels aux endpoints non-matérialisés partagent le budget d'API-query team-wide (~240/min burst, ~2400/hour soutenu) avec tout autre trafic de requête ; les endpoints matérialisés tirent d'un bucket partagé séparé et plus élevé (~1200/min, ~12000/hour). Il n'y a pas de limite par-nom-endpoint, donc marteler un endpoint peut affamer les autres de la même team. Les appelants lourds doivent faire du batch où possible et reculer sur 429.
  • Tarification. Appeler les endpoints n'est pas facturé aujourd'hui, mais le sera une fois que les endpoints seront livrés aux côtés du managed warehouse. Signalez cela à l'utilisateur s'il planifie une utilisation haut-volume pour que le coût futur ne soit pas une surprise.
  • Dites à PostHog ce qui manque. Si une erreur, une limite, ou une capacité manquante se met en travers du chemin, utilisez l'outil agent-feedback — c'est le signal principal que l'équipe utilise pour améliorer les endpoints et ces outils.

Skills similaires