setting-up-a-custom-rest-source

Par posthog · skills

Connectez une API REST quelconque à l'entrepôt de données PostHog en tant que source personnalisée en rédigeant un manifeste JSON, sans code spécifique à chaque source. À utiliser lorsque l'utilisateur pointe vers une API sans connecteur PostHog natif — « importer des données depuis cette API REST », « synchroniser mon API interne », « connecter cette API depuis sa documentation », « créer une source personnalisée pour l'entrepôt de données » — et fournit une URL de documentation ou une description en langage naturel des endpoints. Guide la rédaction du manifeste `RESTAPIConfig` (auth — bearer, clé API, HTTP basic, ou OAuth2 client credentials / refresh token — pagination, chemin d'accès aux enregistrements, curseur incrémental, fan-out parent/enfant), sa validation, la lecture test de lignes réelles pour vérifier les mappings de champs, et la création de la source. Si l'API dispose déjà d'un connecteur PostHog natif, utiliser `setting-up-a-data-warehouse-source` à la place — cette skill vérifie d'abord le registre des connecteurs et ne traite que les API sans connecteur natif.

npx skills add https://github.com/posthog/skills --skill setting-up-a-custom-rest-source

Configuration d'une source REST personnalisée

Une source personnalisée importe n'importe quel API HTTP REST dans des tables d'entrepôt interrogeables à partir d'un manifeste JSON — pas de Python par source. Le manifeste est une RESTAPIConfig : la même structure que celle qui alimente les connecteurs REST intégrés de PostHog (Intercom, Attio, Sentry, …), donc le moteur REST générique gère l'authentification, la pagination, l'extraction de records JSONPath et les curseurs incrémentiels pour vous. Votre travail consiste à rédiger un manifeste correct et à le valider contre des données en direct avant de créer la source.

Il s'agit d'une capacité en alpha. Limites : au maximum 50 ressources par manifeste, et au maximum 5 sources personnalisées par projet.

Quand utiliser cette skill

  • L'utilisateur souhaite importer une API qui n'a pas de connecteur intégré — un service interne, une SaaS de niche, une API publique — et peut vous donner son URL de documentation ou décrire ses endpoints.
  • L'utilisateur demande explicitement une « source REST personnalisée », un « manifeste de source personnalisée » ou de « construire un connecteur à partir de la documentation ».

Une source personnalisée est le repli — uniquement correct quand aucun connecteur natif ne convient. PostHog propose des centaines de connecteurs natifs, bien plus qu'il ne serait possible de les lister ici, donc ne supposez jamais qu'une API n'a pas de connecteur intégré — la plupart des applications SaaS et bases de données bien connues en ont un, et une mauvaise hypothèse les redirige dans un manifeste rédigé à la main qui duplique un connecteur éprouvé. L'étape 0 ci-dessous vous fait vérifier le registre avant de rédiger quoi que ce soit ; si un connecteur natif correspond, transmettez à setting-up-a-data-warehouse-source à la place.

La grammaire

Lisez references/manifest-reference.md avant de rédiger — c'est la référence complète des champs RESTAPIConfig (types d'auth, les six paginateurs, curseurs incrémentiels, fan-out parent/enfant) avec des exemples travaillés pour chacun. Rédigez le manifeste à partir de cette grammaire ; ne devinez pas les noms de champs.

Le squelette :

{
  "client": {
    "base_url": "https://api.example.com/v1",
    "auth": { "type": "bearer" }
  },
  "resources": [
    {
      "name": "users",
      "primary_key": "id",
      "endpoint": {
        "path": "/users",
        "data_selector": "data",
        "paginator": { "type": "json_response", "next_url_path": "next" },
        "incremental": { "cursor_path": "updated_at", "start_param": "since" }
      }
    }
  ]
}

Les secrets ne vont jamais en ligne dans le manifeste. manifest_json ne contient que la structure non-secrète. La credential voyage dans une clé de payload séparée choisie par le client.auth.type du manifeste : auth_token (bearer), auth_api_key (api_key), auth_password (http_basic), ou auth_oauth2_client_secret pour oauth2 (plus auth_oauth2_refresh_token pour la subvention refresh-token uniquement). Le moteur l'injecte au runtime, et PostHog le masque de chaque réponse. Mettre un token en ligne est rejeté à la validation.

