CommunityRédaction et éditiongithub.com

bojan-basrak/rankscale-api-skill

Compétence d'agent non officielle et indépendante du fournisseur pour interroger l'API REST de visibilité de marque Rankscale AI — fonctionne avec Claude Code, Cursor, Codex et d'autres outils agentiques.

Qu'est-ce que rankscale-api-skill ?

Cette compétence d'agent permet aux professionnels du référencement (SEO) et aux développeurs d'interroger directement l'API REST de visibilité de marque de Rankscale depuis leurs outils agentiques (Claude Code, Cursor, Codex, etc.), sans passer par le tableau de bord. Elle donne accès à des métriques clés comme la visibilité, le sentiment, les citations, la position moyenne et le taux de détection pour une marque et ses concurrents, sur différentes périodes et moteurs d'IA (ChatGPT, Gemini, Claude, Perplexity, etc.). L'agent doit être configuré avec une clé API via la variable d'environnement `RANKSCALE_API_KEY` et peut utiliser `curl` et des outils de parsing JSON (Node.js, jq, Python) pour récupérer et analyser les données. La compétence fournit des recettes de workflow pour identifier une marque, extraire des métriques sur une fenêtre temporelle, analyser les citations et le sentiment, et gérer efficacement les gros volumes de données en écrivant les réponses directement sur disque pour économiser des tokens. Elle inclut également des avertissements sur les particularités de l'API (traps camelCase, champs ignorés, limites de pagination et interprétation correcte des métriques comme `brandNotFound` ou les rangs).

Compatible avec✓Claude Code✓Codex CLI✓Cursor✓Antigravity✓Gemini CLI
npx skills add bojan-basrak/rankscale-api-skill

Installed? Explore more Rédaction et édition skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

API REST Rankscale

Rankscale est un outil de suivi de visibilité de marque par IA. Il interroge divers modèles d'IA (ChatGPT, Gemini, Claude, Perplexity, etc.) avec les termes de recherche suivis par l'utilisateur, analyse les réponses et rapporte à quelle fréquence, où et avec quelle favorabilité les marques suivies sont mentionnées.

Cette compétence appelle directement l'API REST afin que l'utilisateur (un professionnel du référencement, pas un développeur) puisse extraire des données pour des rapports, des graphiques et des analyses personnalisées sans cliquer sur le tableau de bord.

