| name | zendesk_query |
| description | Query Zendesk support tickets and comments for Emplois de l'Inclusion (read-only). (project) |
Zendesk Query Skill
Lecture seule des tickets et commentaires Zendesk du support Emplois.
Configuration
Variables d'environnement (cf. .env.example) :
ZENDESK_SUBDOMAIN — sous-domaine <subdomain>.zendesk.com
ZENDESK_EMAIL — email du compte API
ZENDESK_API_TOKEN — jeton API (Admin Center → Apps → API)
L'instance par défaut est emplois. Configurée dans config/sources.yaml.
Usage
from lib.sources import get_zendesk
zd = get_zendesk()
ticket = zd.get_ticket(12345)
comments = zd.get_ticket_comments(12345)
first_reply = zd.first_user_reply(12345)
for r in zd.iter_tickets([1, 2, 3], with_comments=True):
if r.error:
continue
print(r.ticket.subject, len(r.comments or []))
hits = zd.search_tickets("status:open tags:bug created>2026-01-01", sort_by="created_at", sort_order="desc", max_results=50)
n = zd.count_tickets("status:open tags:bug created>2026-01-01")
print(f"{n} tickets correspondent, {len(hits)} chargés")
Méthodes disponibles
| Méthode | Retour | Usage |
|---|
get_ticket(ticket_id) | ZendeskTicket | Métadonnées d'un ticket |
get_ticket_comments(ticket_id) | list[ZendeskComment] | Commentaires (oldest first, première page uniquement) |
first_user_reply(ticket_id) | ZendeskComment | None | Première réponse end-user après le premier message agent |
iter_tickets(ids, with_comments=False) | itérateur TicketResult | Boucle batch avec gestion d'erreur par ticket et log de progression |
search_tickets(query, sort_by=None, sort_order=None, max_results=100) | list[ZendeskTicket] | Recherche full-text via /search.json ; type:ticket ajouté automatiquement, suit next_page jusqu'à max_results |
count_tickets(query) | int | Nombre total de tickets correspondants (/search/count.json), sans coût pagination |
check_auth() | dict | Vérifie les credentials (users/me) |
Anonymisation des NIR (activée par défaut)
Les tickets de support contiennent parfois des NIR (numéros de sécurité sociale) saisis par les usagers — mesuré à ~1,3 % des tickets sur un échantillon de 300.
Le client les remplace automatiquement par [NIR-ANONYMISÉ] dans les sujets de tickets et les commentaires (body et html_body). Un NIR n'est donc jamais exposé à l'agent ni restitué à l'utilisateur.
La détection valide la clé INSEE (97 - (13 premiers chiffres mod 97)), ce qui évite d'effacer des numéros de téléphone, SIRET ou références de commande. Les séparateurs (espaces, points, tirets) sont gérés.
Le code vit dans lib/pii.py, indépendant de Zendesk : redact_nir(texte) est réutilisable sur n'importe quelle source de texte libre (commentaires Matomo, exports Metabase, contenus de tableaux de bord…).
load_api()
load_api().redact
ZendeskAPI(..., redact=False)
Ne jamais désactiver l'anonymisation pour produire une réponse, un rapport ou un tableau de bord destiné à un utilisateur.
Notes
- Rate limit interne (~700 req/min, plan Suite Professional). Sur 429, le client attend
Retry-After et réessaie jusqu'à 3 fois avant de lever ZendeskError(429, ...).
- Toutes les méthodes lèvent
ZendeskError(status_code, message) sur erreur HTTP non-200.
- Les commentaires utilisent le sideloading
users pour exposer author_role (end-user / agent / admin).
- Pour des analyses cross-tickets, utiliser
iter_tickets (logue tous les 500 et continue malgré les erreurs ponctuelles) plutôt que de boucler à la main.
iter_tickets(with_comments=True) fait 2 appels par ticket (métadonnées + commentaires). Pour des batches volumineux, prévoir le coût.
Limitations connues
- Pagination non implémentée :
get_ticket_comments ne lit que la première page de la réponse Zendesk (~100 commentaires max). Les tickets longs (chaînes de support très actives) seront tronqués sans erreur. Si ce cas devient bloquant, ajouter le suivi de next_page dans _get.
- Anonymisation limitée au NIR : les autres données personnelles (nom, e-mail, téléphone, adresse) ne sont pas masquées et restent visibles dans les commentaires.
Quand l'utiliser
- Diagnostiquer une demande utilisateur précise (ticket #X)
- Extraire les premières clarifications sur un échantillon de tickets pour analyser les motifs de contact
- Recouper des tags / statuts avec des données Matomo ou Metabase