API Feedback
Chat in-app avec l'admin de la plateforme et point d'entrée pour les demandes d'activation de modules on-demand.
API Feedback
L'API Feedback alimente le chat in-app entre un utilisateur authentifié et l'admin de la plateforme. Elle sert aussi de point d'entrée pour les demandes d'activation de modules on-demand : cliquer "Demander" sur un module stub (email, SMS, WhatsApp, opérateur téléphonique) ouvre un fil de feedback avec un topic dédié, qui apparaît dans l'inbox "On demand" du dashboard admin.
Un fil est une conversation stable épinglée à un topic. Chaque réponse est une ligne feedback_message rattachée à ce fil. L'état de lecture est tracké par rôle (user, admin) afin que chaque côté ne voie que son propre badge non-lu.
Tous les endpoints requièrent un appelant authentifié. Erreurs génériques : 401 (non authentifié), 404 (fil inexistant). Les causes spécifiques sont en ligne.
Conventions de topic
Le champ topic d'un fil est une chaîne libre plafonnée à 64 caractères, mais le produit suit un petit jeu de conventions :
| Valeur de topic | Signification |
|---|---|
general |
Défaut. Chat fourre-tout. |
feedback |
Feedback produit générique. |
bug |
Rapport de bug. |
feature |
Demande de fonctionnalité. |
on_demand_email |
Demande d'activation du stub campagne email. |
on_demand_sms |
Demande d'activation du stub campagne SMS. |
on_demand_whatsapp |
Demande d'activation du stub WhatsApp. |
on_demand_phone_carrier |
Demande d'activation du stub opérateur tél. |
Tout topic correspondant à on_demand_* est capté par l'endpoint admin GET /api/admin/feedback/on-demand, qui groupe les fils par topic et expose les compteurs ouverts. Les stubs on-demand sont listés dans le registre des modules sous on_demand ; un client peut lire le registre et construire topic = "on_demand_" + slug.
Le champ plus court type (bug, feature, other) est indépendant du topic et ne porte que l'intention grossière pour le tri.
POST /api/feedback/threads
Crée un nouveau fil avec son premier message. Limite : 20 fils par utilisateur par heure.
| Champ | Type | Notes |
|---|---|---|
type |
string | bug, feature ou other. Défaut other. |
message |
string | 3 à 5000 caractères. Corps du premier message. |
topic |
string | Optionnel. Défaut general. Max 64 caractères. |
Requête
POST /api/feedback/threads
{
"type": "feature",
"topic": "on_demand_whatsapp",
"message": "L'envoi de relances WhatsApp sur les leads scrapés serait utile."
}
Réponse — 201 Created
{
"id": 142,
"user_id": 7,
"user_email": "user@example.com",
"type": "feature",
"status": "open",
"created_at": "2026-05-27 10:11:12",
"last_read_user": "2026-05-27 10:11:12",
"last_read_admin": null,
"messages": [
{
"id": 991,
"author_role": "user",
"author_user_id": 7,
"message": "L'envoi de relances WhatsApp sur les leads scrapés serait utile.",
"created_at": "2026-05-27 10:11:12"
}
],
"preview": "L'envoi de relances WhatsApp sur les leads scrapés serait utile.",
"last_message_at": "2026-05-27 10:11:12",
"unread_for_me": 0
}
Causes spécifiques : 400 type hors de {bug, feature, other} ; 422 message plus court que 3 ou plus long que 5000 ; 429 plus de 20 fils dans la dernière heure.
POST /api/feedback/threads/{thread_id}/messages
Ajoute une réponse à un fil existant. L'appelant doit posséder le fil, et le fil ne doit pas être closed. Poster un message marque aussi le fil comme lu côté user.
Requête
POST /api/feedback/threads/142/messages
{
"message": "Pour contexte : le tracking d'opt-out serait aussi nécessaire."
}
Réponse — 201 Created
Renvoie le fil sérialisé complet, identique en forme à la réponse de POST /threads, avec le message ajouté inclus.
Causes spécifiques : 400 fil closed ; 403 appelant ne possède pas le fil ; 422 message vide ou plus long que 5000.
GET /api/feedback/threads
Liste les fils de l'appelant, les plus récents d'abord. Plafonné à 100 lignes. Chaque entrée embarque la liste complète des messages pour rendre previews et compteurs non-lus sans second aller-retour.
Réponse — 200 OK
[
{
"id": 142,
"user_id": 7,
"user_email": "user@example.com",
"type": "feature",
"status": "open",
"created_at": "2026-05-27 10:11:12",
"last_read_user": "2026-05-27 10:11:12",
"last_read_admin": null,
"messages": [ /* ... */ ],
"preview": "L'envoi de relances WhatsApp...",
"last_message_at": "2026-05-27 10:11:12",
"unread_for_me": 0
}
]
Le compteur unread_for_me reflète les réponses admin pas encore vues, calculé à partir de last_read_user. L'endpoint compagnon GET /api/feedback/unread retourne le même nombre agrégé sur tous les fils, prêt à être lié à un badge d'en-tête.