Zest Public API (1.0.0)

Download OpenAPI specification:Download

Zest — équipe technique: dev@zestmeup.com License: LicenseRef-Zest-Proprietary

Lecture des résultats agrégés Survey et engagomètre pour les outils BI.

API publique en lecture seule des résultats Listen d'une corporation : campagnes Survey et engagomètre (EM), itérations, catalogue de questions, filtres, détails, diagnostic et résultat d'une question. Elle est destinée aux outils de BI : sept opérations GET, des résultats agrégés, aucune donnée individuelle.

Parcours BI

  1. Obtenir une clé auprès d'un super admin de la corporation (écran API Keys, voir Authentification).
  2. GET /v1/surveys → campagnes lancées de la corporation.
  3. GET /v1/surveys/{surveyId}/iterations → itérations et snapshots.
  4. GET .../questions → identifiants et ordre des questions ; GET .../filters → valeurs utilisables dans filters (voir Filtres).
  5. GET .../results → résultats par question, paginés (voir Pagination et curseurs) ; GET .../diagnostic → diagnostic d'une population ; GET .../questions/{questionId}/results → une question.

Exemple, avec la clé dans une variable d'environnement (jamais dans l'URL) :

curl -H "Authorization: Bearer $ZEST_API_KEY" \
  "https://<hôte>/v1/surveys?limit=10"

Authentification

Authorization: Bearer <clé> sur chaque appel. Ne placez jamais la clé dans une URL (chemin ou query) : les URL sont journalisées par les proxys et les navigateurs.

  • Format : zpk_v1_…. La clé est un secret ; elle n'est affichée qu'à sa création.
  • Création : par un super admin de la corporation, dans l'écran API Keys.
  • Portée : lecture (survey:read) des résultats Survey et EM d'une seule corporation, celle de la clé. Aucune écriture, aucune autre corporation.
  • Expiration : 1 an au plus après la création. Une clé expirée est refusée (401 token_expired) ; une clé inconnue ou mal formée l'est aussi (401 token_invalid, token_missing sans en-tête).
  • Rotation : avant l'expiration, un super admin renouvelle la clé dans l'écran API Keys. Le renouvellement crée une nouvelle clé de même nom ; l'ancienne reste valide jusqu'à sa révocation. Basculez le client, puis révoquez l'ancienne.
  • Révocation : un super admin révoque une clé depuis le même écran ; elle est refusée dès la requête suivante (401 token_revoked).
  • Adresses IP autorisées (facultatif) : un super admin peut restreindre une clé à une liste d'adresses IP ou de plages CIDR (par exemple 203.0.113.7 ou 203.0.113.0/24), dans l'écran API Keys ; sans liste, la clé s'utilise depuis n'importe quelle adresse. Une requête qui vient d'une autre adresse est refusée (403 ip_not_allowed) avant tout calcul et ne compte dans aucun quota. L'adresse prise en compte est celle que voit Zest en entrée de la plateforme : pour un outil BI hébergé, c'est l'adresse de sortie (publique) de son hébergeur, qui doit être stable.

Filtres