Configuration

  • Clé API : Lue depuis la variable d'environnement RANKSCALE_API_KEY. Le format de la clé est rk_<hash>_<workspaceId> — le suffixe est un identifiant d'espace de travail, pas un ID de marque, donc une seule clé atteint chaque marque dans son espace de travail (particularités §15). Si elle n'est pas définie, demandez à l'utilisateur de la définir une fois : PowerShell setx RANKSCALE_API_KEY "rk_..." (un nouveau shell est nécessaire pour prendre effet) ou passez-la par session avec $env:RANKSCALE_API_KEY = "rk_...". Ne jamais afficher la clé dans les réponses ni l'écrire dans des fichiers.
  • URL de base : https://rankscale.ai (note : pas de préfixe /api — le chemin est /v1/... directement sur le domaine marketing).
  • En-tête d'authentification : Authorization: Bearer $RANKSCALE_API_KEY.
  • Limite de débit : 200 requêtes par minute par clé API. La réponse contient X-RateLimit-Limit, X-RateLimit-Remaining et X-RateLimit-Reset (secondes jusqu'à la réinitialisation de la fenêtre) — lisez-les avec curl -i si vous effectuez un traitement par lots. Mettez en cache les réponses des rapports pendant 5 à 10 minutes lorsque cela est possible.
  • Outils disponibles : curl pour les requêtes. Pour l'analyse JSON, utilisez ce que l'environnement fournit — node -e "...", jq, ou python -m json.tool. Vérifiez ce qui se trouve dans le PATH avant de supposer ; ne dépendez pas exclusivement d'un seul d'entre eux.
  • Syntaxe du shell : les exemples ci-dessous utilisent l'expansion de variables de style bash ($RANKSCALE_API_KEY). Sur Windows PowerShell, cela devient $env:RANKSCALE_API_KEY. Choisissez le shell que vous appelez — les deux fonctionnent, mais faites attention à la syntaxe.

Modèle d'appel

Chaque point de terminaison renvoie {success: true, data: {...}} en cas de succès, ou {success: false, error: {code, message, details}} en cas d'échec. Vérifiez toujours .success avant de lire .data.

Vérifiez aussi warnings. Une réponse réussie peut comporter une troisième clé de niveau supérieur, warnings[], listant les champs de requête que l'API n'a pas reconnus et ignorés — souvent avec une suggestion ("Champ non reconnu 'startDate' ignoré. Vouliez-vous dire 'isoStartDate' ? …"). Il est absent lorsque la requête est propre, donc if (json.warnings) est un garde-fou fiable. Un avertissement signifie que les chiffres répondent à une question différente de celle posée — l'API revient aux valeurs par défaut pour le champ ignoré. Signalez-le à l'utilisateur au lieu de l'ignorer ; c'est le moyen le moins coûteux de détecter le piège du camelCase (particularités §1).

Enregistrez les réponses JSON brutes dans un fichier à côté du travail de l'utilisateur (typiquement Rankscale/<endpoint>_<contexte>.json) afin qu'elles puissent être ré-analysées sans rappeler l'API. Présentez à l'utilisateur un résumé propre, pas le JSON brut, sauf s'il le demande.

Efficacité des tokens — le levier le plus important. Pour tout ce qui est volumineux (multi-sujet, multi-moteur, historique complet, ou /search-terms-report avec includeAnswerTexts), écrivez la réponse directement sur le disque avec -o et extrayez uniquement les valeurs dont vous avez besoin avec node -e. Ne lisez pas les charges utiles /report entières dans le contexte — un rapport filtré fait environ 40–50 Ko et un balayage de 7 sujets fait ~300 Ko. L'extraction de scalaires/séries côté client maintient cela hors contexte et, pour les extractions en masse, réduit approximativement de moitié l'utilisation des tokens par rapport à la lecture des charges utiles en ligne. (Pour une seule mesure étroite, la surcharge n'en vaut pas la peine — lisez simplement la petite réponse.)

Les tailles de charge utile sont très inégales — planifiez en fonction. Mesurée sur une seule marque :

Point de terminaisonFenêtreTaille
/report (filtré)30j~40–50 Ko
/report (filtré)1 mois calendaire~105–110 Ko
/citations3m~3.9 Mo
/citations uncapped: true1 mois calendaire~4.4–5.7 Mo
/sentiment30j~9 Mo
/sentiment3m~17 Mo

La taille n'évolue pas avec la longueur de la fenêtre — uncapped: true importe bien plus. Un seul mois sans limite est revenu plus gros qu'une extraction plafonnée de trois mois, donc n'extrapolez pas une taille d'un mois à partir de la ligne 3m.

/sentiment et /citations ne sont jamais sûrs à lire en ligne — utilisez toujours -o vers un fichier et extrayez. Pour des appels aussi lourds, capturez aussi le statut HTTP (curl -w '%{http_code}'), car un 502 transitoire arrive sous forme de corps HTML qui ressemble à un chemin cassé mais nécessite juste une nouvelle tentative (particularités §6).

# Bash (Git Bash / WSL / macOS / Linux)
curl -s -H "Authorization: Bearer $RANKSCALE_API_KEY" \
     "https://rankscale.ai/v1/metrics/brands" \
     -o brands.json

curl -s -X POST -H "Authorization: Bearer $RANKSCALE_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"brandId":"<id>"}' \
     "https://rankscale.ai/v1/metrics/report" \
     -o report.json
# Équivalent PowerShell
curl.exe -s -H "Authorization: Bearer $env:RANKSCALE_API_KEY" `
     "https://rankscale.ai/v1/metrics/brands" `
     -o brands.json

curl.exe -s -X POST -H "Authorization: Bearer $env:RANKSCALE_API_KEY" `
     -H "Content-Type: application/json" `
     -d '{\"brandId\":\"<id>\"}' `
     "https://rankscale.ai/v1/metrics/report" `
     -o report.json

Notez dans PowerShell : utilisez curl.exe (l'alias curl pointe vers Invoke-WebRequest, qui se comporte différemment), échappez les guillemets intérieurs dans les corps JSON -d avec \", et utilisez l'accent grave ` pour la continuation de ligne. Invoke-RestMethod fonctionne aussi et analyse JSON automatiquement, mais la forme curl maintient les réponses cohérentes entre les shells.

L'inventaire complet des points de terminaison et les formes de requêtes se trouvent dans references/endpoints.md. Lisez-le avant tout appel dont vous n'êtes pas sûr. Les surprises et les pièges sont dans references/quirks.md — lisez-le avant de rapporter des métriques à l'utilisateur, car plusieurs d'entre eux affectent la façon dont les chiffres doivent être interprétés.

Hors de portée : l'API des liens de partage. Rankscale publie une deuxième API REST pour les liens de partage de tableaux de bord publics. Elle utilise une clé différente (Paramètres → Partage, pas Paramètres → Intégrations), donc RANKSCALE_API_KEY ne s'authentifiera pas auprès d'elle. Si l'utilisateur demande à créer ou révoquer un lien de partage, dites qu'il s'agit d'une API séparée que cette compétence ne couvre pas — ne devinez pas ses chemins.

Recettes de workflow

1. Identifier la marque

La plupart des points de terminaison de rapport ont besoin d'un brandId. Lorsque l'utilisateur nomme une marque ("affiche-moi les métriques d'Acme"), résolvez d'abord l'ID :

  1. Si Rankscale/brands.json existe dans le répertoire de travail de l'utilisateur, lisez-le.
  2. Sinon, appelez GET /v1/metrics/brands et enregistrez le résultat.
  3. Faites correspondre le nom de la marque de l'utilisateur avec brands[].name (insensible à la casse) et avec brands[].brandInfo.names (alias). Si plusieurs correspondances, demandez à l'utilisateur de lever l'ambiguïté.

2. Extraire les métriques pour une marque sur une fenêtre

L'utilisateur demande presque toujours une fenêtre de temps. Utilisez timeFrame (camelCase, F majuscule — l'API ignore silencieusement toute autre orthographe) avec l'un de ces préréglages documentés : 24h, 7d, 30d, 3m, 1y. Associez-le à aggregation (hourly, daily, weekly, ou monthly) pour la taille du compartiment. Pour les fenêtres personnalisées, utilisez isoStartDate + isoEndDate (chaînes de date ISO appariées) ; celles-ci remplacent timeFrame.

{
  "brandId": "<id>",
  "timeFrame": "30d",
  "aggregation": "daily",
  "includeNotFoundExecutions": true
}

Filtres de rapport optionnels (tous acceptent une seule chaîne, un tableau pour OU-dans-le-champ, ou "all" pour aucun filtre ; les filtres se combinent avec ET entre les champs) :

  • selectedTopic — ID de sujet, nom de sujet, _orphaned, ou tableau
  • selectedTags — tag, __UNTAGGED__, ou tableau
  • selectedEngine — ID de moteur (préféré — voir references/endpoints.md pour le catalogue) ou nom convivial
  • selectedQuery — chaîne de requête de terme de recherche exacte ou tableau
  • searchTermId — ID de terme de recherche unique
  • periodOffset — entier, décale la fenêtre prédéfinie de N périodes en arrière (0 = actuelle, 1 = précédente, …)
  • userTimezone — fuseau horaire IANA comme Europe/Paris pour les limites de jour locales de l'utilisateur
  • includeNotFoundExecutions — booléen, contrôle si les exécutions "marque non trouvée dans la réponse" comptent dans les métriques (voir quirks.md)

Lisez la réponse à partir de data.ownBrandMetrics.historicalData.<aggregation> (par ex. .daily lorsque vous avez demandé aggregation: "daily"). Chaque tableau de compartiments — visibilityScore, sentiment, mentions, sources, citations, citationCounts, avgPosition, detectionRate, top3, brandNotFound — s'exécute en parallèle avec timestamps.

Trois séries temporelles parallèles l'accompagnent :

  • data.ownBrandMetrics.topicMetricsData.<aggregation> — par sujet
  • data.ownBrandMetrics.engineMetricsData.<aggregation> — par moteur ; non documenté en amont, et généralement la coupe la plus précieuse lorsqu'une fenêtre d'agrégat semble plate, car les mouvements au niveau du moteur s'annulent dans le total (particularités §25)
  • data.competitorTimeSeriesData.<aggregation> — par concurrent, marque propre exclue (particularités §16)

brandNotFound[] est un non-signal — il indique true pour pratiquement toute marque avec une détection inférieure à 100 %. Utilisez detectionRate à la place et ne signalez jamais "marque non trouvée" à partir de l'indicateur (particularités §2).

Présentez un tableau de métriques avec ces colonnes : Date, Visibilité, Sentiment, Mentions, Citations, Position moyenne, % de détection, % Top-3. Au-dessus, affichez le résumé instantané (valeurs instantanées actuelles de ownBrandMetrics + le delta trends).

Classement de la marque (par visibilité) — vs. concurrents. Calculez-le à partir de data.competitorMetrics[] (qui inclut la marque propre, signalée isOwnBrand: true) : rang = 1 + (nombre d'entrées avec un visibilityScore strictement supérieur) — les égalités ne font pas descendre la marque. Cela reproduit le rang du tableau de bord. La réponse contient également latestRank/avgRank par entrée — ce ne sont pas des rangs. Vérifié le 2026-08-07 : ils renvoient des valeurs non entières (latestRank: 2.7, avgRank: 2.9) pour une marque dont le rang calculé était 1, donc ils suivent quelque chose de similaire à une position, pas un ordinal. Ignorez-les. Le own_brand_rank équivalent du MCP est également toujours 1 (une épingle d'affichage). La méthode de calcul par tri de visibilité ci-dessus est celle qui correspondait au tableau de bord lors des tests. Les filtres partagés (selectedEngine, selectedTopic, selectedTags, selectedQuery) fonctionnent par coupe, vous pouvez donc classer au sein d'un seul moteur, sujet, tag ou requête en réexécutant avec filtre. Notez que les entrées competitorMetrics peuvent avoir un validMetricsCount différent de celui de la marque propre (les lignes de base des concurrents utilisent une fenêtre plus large) — le classement correspond toujours à l'interface utilisateur. Recette complète — y compris le rang quotidien dans le temps et ses mises en garde — dans la recette §6 ci-dessous.

3. Analyse des citations

/v1/metrics/citations renvoie les sources (sites, articles) que les modèles d'IA citent en répondant aux termes de recherche de l'utilisateur. Utile pour comprendre quels domaines tiers influencent les réponses IA concernant une marque.

Champs clés : data.totalCitations, data.uniqueCitations (URL distinctes), data.uniqueDomains et data.citationsByDomain[] (chaque domaine). Dans chaque entrée de domaine, occurrences est le nombre ; le champ citations est le tableau d'URL, pas un nombre — donc la part de citation = occurrences / totalCitations, et les URL principales proviennent de l'aplatissement du tableau d'URL de chaque domaine et du tri par occurrences.

Chaque objet URL est {url, normalizedUrl, occurrences, engineAppearances: {<engineId>: count}, firstSeenAt, lastSeenAt, category, searchTerms[]}. engineAppearances est la seule répartition des citations par moteur dans l'API — additionnez-la sur les URL d'un domaine pour répondre à "quels moteurs citent notre site". firstSeenAt/lastSeenAt sont le seul écho de la fenêtre que vous avez réellement obtenue. Normalisez davantage normalizedUrl avant l'analyse au niveau de la page (elle laisse les variantes www./barre oblique finale/requête distinctes), et notez que category: "owned" signifie "le site propre d'une entreprise", pas détenu par la marque suivie — les concurrents l'ont aussi. Voir particularités.md §13b. data.domainSummary a des vues pré-découpées (topDomainsOverall, topDomainsByEngine, topDomainsByQuery, topDomainsByOwnBrandCitations, topDomainsByCompetitor) — mais celles-ci sont plafonnées (≈20/10 entrées) et topDomainsByCompetitor répertorie les domaines où un concurrent a été mentionné (inclut des sites tiers neutres comme Reddit/Booking), donc ne l'utilisez pas pour identifier les sites détenus par un concurrent. Voir particularités.md §13b.

Vérifiez les plafonds avant de considérer une liste comme complète. La réponse plafonne par défaut à 5 000 URL uniques et 50 marques. data.paginationInfo indique la vérité — citationsCapped, brandsCapped, responseTrimmed, capBypassed, maxCitations, maxBrands, totalCount vs returnedCount. Passez uncapped: true (paramètre de corps ou de requête) pour lever le plafond d'URL ; il ne lève pas le plafond de 50 marques ni le garde-fou de taille de réponse. deduplicated: true déduplique les chemins de réponse et ajoute data.searchTermsById. Si un indicateur de plafond est true, dites-le à l'utilisateur et réduisez la fenêtre ou filtrez plutôt que de présenter une liste tronquée comme l'image complète. Voir particularités.md §13c.

4. Sentiment

/v1/metrics/sentiment renvoie des agrégats de sentiment au niveau de la fenêtre plus des nuages de mots-clés pour la marque suivie et chaque concurrent — pas une série temporelle (utilisez /report's historicalData.<agg>.sentiment[] pour le sentiment dans le temps). Mêmes filtres partagés, plus deduplicated: true.

Deux tableaux avec des portées différentes : data.brandSentiments[] concerne uniquement la marque suivie ; data.companySentiments[] concerne chaque marque détectée, y compris la marque propre (isOwnBrand: true) — utilisez celui-ci pour les comparaisons de concurrents. brandSentimentsBySearchTerm[] / companySentimentsBySearchTerm[] donnent les mêmes coupes par terme de recherche.

Par entrée : avgSentiment (échelle 0–100, = totalSentimentScore / sentimentCount), sentimentCount, executionCount et positiveCount / neutralCount / negativeCount. Le sentiment est divisé par source — blocs webGrounding* (moteurs ancrés sur le web) vs trainingData*, contrôlés par les booléens hasWebGrounding / hasTrainingData, avec webGroundingSentimentByEngine[<engineId>] = {sum, count, avg} pour les scores par moteur.

Deux pièges — lisez particularités.md §19 avant de rapporter quoi que ce soit. (1) `p

[… tronqué pour la traduction]

Skills associés