Skip to content

Signalements

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

ParamValeursDéfautNotes
statuspending | reviewed | action_taken | dismissedaucun (tous statuts)Filtre exact. Une valeur inconnue est silencieusement ignorée (équivaut à aucun).
targetTypemedia | user | commentaucunIdem.
limit1..10050Borné en dur côté serveur.
cursorAtISO-8601 datetimeaucuncreated_at du dernier item de la page précédente. À fournir avec cursorId (les deux ou aucun).
cursorIdhex (32 chars)aucunid 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

Terminal window
# Première page de la file
curl -s -H "Authorization: Bearer $ADMIN_API_TOKEN" \
"http://hydrogen.dev.com/admin/reports?status=pending&limit=50"
# Page suivante
curl -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

StatusBodySens
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

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

StatusBodySens
404erreur JSON:API (errors[].title = "Report not found")row absente ou hex malformé
403{ "error": "..." }auth KO

Transition du verdict modérateur.

Body

{
"status": "reviewed" | "action_taken" | "dismissed",
"resolutionNote": "Optional internal note.", // optionnel
"resolvedBy": "<reporterHex>" // optionnel — id opérateur
}
  • status ne peut pas valoir pending (pas de réouverture supportée dans cette itération).
  • resolvedBy est optionnel : utile quand un opérateur humain valide via un BO ; à omettre pour un job automatisé (la colonne reste NULL).
  • resolutionNote est 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

StatusBodySens
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.