Les routes de résultats acceptent un paramètre filters : un objet JSON encodé en URL. Absent, il désigne l'ensemble de la corporation.

  • {"type": "overall"} (défaut) : une cohorte pour toute la corporation.
  • {"type": "custom", "segments": [...]} : une cohorte (segment) par sélection de segments. Le diagnostic n'accepte qu'un seul segment.
  • restrictions : sélections appliquées à toutes les cohortes.
  • Dimensions : department, location, team, smart_group, role, attribute et question. Les identifiants et valeurs utilisables proviennent de listResultFilters, pour la même itération et la même vue (viewMode dynamic ou static avec snapshotId). Un identifiant inconnu est refusé (400 invalid_filters).
  • Budgets : au plus 10 sélections, 100 valeurs de filtre au total, 5 cohortes (segments ; le benchmark éventuel s'y ajoute) et 6 Kio pour filters une fois encodé. Une combinaison hors budget est refusée (400 filter_budget_exceeded), jamais tronquée.

Pagination et curseurs

Listes : limit (défaut 50, maximum 100 ; 50 pour les résultats) et cursor renvoyé dans meta.nextCursor (null en fin de liste). Tri stable par identifiant croissant ; aucune garantie d'instantané entre deux pages d'une liste. Résultats : seule la collection questions est paginée ; participation et scores globaux sont calculés sur le périmètre complet et répétés sur chaque page.

Le curseur est opaque : ne le décodez pas, ne le fabriquez pas, ne le stockez pas au-delà de la lecture en cours. Il est lié à la corporation, à la route et à tous les paramètres de la requête. Rejouer un curseur sur une autre route, avec d'autres paramètres ou pour une autre corporation renvoie 400 invalid_cursor : modifiez un paramètre, repartez sans curseur.

Mesures et masquage

Chaque mesure est un objet {status, value}. status vaut :

  • available : valeur présente ;
  • suppressed : masquée par les règles d'anonymat de l'itération ;
  • no_data : aucune réponse ;
  • not_applicable : sans objet pour ce type de question ou cette comparaison ;
  • not_available : non calculable, par exemple benchmark indisponible.

Hors available, la valeur est toujours null. Zéro est une valeur, jamais un substitut à une absence ou à un masquage.

Seuls des agrégats sont exposés : aucune identité, aucun libellé de membre, aucune réponse individuelle ni texte libre. Une mesure dérivée (évolution, écart au benchmark) n'est calculée que si tous ses opérandes sont available, sinon suppressed. Les règles de masquage et leurs limites sont détaillées dans Anonymat.

Anonymat

L'API applique exactement la règle de la plateforme web : les chiffres de l'API sont identiques à ceux affichés à l'écran, sans écart à expliquer. Elle ne protège ni plus ni moins que le web.

Seuil. Chaque campagne a un seuil d'anonymat (anonymousThreshold de listSurveys), celui configuré pour la campagne, 3 par défaut. Il est le même pour toutes les itérations de la campagne.

Quand une cohorte est masquée. Pour chaque question et chaque cohorte, on additionne les répondants (answered) et les personnes qui ont passé la question (skipped). Si ce total est strictement inférieur au seuil, la cohorte est masquée pour cette question, à condition que la campagne soit anonyme (private) ou mixte (open) avec au moins une réponse anonyme dans la cohorte. Les campagnes nominatives (public), ou mixtes dont toutes les réponses de la cohorte sont nominatives, ne sont jamais masquées. Exemple avec un seuil de 3 : 2 répondants et 1 personne ayant passé la question font 3, la cohorte est visible ; 1 répondant et 1 personne ayant passé la question font 2, elle est masquée.

Sous le seuil.

  • Masqués (suppressed) : score, écart type, polarité et distribution, ainsi que toute mesure dérivée qui en dépend (évolution, écart au benchmark, score de thème, écarts du diagnostic).
  • Conservés : les effectifs answered, skipped et commentCount, et la participation (invited, submitted, rate). Le nombre de personnes ayant répondu reste donc visible, et révèle qu'un groupe est petit. Le rythme quotidien de participation (daily) est vide pour une cohorte masquée et pour un segment dont le nombre de soumissions est sous le seuil.
  • Exception : une cohorte définie par des réponses (condition ou restriction de type question) révèle ces réponses par ses effectifs ; lorsqu'elle est masquée, ses effectifs et sa participation le sont aussi.

Pas de masquage par modalité. La règle s'applique à la cohorte entière, jamais à une modalité de réponse : dans une cohorte visible, une modalité choisie par une seule personne apparaît dans la distribution.

Aucune protection entre cohortes. Le masquage est évalué cohorte par cohorte, dans une même requête, et ne protège pas contre le recoupement de plusieurs cohortes ou de plusieurs requêtes. En comparant deux cohortes proches, ou en soustrayant des cohortes visibles d'une cohorte plus large, on peut retrouver par différence les effectifs et les réponses d'un petit groupe masqué. Des cohortes imbriquées d'une même requête (un service avec et sans ses sous-groupes, l'ensemble de la corporation et la même population restreinte) donnent même les valeurs exactes. Zest ne l'empêche pas : les règles sont les mêmes que sur le web, où le super admin consulte ses propres données.

