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_idest l'ID du projet (numérique). Disponible dans PostHog sous les paramètres du projet, ou viaposthog-get-projectssi l'utilisateur ne le connaît pas.nameest le nom de l'endpoint — voirendpoints-get-allsi l'utilisateur n'est pas sûr.- Le
/runfinal 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..."
}
resultsest un tableau de lignes ; chaque ligne est un tableau de valeurs de cellule dans l'ordre decolumns.endpoint_versiondit 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
- Confirmer le nom de l'endpoint. Si inconnu, les lister avec
execute-sqlsursystem.data_modeling_endpoints(ouendpoints-get-all). endpoint-getpour voir la forme complète : variables, statut de matérialisation, type de requête.- Décider de la posture d'authentification : clé API personnelle sur un serveur, jamais côté client.
- 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. - Construire un payload de requête exemple à partir des déclarations de variables et faire un appel de test.
- Optionnellement appeler
endpoint-rundepuis cette compétence pour confirmer que le payload fonctionne. - 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.