Outils disponibles

Outil Objectif
external-data-sources-wizard Lister tous les types de source natifs que PostHog supporte. Exécutez ceci en premier (Étape 0) pour vérifier si l'API cible a déjà un connecteur intégré avant de rédiger un manifeste.
external-data-sources-db-schema Valider le manifeste + credential et lister les ressources (tables) qu'il expose, avec les clés primaires détectées et les curseurs incrémentiels. C'est l'étape valider-et-lister.
external-data-sources-preview-resource Lire un petit exemple en direct de lignes pour une ressource — vérifier data_selector / primary_key / cursor_path contre les données réelles avant de créer quoi que ce soit.
data-warehouse-source-setup Créer la source. Active toutes les ressources de manifeste avec les defaults de sync en un seul appel.
external-data-sources-create Création avancée — permet à l'utilisateur de sélectionner manuellement quelles ressources synchroniser via un tableau schemas.
external-data-schemas-list Après création, regarder le statut de sync par table.

Workflow

Étape 0 — Vérifier d'abord s'il existe un connecteur natif

Avant de rédiger quoi que ce soit, appelez external-data-sources-wizard pour lister les types de source natifs et vérifier si l'API cible en fait partie, en correspondant le nom du service. Une source personnalisée est le repli pour les API sans aucun connecteur natif ; ne sautez pas cette vérification en supposant qu'une API bien connue n'est pas supportée — la plupart le sont.

Si un connecteur natif correspond, arrêtez et dites à l'utilisateur que la voie intégrée est plus simple et éprouvée (elle gère l'auth, la pagination, le schéma et la sync incrémentelle pour vous), et transmettez à setting-up-a-data-warehouse-source. Ne continuez avec cette skill que quand l'utilisateur n'a pas de connecteur natif correspondant, ou veut explicitement emprunter la voie REST personnalisée malgré l'existence d'un.

Étape 1 — Rassembler la forme de l'API

Obtenez soit une URL de documentation (extrayez-la et lisez le schéma d'auth, les endpoints de liste, leurs enveloppes de réponse et toute pagination) soit une description en langage naturel des endpoints. Vous avez besoin, par ressource que vous importerez :

  • du chemin (relatif à une base_url commune) et de la méthode (GET, ou POST pour les endpoints de lecture de style query),
  • du schéma d'auth (bearer token / clé API en header ou query / HTTP basic / OAuth2 avec un client détenu par le client — client_credentials ou un refresh token pré-obtenu ; le flux interactif authorization_code n'est pas supporté),
  • du chemin de record — où se trouve le tableau de records dans la réponse JSON (par ex. data, results, items),
  • de la façon dont l'API pagine (URL suivante, link header, cursor, offset, numéro de page, ou page unique),
  • d'un champ clé primaire, et
  • optionnellement d'un champ curseur incrémental (style updated_at) pour que les re-syncs ne récupèrent que les lignes nouvelles/modifiées.

Demandez à l'utilisateur la valeur de la credential, mais dites-lui que vous ne la placerez jamais dans le manifeste, seulement dans la clé de payload auth_*.

Étape 2 — Rédiger le manifeste

Rédigez la RESTAPIConfig à partir de references/manifest-reference.md. Faites correspondre le bloc auth au schéma, choisissez le paginateur qui correspond à la documentation, définissez data_selector au chemin de record, et ajoutez un bloc incremental quand l'API a un curseur style updated_at et un paramètre query correspondant. Pour un endpoint dont les lignes doivent être récupérées par parent (par ex. /forms/{form_id}/responses), utilisez un paramètre resolve parent/enfant — voir l'exemple fan-out. Limitez-vous à un niveau d'imbrication.

Étape 3 — Valider et lister les ressources

Appelez external-data-sources-db-schema avec { source_type: "Custom", manifest_json: "<stringified manifest>", auth_token: "<credential>" }. La clé de credential *n'est pas littéralement `auth_** — utilisez celle pour votre type d'auth :auth_token(bearer),auth_api_key(api_key),auth_password(http_basic), ouauth_oauth2_client_secret(+auth_oauth2_refresh_tokenpour la subvention refresh-token). Il valide la structure du manifeste, le graphe fan-out et la credential (une sonde en direct bornée), puis retourne une entrée de table par ressource avecdetected_primary_keysetincremental_fields. S'il retourne un 400, lemessageest en anglais clair (par ex.resources[0].endpoint.path: must not be empty`) — corrigez le manifeste et réessayez. Bouclez ici jusqu'à ce que ça valide.