Responsabilité du client et bonnes pratiques. L'usage des résultats relève de la responsabilité du client, conformément à sa politique interne de confidentialité.

  • Ne croisez ni ne comparez des cohortes qui ne diffèrent que de quelques personnes (par exemple un service et le même service privé d'un sous-groupe).
  • Ne reconstituez pas, ne publiez pas et ne redistribuez pas de résultats qui permettraient d'identifier les réponses d'un petit groupe.
  • Limitez l'accès à vos tableaux de bord et aux clés API aux personnes habilitées à lire ces résultats.

Fraîcheur des données

Les résultats sont à jour à 30 secondes près : Zest peut servir une réponse depuis son cache de calcul interne de 30 secondes (les mêmes requêtes répétées dans ce délai donnent le même résultat, et les pages d'une même requête sont calculées sur le même instantané). Ce cache est interne à Zest : la réponse HTTP porte Cache-Control: no-store, et les clients et les proxys ne doivent pas la mettre en cache. La liste des destinataires d'une campagne, base des effectifs d'invités et de la participation en vue dynamique, peut avoir jusqu'à 10 minutes de retard. Les valeurs de listResultFilters (départements, sites, équipes, smart groups, rôles, attributs et questions suivies) sont mises en cache et peuvent avoir jusqu'à 5 minutes de retard (les résultats restent à 30 secondes). Le benchmark Zest est indisponible pendant le pilote (benchmark=zest : 400 invalid_parameter).

Bornes

Au plus 4 itérations comparées pour un engagomètre, 2 pour un sondage (1 pour le diagnostic), les budgets de filtres ci-dessus (5 cohortes) et filters ≤ 6 Kio une fois encodé en pourcentage, tel qu'il figure dans l'URL (au-delà : 400 filter_budget_exceeded). L'ingress refuse une ligne de requête de plus de 8 Kio par un 414 hors de l'enveloppe d'erreur ci-dessous : ces bornes l'évitent, y compris avec tous les autres paramètres à leur maximum. Les résultats paginent par 50 questions au plus. Le benchmark zest est refusé pendant le pilote (400 invalid_parameter). Une combinaison hors budget est refusée avant calcul, jamais tronquée.

Erreurs

Toute erreur a la forme {ok: false, error: {code, message}, requestId}. Les codes sont stables et la liste est extensible : traitez un code inconnu selon son statut HTTP. Le message est informatif ; citez requestId au support.

Statut Codes principaux Conduite
400 invalid_request, invalid_parameter, unknown_parameter, invalid_filters, filter_budget_exceeded, invalid_cursor, snapshot_required, snapshot_mismatch, unsupported_lang Corriger la requête, ne pas rejouer.
401 token_missing, token_invalid, token_expired, token_revoked Vérifier ou renouveler la clé.
403 insufficient_scope, module_disabled, corporation_disabled (corporation désactivée ou pas encore ouverte à l'API publique), ip_not_allowed (adresse IP hors de la liste autorisée de la clé) ip_not_allowed : appeler depuis une adresse autorisée ou faire modifier la liste par un super admin (écran API Keys). Autres codes : contacter Zest.
404 resource_not_found Identifiant inconnu ou d'une autre corporation.
405 method_not_allowed Seul GET est exposé (Allow: GET).
409 results_not_available Itération non démarrée : réessayer plus tard.
429 rate_limited Réessayer après Retry-After.
503 service_unavailable Réessayer après Retry-After s'il est présent, sinon avec backoff exponentiel.
504 computation_timeout Réduire filtres ou comparaisons, puis réessayer avec backoff.

Le code client_closed_request (408) ne figure pas au contrat : il ne sert qu'à terminer en interne une requête que le client a déjà abandonnée, et aucun client ne le reçoit.

Pour 429, 503 et 504, réessayez avec un backoff exponentiel plafonné (par exemple 1, 2, 4, 8 secondes, avec une part d'aléa) et respectez Retry-After (en secondes) lorsqu'il est présent. Ne réessayez pas une erreur 4xx autre que 409 et 429 sans changer la requête.

Quotas

Valeurs initiales, à calibrer avant la généralisation : 120 requêtes par minute pour l'ensemble des clés d'une corporation, 60 par minute pour une clé, et 20 échecs d'authentification par minute et par adresse IP. Au-delà : 429 rate_limited avec Retry-After. Ces valeurs peuvent évoluer sans changement de version ; fiez-vous à Retry-After plutôt qu'à un chiffre. Répartissez les appels (par exemple une itération à la fois) et ne parallélisez pas les calculs lourds (results, diagnostic, résultat d'une question).

Versionnement

Le chemin (/v1) ne change que pour une rupture. info.version suit le semver du contrat : patch pour une correction de description ou d'exemple, mineure pour un ajout compatible, majeure pour une rupture publiée sous une nouvelle version d'URL. Les clients ignorent les champs inconnus de réponse et les codes d'erreur inconnus. Les changements sont consignés dans contract/CHANGELOG.md du dépôt Philophrosyne.

Documentation

Cette page est publique et statique : elle ne demande aucune clé, n'en stocke aucune et ne propose pas de console d'essai. Le contrat OpenAPI est téléchargeable sans authentification (lien « Download » ci-dessus ; fichiers openapi.yaml et openapi.json à côté de cette page). Les exemples utilisent des identifiants et des clés factices.

Contact

Contact technique : dev@zestmeup.com.

Discovery

Découverte des campagnes, itérations, questions et filtres.

Lister les campagnes Survey et engagomètre

Campagnes Survey et EM lancées de la corporation (les brouillons ne sont jamais listés), des plus récentes aux plus anciennes, y compris celles sans résultat (statut et disponibilité explicites). Une liste vide renvoie 200 et un tableau vide.

Authorizations:
bearerAuth
query Parameters
type
string (SurveyType)
Enum: "survey" "engageometer"

Restreint la liste à un type de campagne.

lang
string^[a-z]{2,3}(_[A-Z]{2})?$

Langue des libellés (code produit, ex. fr, en, pt_BR). Défaut : langue de la corporation. Une langue non supportée renvoie 400 unsupported_lang. Un libellé non traduit retombe sur la langue de base de la campagne.

limit
integer [ 1 .. 100 ]
Default: 50

Taille de page des listes du catalogue.

cursor
string [ 1 .. 1024 ] characters

Curseur opaque issu de meta.nextCursor de la page précédente.

Responses

Response samples

Content type
application/json
Example
{
  • "ok": true,
  • "data": [
    ],
  • "meta": {
    }
}

Lister les itérations d'une campagne

Itérations de la campagne, de la fin la plus récente à la plus ancienne (la première est l'itération par défaut des résultats et latestIterationId de la campagne), avec dates, état, mode de confidentialité, snapshot disponible pour la vue statique et disponibilité des benchmarks. Les itérations de test ne sont jamais exposées.

Authorizations:
bearerAuth
path Parameters
surveyId
required
string (Id) ^[1-9][0-9]{0,18}$

Identifiant de campagne (Survey ou EM).

query Parameters
limit
integer [ 1 .. 100 ]
Default: 50

Taille de page des listes du catalogue.

cursor
string [ 1 .. 1024 ] characters

Curseur opaque issu de meta.nextCursor de la page précédente.

Responses

Response samples

Content type
application/json
Example
{
  • "ok": true,
  • "data": [
    ],
  • "meta": {
    }
}

Lister le catalogue de questions d'une itération

Questions de l'itération (hors sections, textes et images) dans l'ordre d'affichage, chaque matrice juste avant ses sous-questions, avec type, libellé, échelle, options et thème. Aucune réponse. position est le rang dans cet ordre, à partir de 0. templateId identifie la même question d'une itération à l'autre.

Authorizations:
bearerAuth
path Parameters
surveyId
required
string (Id) ^[1-9][0-9]{0,18}$

Identifiant de campagne (Survey ou EM).

iterationId
required
string (Id) ^[1-9][0-9]{0,18}$

Identifiant d'itération ; doit appartenir à la campagne.

query Parameters
lang
string^[a-z]{2,3}(_[A-Z]{2})?$

Langue des libellés (code produit, ex. fr, en, pt_BR). Défaut : langue de la corporation. Une langue non supportée renvoie 400 unsupported_lang. Un libellé non traduit retombe sur la langue de base de la campagne.

limit
integer [ 1 .. 100 ]
Default: 50

Taille de page des listes du catalogue.

cursor
string [ 1 .. 1024 ] characters

Curseur opaque issu de meta.nextCursor de la page précédente.

Responses

Response samples

Content type
application/json
Example
{
  • "ok": true,
  • "data": [
    ],
  • "meta": {
    }
}

Lister les valeurs de filtres applicables

Valeurs de filtres utilisables dans le paramètre filters des résultats de cette itération : départements, sites, équipes, smart groups, rôles, attributs et questions étoilées. Aucune liste de membres ni réponse individuelle. En vue dynamique, les départements, sites et équipes sont ceux de la population de l'itération (avec leurs ancêtres) et les options d'attribut celles portées par cette population. En vue statique, l'organisation, les smart groups et les attributs proviennent du snapshot demandé. Les smart groups sont tous ceux de la corporation (vue dynamique) ou du snapshot (vue statique). Les valeurs sont ordonnées par dimension dans l'ordre de FilterDimension, puis par identifiant, les rôles suivant l'ordre de RoleId. Une question filtrable est identifiée par son templateId.

Authorizations:
bearerAuth
path Parameters
surveyId
required
string (Id) ^[1-9][0-9]{0,18}$

Identifiant de campagne (Survey ou EM).

iterationId
required
string (Id) ^[1-9][0-9]{0,18}$

Identifiant d'itération ; doit appartenir à la campagne.

query Parameters
dimension
string (FilterDimension)
Enum: "department" "location" "team" "smart_group" "role" "attribute" "question"

Restreint la liste à une dimension de filtre.

viewMode
string (ViewMode)
Default: "dynamic"
Enum: "dynamic" "static"

dynamic : organisation et attributs courants. static : organisation figée au snapshot de l'itération ; snapshotId est alors obligatoire (400 snapshot_required).

snapshotId
string (SnapshotId) ^[0-9a-f]{24}$

Snapshot de l'itération de référence, obligatoire en vue statique et interdit en vue dynamique. Doit appartenir à l'itération (400 snapshot_mismatch).

lang
string^[a-z]{2,3}(_[A-Z]{2})?$

Langue des libellés (code produit, ex. fr, en, pt_BR). Défaut : langue de la corporation. Une langue non supportée renvoie 400 unsupported_lang. Un libellé non traduit retombe sur la langue de base de la campagne.

limit
integer [ 1 .. 100 ]
Default: 50

Taille de page des listes du catalogue.

cursor
string [ 1 .. 1024 ] characters

Curseur opaque issu de meta.nextCursor de la page précédente.

Responses

Response samples

Content type
application/json
Example
{
  • "ok": true,
  • "data": [
    ],
  • "meta": {
    }
}

Results

Résultats agrégés, diagnostic et résultat d'une question.

Lire les résultats agrégés par question (getDetails)

Résultats agrégés par question, cohorte et itération : scores, distributions, polarité, participation et score global (Survey) ou expérience collaborateur (EM).

Pagination. Seule la collection questions est paginée : limit compte des questions distinctes de l'itération de référence, dans l'ordre de listIterationQuestions. Participation, scores globaux, cohortes et itérations sont calculés sur le périmètre complet et répétés sur chaque page ; themes ne liste que les thèmes de la page. Les pages d'une même requête sont calculées sur le même instantané pendant 30 secondes (résultats à jour à 30 secondes près).

Une ligne par question, itération et cohorte. Chaque question de la page produit exactement une ligne par itération (référence puis comparées, dans l'ordre demandé) et par cohorte. Une question dont le templateId n'existe pas dans une itération comparée y reçoit une ligne dont toutes les mesures valent no_data (questionId et templateId de la référence). Une question qui n'existe que dans une itération comparée n'est pas listée. Le benchmark zest n'a de lignes que pour l'itération de référence.

Cohortes. Libellés neutres et non localisés : Overall, Segment N (rang dans filters.segments, à partir de 1), Benchmark overall, Benchmark Zest. Une cohorte se reconnaît à kind, segmentIndex et benchmark, jamais à son libellé.

Masquage. Une ligne sous le seuil d'anonymat de l'itération garde ses effectifs (answered, skipped, commentCount) ; score, écart type, polarité et distribution valent suppressed. Une cohorte définie par des réponses (condition ou restriction de type question) révèle ces réponses par ses effectifs : lorsqu'elle est masquée, ses effectifs le sont aussi (answered, skipped, commentCount, et en participation invited, submitted, rate). La participation d'une autre cohorte masquée garde invited, submitted et rate ; le rythme daily est vide pour une cohorte masquée, pour un benchmark et pour un segment sous le seuil d'anonymat.

Benchmark. Un benchmark demandé mais indisponible renvoie 200 avec benchmark.status à not_available et son motif, sans cohorte benchmark. Pendant le pilote, benchmark=zest est refusé (400 invalid_parameter).

Bornes. limit au plus 50 questions par page, au plus 5 cohortes et, selon le type de campagne, 4 itérations comparées (engagomètre, 5 itérations lues) ou 2 (sondage, 3 itérations lues). Une requête hors bornes est refusée avant calcul.

Erreurs. 400 invalid_filters (JSON invalide, identifiant ou valeur de filtre absent de listResultFilters), filter_budget_exceeded (bornes de filtres, dont les 5 cohortes, ou filters au-delà de 6 Kio encodés), invalid_parameter (trop d'itérations comparées, comparaison incohérente : doublon, référence répétée, listes d'itérations et de snapshots désalignées ; benchmark=zest pendant le pilote), snapshot_required, snapshot_mismatch, invalid_cursor, unsupported_lang ; 404 resource_not_found ; 409 results_not_available.

Authorizations:
bearerAuth
path Parameters
surveyId
required
string (Id) ^[1-9][0-9]{0,18}$

Identifiant de campagne (Survey ou EM).

iterationId
required
string (Id) ^[1-9][0-9]{0,18}$

Identifiant d'itération ; doit appartenir à la campagne.

query Parameters
compareIterationIds
Array of strings (Id) <= 4 items unique [ items^[1-9][0-9]{0,18}$ ]

Itérations de la même campagne à comparer à la référence, séparées par des virgules. Sans doublon ni répétition de la référence. Jamais de sélection implicite de toutes les itérations. Au plus 4 pour un engagomètre (5 itérations lues) et 2 pour un sondage (3 itérations lues) : au-delà, 400 invalid_parameter.

viewMode
string (ViewMode)
Default: "dynamic"
Enum: "dynamic" "static"

dynamic : organisation et attributs courants. static : organisation figée au snapshot de l'itération ; snapshotId est alors obligatoire (400 snapshot_required).

snapshotId
string (SnapshotId) ^[0-9a-f]{24}$

Snapshot de l'itération de référence, obligatoire en vue statique et interdit en vue dynamique. Doit appartenir à l'itération (400 snapshot_mismatch).

compareSnapshotIds
Array of strings (SnapshotId) <= 4 items unique [ items^[0-9a-f]{24}$ ]

Vue statique uniquement : snapshots des itérations comparées, dans le même ordre et en même nombre que compareIterationIds (au plus 4, 2 pour un sondage). Chaque snapshot doit appartenir à l'itération de même rang (400 snapshot_mismatch).

ResultFiltersOverall (object) or ResultFiltersCustom (object) (ResultFilters)

Objet JSON encodé en URL définissant les cohortes et restrictions. Absent : ensemble de la corporation. Les identifiants proviennent de listResultFilters pour la même itération et la même vue. Au plus 6 Kio une fois encodé.

benchmark
string (BenchmarkType)
Enum: "overall" "zest"

Benchmark optionnel, absent par défaut. overall : ensemble de la corporation. zest : référentiel Zest, engagomètre uniquement et si le module est actif ; refusé pendant le pilote (400 invalid_parameter, « Le benchmark Zest n'est pas disponible pour le moment. »). Un benchmark indisponible est signalé dans benchmark.status, jamais remplacé.

lang
string^[a-z]{2,3}(_[A-Z]{2})?$

Langue des libellés (code produit, ex. fr, en, pt_BR). Défaut : langue de la corporation. Une langue non supportée renvoie 400 unsupported_lang. Un libellé non traduit retombe sur la langue de base de la campagne.

limit
integer [ 1 .. 50 ]
Default: 50

Nombre de questions distinctes par page de résultats (au plus 50).

cursor
string [ 1 .. 1024 ] characters

Curseur opaque issu de meta.nextCursor de la page précédente.

Responses

Response samples

Content type
application/json
Example
{
  • "ok": true,
  • "data": {
    },
  • "meta": {
    }
}

Lire le diagnostic d'une itération (getDiagnostic)

Diagnostic d'une population (ensemble de la corporation ou un segment) : participation, thèmes, questions étoilées, écarts top/flop et score global (Survey) ou expérience collaborateur (EM), avec au plus une itération comparée. Réponse non paginée : sa taille est bornée par le catalogue de l'itération, dont chaque question notée figure dans son thème (sous-questions de matrice comprises, sans leur matrice).

Bornes. Une seule population : filters vaut overall (restrictions éventuelles) ou custom avec EXACTEMENT un segment (population : cohort_1, Overall ou Segment 1). Au plus une itération comparée (compareIterationIds) et, en vue statique, un snapshot comparé (compareSnapshotIds) ; limit et cursor n'existent pas (400 unknown_parameter). Le benchmark (overall ou zest) ne concerne que l'itération de référence ; il n'est jamais une cohorte de la réponse. Pendant le pilote, benchmark=zest est refusé (400 invalid_parameter).

Masquage. Une mesure dérivée (évolution, écart au benchmark) n'est calculée que si tous ses opérandes sont available : un opérande masqué la rend suppressed, jamais une différence avec un côté caché. Sans comparaison, évolution not_applicable ; benchmark non demandé, not_applicable ; benchmark demandé mais indisponible, not_available. Le score d'un thème est la moyenne de ses questions visibles, et sa completeness vaut complete (toutes visibles), partial (au moins une masquée ou sans réponse) ou suppressed (toutes masquées). L'évolution d'un thème est la moyenne des évolutions de ses questions visibles dans les deux itérations ; une question qui a changé de thème, absente de l'itération comparée ou sous-question de matrice en est exclue. theme vaut null pour les questions notées sans thème. Les écarts (gaps) ne portent que sur les questions visibles, sous-questions de matrice exclues : moyenne et écart type des scores normalisés, top (au-dessus de la moyenne) et flop (en dessous), trois au plus chacun ; l'écart type vaut no_data sous deux questions. Les effectifs de participation (invited, submitted, rate) sont conservés pour une population sous le seuil d'anonymat, sauf si elle est définie par des réponses (condition ou restriction de type question) : ils sont alors suppressed, comme rateEvolution (avec comparaison) et rateBenchmarkGap (avec benchmark). Pour l'engagomètre, les questions fixes d'engagement et d'entreprise ne sont plus étoilées (starredQuestions peut être vide) et n'entrent pas dans les écarts.

Arrondis. Scores et évolutions sur une décimale ; écarts du bloc gaps (moyenne, écart type, zScore) sur deux décimales ; points de pourcentage de participation sur une décimale.

Erreurs. 400 invalid_filters (JSON invalide, identifiant ou valeur de filtre absent de listResultFilters), filter_budget_exceeded (plus d'un segment, bornes de filtres ou filters au-delà de 6 Kio encodés), invalid_parameter (plus d'une itération comparée, doublon, référence répétée, listes d'itérations et de snapshots désalignées ; benchmark=zest pendant le pilote), snapshot_required, snapshot_mismatch, unsupported_lang ; 404 resource_not_found ; 409 results_not_available.

Authorizations:
bearerAuth
path Parameters
surveyId
required
string (Id) ^[1-9][0-9]{0,18}$

Identifiant de campagne (Survey ou EM).

iterationId
required
string (Id) ^[1-9][0-9]{0,18}$

Identifiant d'itération ; doit appartenir à la campagne.

query Parameters
compareIterationIds
Array of strings (Id) <= 1 items [ items^[1-9][0-9]{0,18}$ ]

Itération de la même campagne comparée à la référence (au plus une).

viewMode
string (ViewMode)
Default: "dynamic"
Enum: "dynamic" "static"

dynamic : organisation et attributs courants. static : organisation figée au snapshot de l'itération ; snapshotId est alors obligatoire (400 snapshot_required).

snapshotId
string (SnapshotId) ^[0-9a-f]{24}$

Snapshot de l'itération de référence, obligatoire en vue statique et interdit en vue dynamique. Doit appartenir à l'itération (400 snapshot_mismatch).

compareSnapshotIds
Array of strings (SnapshotId) <= 1 items [ items^[0-9a-f]{24}$ ]

Vue statique uniquement, snapshot de l'itération comparée.

DiagnosticFiltersOverall (object) or DiagnosticFiltersCustom (object) (DiagnosticFilters)

Objet JSON encodé en URL définissant la population du diagnostic : ensemble de la corporation ou un seul segment, avec restrictions éventuelles. Au plus 6 Kio une fois encodé.

benchmark
string (BenchmarkType)
Enum: "overall" "zest"

Benchmark optionnel, absent par défaut. overall : ensemble de la corporation. zest : référentiel Zest, engagomètre uniquement et si le module est actif ; refusé pendant le pilote (400 invalid_parameter, « Le benchmark Zest n'est pas disponible pour le moment. »). Un benchmark indisponible est signalé dans benchmark.status, jamais remplacé.

lang
string^[a-z]{2,3}(_[A-Z]{2})?$

Langue des libellés (code produit, ex. fr, en, pt_BR). Défaut : langue de la corporation. Une langue non supportée renvoie 400 unsupported_lang. Un libellé non traduit retombe sur la langue de base de la campagne.

Responses

Response samples

Content type
application/json
Example
{
  • "ok": true,
  • "data": {
    },
  • "meta": {
    }
}

Lire le résultat agrégé d'une question (getQuestion)

Une question de l'itération de référence : sa définition (question, comme dans listIterationQuestions), puis ses résultats agrégés par cohorte et par itération (results), l'évolution de son score par rapport aux itérations comparées (evolutions) et son écart au benchmark (benchmarkGaps). Aucune identité ni réponse individuelle. results reprend à l'identique les lignes de cette question dans getSurveyResults pour les mêmes paramètres : une ligne par itération et par cohorte (cohortes benchmark comprises ; le benchmark zest n'a de lignes que pour l'itération de référence), avec des mesures no_data pour une itération comparée où la question n'existe pas. Pour une matrice, la réponse porte sa propre ligne ; chacune de ses sous-questions est une requête distincte (matrixParentId).

Bornes. Réponse non paginée : au plus 6 cohortes (5 segments et le benchmark) × 5 itérations (la référence et 4 comparées ; 3 et 2 pour un sondage). Mêmes paramètres et mêmes bornes de comparaison et de filtres que getSurveyResults, sans limit ni cursor (400 unknown_parameter).

Évolutions et écarts. evolutions compte une entrée par cohorte régulière (overall ou segment, jamais le benchmark) et par itération comparée ; comparedQuestionId est la question de l'itération comparée appariée par templateId, null si elle n'en a pas (l'évolution vaut alors not_applicable). Comme dans getSurveyDiagnostic, l'évolution vaut aussi not_applicable lorsque la question a changé de thème entre les deux itérations. benchmarkGaps compte une entrée par cohorte régulière, par rapport à la cohorte benchmark de l'itération de référence ; il est vide sans benchmark. Une mesure dérivée n'est calculée que si tous ses opérandes sont available : un opérande masqué la rend suppressed, jamais une différence avec un côté caché ; sans comparaison ni benchmark il n'y a aucune entrée.

Masquage. Mêmes règles que getSurveyResults : une ligne sous le seuil d'anonymat garde ses effectifs (answered, skipped, commentCount) et masque score, écart type, polarité et distribution ; les effectifs ne sont masqués que pour une cohorte définie par des réponses (condition ou restriction de type question). Les distributions n'ont pas de masquage par option : seule la ligne est protégée par le seuil.

Échelles. Pour une question nps, score.value est sur l'échelle de scoreScale (-100 à 100) alors que les value de distribution sont sur l'échelle native des réponses (0 à 10, comme question.responseScale).

Texte. Aucun texte libre n'est jamais exposé : ni réponse, ni commentaire, ni valeur « autre ». Une question open_text n'a que ses effectifs (answered, skipped, commentCount) ; score, écart type, polarité et distribution valent no_data.

Erreurs. 400 invalid_filters (JSON invalide, identifiant ou valeur de filtre absent de listResultFilters), filter_budget_exceeded (bornes de filtres ou filters au-delà de 6 Kio encodés), invalid_parameter (trop d'itérations comparées, comparaison incohérente : doublon, référence répétée, listes d'itérations et de snapshots désalignées ; benchmark=zest pendant le pilote), snapshot_required, snapshot_mismatch, unsupported_lang ; 404 resource_not_found (campagne, itération ou snapshot inconnus, question d'une autre itération ou non exposée : section, texte, matrice sans sous-question) ; 409 results_not_available.

Authorizations:
bearerAuth
path Parameters
surveyId
required
string (Id) ^[1-9][0-9]{0,18}$

Identifiant de campagne (Survey ou EM).

iterationId
required
string (Id) ^[1-9][0-9]{0,18}$

Identifiant d'itération ; doit appartenir à la campagne.

questionId
required
string (Id) ^[1-9][0-9]{0,18}$

Identifiant de question ; doit appartenir à l'itération.

query Parameters
compareIterationIds
Array of strings (Id) <= 4 items unique [ items^[1-9][0-9]{0,18}$ ]

Itérations de la même campagne à comparer à la référence, séparées par des virgules. Sans doublon ni répétition de la référence. Jamais de sélection implicite de toutes les itérations. Au plus 4 pour un engagomètre (5 itérations lues) et 2 pour un sondage (3 itérations lues) : au-delà, 400 invalid_parameter.

viewMode
string (ViewMode)
Default: "dynamic"
Enum: "dynamic" "static"

dynamic : organisation et attributs courants. static : organisation figée au snapshot de l'itération ; snapshotId est alors obligatoire (400 snapshot_required).

snapshotId
string (SnapshotId) ^[0-9a-f]{24}$

Snapshot de l'itération de référence, obligatoire en vue statique et interdit en vue dynamique. Doit appartenir à l'itération (400 snapshot_mismatch).

compareSnapshotIds
Array of strings (SnapshotId) <= 4 items unique [ items^[0-9a-f]{24}$ ]

Vue statique uniquement : snapshots des itérations comparées, dans le même ordre et en même nombre que compareIterationIds (au plus 4, 2 pour un sondage). Chaque snapshot doit appartenir à l'itération de même rang (400 snapshot_mismatch).

ResultFiltersOverall (object) or ResultFiltersCustom (object) (ResultFilters)

Objet JSON encodé en URL définissant les cohortes et restrictions. Absent : ensemble de la corporation. Les identifiants proviennent de listResultFilters pour la même itération et la même vue. Au plus 6 Kio une fois encodé.

benchmark
string (BenchmarkType)
Enum: "overall" "zest"

Benchmark optionnel, absent par défaut. overall : ensemble de la corporation. zest : référentiel Zest, engagomètre uniquement et si le module est actif ; refusé pendant le pilote (400 invalid_parameter, « Le benchmark Zest n'est pas disponible pour le moment. »). Un benchmark indisponible est signalé dans benchmark.status, jamais remplacé.

lang
string^[a-z]{2,3}(_[A-Z]{2})?$

Langue des libellés (code produit, ex. fr, en, pt_BR). Défaut : langue de la corporation. Une langue non supportée renvoie 400 unsupported_lang. Un libellé non traduit retombe sur la langue de base de la campagne.

Responses

Response samples

Content type
application/json
Example
{
  • "ok": true,
  • "data": {
    },
  • "meta": {
    }
}