Signalements
GET /admin/reports
Section titled “GET /admin/reports”Scan paginé (keyset) de la file de modération hxa_bo.report. Renvoie les données brutes, sans anonymisation : la modération a besoin d’identifier le rapporteur pour les analyses de pattern (utilisateur qui signale en masse, etc.).
Query params
| Param | Valeurs | Défaut | Notes |
|---|---|---|---|
status | pending | reviewed | action_taken | dismissed | aucun (tous statuts) | Filtre exact. Une valeur inconnue est silencieusement ignorée (équivaut à aucun). |
targetType | media | user | comment | aucun | Idem. |
limit | 1..100 | 50 | Borné en dur côté serveur. |
cursorAt | ISO-8601 datetime | aucun | created_at du dernier item de la page précédente. À fournir avec cursorId (les deux ou aucun). |
cursorId | hex (32 chars) | aucun | id du dernier item — discriminant pour les created_at identiques. |
Tri implicite : created_at DESC, id DESC (plus récents d’abord).
Réponse (200)
{ "items": [ { "id": "01a3471992e44c60a8f08321f713635a", "reporterUserId": "ff…", "targetType": "media", "targetId": "ab…", "reasonCode": "spam", "details": "…optional free text…", "status": "pending", "resolvedByUserId": null, "resolvedAt": null, "resolutionNote": null, "createdAt": "2026-06-13T12:34:56+00:00", "updatedAt": "2026-06-13T12:34:56+00:00" } ], "nextCursor": { "at": "2026-06-13T12:34:56+00:00", "id": "01a3…" } // `null` quand la page courante contient < `limit` items (= dernière page)}Exemple curl
# Première page de la filecurl -s -H "Authorization: Bearer $ADMIN_API_TOKEN" \ "http://hydrogen.dev.com/admin/reports?status=pending&limit=50"
# Page suivantecurl -s -H "Authorization: Bearer $ADMIN_API_TOKEN" \ "http://hydrogen.dev.com/admin/reports?status=pending&limit=50&cursorAt=2026-06-13T12:34:56%2B00:00&cursorId=01a3471992e44c60a8f08321f713635a"Erreurs
| Status | Body | Sens |
|---|---|---|
400 | { "error": "Both cursorAt and cursorId must be supplied together." } | une moitié seulement du curseur a été envoyée |
400 | { "error": "cursorAt is not a valid datetime." } | parsing Carbon KO |
400 | { "error": "cursorId is not a valid hex UUID." } | hex malformé |
403 | { "error": "..." } | auth KO |
GET /admin/reports/{hex}
Section titled “GET /admin/reports/{hex}”Lecture unitaire d’un signalement, en JSON:API 1.1 (cf. Convention de format).
Réponse (200) : enveloppe { jsonapi, data:{ type:"reports", id, attributes } }. data.attributes reprend les mêmes champs que items[] de la liste (id remonté au niveau data.id, pas dupliqué dans attributes) : reporterUserId, targetType, targetId, reasonCode, details, status, resolvedByUserId, resolvedAt, resolutionNote, createdAt, updatedAt.
{ "jsonapi": { "version": "1.1" }, "data": { "type": "reports", "id": "4f3c1a2b-5d6e-7f80-91a2-b3c4d5e6f700", "attributes": { "reporterUserId": "…", "targetType": "media", "targetId": "…", "reasonCode": "spam", "details": "…", "status": "pending", "resolvedByUserId": null, "resolvedAt": null, "resolutionNote": null, "createdAt": "2026-06-01T10:00:00+00:00", "updatedAt": "2026-06-01T10:00:00+00:00" } }}Erreurs
| Status | Body | Sens |
|---|---|---|
404 | erreur JSON:API (errors[].title = "Report not found") | row absente ou hex malformé |
403 | { "error": "..." } | auth KO |
PATCH /admin/reports/{hex}
Section titled “PATCH /admin/reports/{hex}”Transition du verdict modérateur.
Body
{ "status": "reviewed" | "action_taken" | "dismissed", "resolutionNote": "Optional internal note.", // optionnel "resolvedBy": "<reporterHex>" // optionnel — id opérateur}statusne peut pas valoirpending(pas de réouverture supportée dans cette itération).resolvedByest optionnel : utile quand un opérateur humain valide via un BO ; à omettre pour un job automatisé (la colonne resteNULL).resolutionNoteest trim+filtré (vide ⇒ NULL).
Idempotence : un PATCH sur une row déjà résolue retourne 200 avec le verdict existant sans toucher la base — le premier verdict modérateur est canonique.
Réponse (200) : la row complète mise à jour (même shape que GET /admin/reports/{hex}).
Erreurs
| Status | Body | Sens |
|---|---|---|
400 | { "error": "status must be one of: reviewed, action_taken, dismissed." } | enum invalide |
400 | { "error": "resolvedBy is not a valid hex UUID." } | hex malformé |
400 | { "error": "Body must be a JSON object." } | JSON KO |
404 | { "error": "Report not found." } | row absente |
403 | { "error": "..." } | auth KO |
Notes
- Le verdict n’envoie aucune notification au rapporteur ni à la cible — c’est volontaire, la modération reste invisible côté produit. Si un comportement « décision communiquée à l’utilisateur » est requis plus tard, c’est un side-effect à brancher ici (et à documenter).
- Aucune action automatique sur la cible (suppression de média, ban de compte, …) : la modération applique ces gestes hors de Hydrogen via l’admin métier. Cet endpoint ne fait que figer le verdict côté file.