Étape 4 — Test-lire chaque ressource

Pour chaque ressource, appelez external-data-sources-preview-resource avec { source_type: "Custom", payload: { manifest_json, auth_token }, resource_name: "<name>", limit: 10 } (la clé auth_token varie selon le type d'auth, comme à l'étape 3). Il retourne jusqu'à limit lignes réelles plus les columns déduits. Vérifiez que :

  • data_selector est correct — rows sont les records que vous attendez, pas un objet enveloppe. Si rows ressemble à [{ "data": [...] }] vous avez pointé sur l'enveloppe, pas le tableau ; corrigez data_selector.
  • primary_key existe dans les lignes et est unique.
  • le champ cursor_path incrémental est présent dans les lignes et ressemble à un timestamp/id triable.

Un échec en direct (hôte inaccessible, auth rejeté) revient comme error avec rows vide — corrigez les credentials ou l'URL et réessayez. Itérez les étapes 2–4 jusqu'à ce que l'échantillon ressemble bien.

Étape 5 — Créer la source

Appelez data-warehouse-source-setup avec { source_type: "Custom", payload: { manifest_json, auth_token }, prefix: "<short_name>" } (la clé auth_token varie selon le type d'auth, comme à l'étape 3). Il active chaque ressource du manifeste avec des defaults de sync sensés (incrémental où le manifeste déclare un curseur, sinon refresh complet) et crée la source. Si l'utilisateur ne veut qu'un sous-ensemble de ressources, utilisez external-data-sources-create avec un tableau schemas à la place (voir setting-up-a-data-warehouse-source pour la forme schemas). Choisissez un prefix court en minuscules — les tables deviennent {prefix}_{resource_name} en HogQL.

Après création, appelez external-data-schemas-list pour montrer à l'utilisateur le statut de sync initial, et dites-lui comment interroger : SELECT * FROM {prefix}_{resource_name} LIMIT 10.

Notes importantes

  • Toujours prévisualiser avant de créer. db-schema prouve que le manifeste s'analyse et que la credential fonctionne ; preview prouve les mappages de champs (data_selector / primary_key / cursor_path) contre les lignes réelles. Sauter preview est le moyen le plus courant de créer une source qui synchronise zéro ou des lignes malformées.
  • *Secrets seulement dans `auth_.** Ne mettez jamais un token/clé/mot de passe en ligne dansmanifest_json` — c'est rejeté, et le manifeste est non-secret (il fait un aller-retour vers le client).
  • Un seul niveau de fan-out. Une ressource enfant peut dépendre d'un parent au niveau supérieur ; un parent ne peut pas lui-même être un enfant.
  • GET et POST uniquement. Le moteur lit les données en amont ; PUT/PATCH/DELETE sont rejetés pour qu'un manifeste ne puisse pas muter l'API source.
  • Choisir le curseur avec soin. Préférez un champ style updated_at à created_at (il attrape les éditions), et définissez cursor_type quand le curseur n'est pas un datetime (par ex. un id entier) pour qu'il soit comparé avec le bon type.
  • Les secrets OAuth2 sont adoptés dans un magasin de credential géré par le serveur au premier appel db-schema / preview / create, et tout refresh token à usage unique pivoté est persisté côté serveur — donc gardez l'intégralité du bloc client.auth identique à travers ces appels dans une seule configuration, et re-soumettez les mêmes secrets chaque fois. Changer n'importe quel champ du bloc auth en cours de configuration jette la rotation stockée, et les fournisseurs qui pivotent les refresh tokens à usage unique rejetteront alors la prochaine menthe jusqu'à ce que l'utilisateur récupère un token frais. Ne définissez jamais auth_oauth2_integration_id vous-même (c'est détenu par le serveur) ; pour reconnecter une source dont le token a échoué, mettez-la à jour avec auth_oauth2_client_secret / auth_oauth2_refresh_token re-entrés. Voir la section OAuth2 de la référence manifeste pour les champs du bloc auth.

Skills similaires