Aller au contenu

API — Administration

Base URL

http://localhost:8010/api/v1

Authentification requise

Tous les endpoints admin nécessitent un token JWT valide (Authorization: Bearer <token>) et le rôle admin. En cas de rôle insuffisant, le serveur retourne 403 Forbidden.


Dashboard

GET /admin/dashboard — Tableau de bord KPIs

Retourne les indicateurs clés, les tendances et les clubs en attente.

{
  "data": {
    "kpis": {
      "total_users": 150,
      "total_games": 42,
      "total_clubs": 8,
      "activity_rate": 65.3,
      "pending_clubs": 2
    },
    "registration_trend": {
      "2025-07": 10,
      "2025-08": 15,
      "2025-09": 20
    },
    "games_trend": {
      "2025-07": 5,
      "2025-08": 8,
      "2025-09": 12
    },
    "level_distribution": [
      { "name": "Débutant", "min": 1, "max": 2, "count": 30 },
      { "name": "Intermédiaire", "min": 3, "max": 5, "count": 50 }
    ],
    "pending_clubs_list": [
      {
        "id": 1,
        "name": "Padel Club Paris",
        "city": "Paris",
        "created_at": "2025-12-01T10:00:00Z"
      }
    ]
  }
}

Niveaux de jeu

GET /admin/game-levels — Lister les niveaux

Retourne la liste de tous les niveaux de jeu triés par sort_order.

{
  "data": [
    {
      "id": 1,
      "name": "Débutant",
      "min_value": 1,
      "max_value": 2,
      "sort_order": 1,
      "created_at": "2025-01-01T00:00:00Z",
      "updated_at": "2025-01-01T00:00:00Z"
    }
  ]
}

POST /admin/game-levels — Créer un niveau

Champ Type Obligatoire Description
name string Nom unique du niveau
min_value integer Valeur minimale de la plage
max_value integer Valeur maximale de la plage
sort_order integer Ordre d'affichage
{
  "data": {
    "id": 4,
    "name": "Expert+",
    "min_value": 9,
    "max_value": 10,
    "sort_order": 4
  }
}
{
  "message": "The given data was invalid.",
  "errors": {
    "name": ["The name has already been taken."]
  }
}

PUT /admin/game-levels/{id} — Modifier un niveau

Mêmes champs que la création (tous optionnels).

{
  "data": {
    "id": 1,
    "name": "Débutant modifié",
    "min_value": 1,
    "max_value": 3,
    "sort_order": 1
  }
}

DELETE /admin/game-levels/{id} — Supprimer un niveau

{ "message": "Niveau de jeu supprimé avec succès." }

POST /admin/game-levels/restore-defaults — Restaurer les défauts

Supprime tous les niveaux et recrée ceux par défaut.

{
  "data": [
    { "id": 10, "name": "Débutant", "min_value": 1, "max_value": 2, "sort_order": 1 }
  ]
}

Utilisateurs

GET /admin/users — Lister les utilisateurs

Paramètre Type Description
search string Recherche par nom, prénom ou email
role string Filtre par rôle : player, club_manager, admin
min_level integer Filtre par niveau minimum
max_level integer Filtre par niveau maximum
page integer Numéro de page (défaut : 1)
per_page integer Éléments par page (défaut : 15)
{
  "data": [
    {
      "id": 1,
      "first_name": "Jean",
      "last_name": "Dupont",
      "email": "jean@example.com",
      "role": "player",
      "city": "Paris",
      "level": { "id": 1, "name": "Débutant" },
      "reliability_score": 85,
      "created_at": "2025-01-15T10:00:00Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "last_page": 5,
    "per_page": 15,
    "total": 72
  }
}

GET /admin/users/{id} — Détail d'un utilisateur

{
  "data": {
    "id": 1,
    "first_name": "Jean",
    "last_name": "Dupont",
    "email": "jean@example.com",
    "role": "player",
    "city": "Paris",
    "level": { "id": 1, "name": "Débutant" },
    "reliability_score": 85,
    "email_verified_at": "2025-01-15T10:00:00Z",
    "created_at": "2025-01-15T10:00:00Z"
  },
  "statistics": {
    "total_games": 12,
    "wins": 8,
    "losses": 4,
    "clubs_managed": 0
  }
}

Clubs

GET /admin/clubs — Lister les clubs

Paramètre Type Description
search string Recherche par nom ou ville
status string Filtre par statut : pending, validated, suspended
page integer Numéro de page (défaut : 1)
per_page integer Éléments par page (défaut : 15)
{
  "data": [
    {
      "id": 1,
      "name": "Padel Club Paris",
      "city": "Paris",
      "address": "123 Rue du Padel",
      "status": "pending",
      "logo_url": null,
      "owner": {
        "id": 10,
        "first_name": "Sophie",
        "last_name": "Martin"
      },
      "created_at": "2025-12-01T10:00:00Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "last_page": 1,
    "per_page": 15,
    "total": 2
  }
}

GET /admin/clubs/{id} — Détail d'un club

{
  "data": {
    "id": 1,
    "name": "Padel Club Paris",
    "city": "Paris",
    "address": "123 Rue du Padel",
    "status": "validated",
    "description": "Club de padel premium",
    "phone": "01 23 45 67 89",
    "email": "contact@padelclubparis.com",
    "website": "https://padelclubparis.com",
    "owner": { "id": 10, "first_name": "Sophie", "last_name": "Martin" },
    "terrains": [],
    "created_at": "2025-12-01T10:00:00Z"
  }
}

POST /admin/clubs — Créer un club

Champ Type Obligatoire Description
name string Nom du club
address string Adresse
city string Ville
description string Description
phone string Téléphone
email string Email de contact
website string Site web
{
  "data": { "id": 3, "name": "Nouveau Club", "status": "validated" }
}

PUT /admin/clubs/{id} — Modifier un club

Mêmes champs que la création (tous optionnels).

DELETE /admin/clubs/{id} — Supprimer un club

{ "message": "Club supprimé avec succès." }

POST /admin/clubs/{id}/approve — Approuver un club

Change le statut d'un club pending vers validated.

{ "message": "Club approuvé avec succès." }

POST /admin/clubs/{id}/reject — Rejeter un club

Change le statut d'un club pending vers suspended.

{ "message": "Club rejeté." }

POST /admin/clubs/{id}/suspend — Suspendre un club

Change le statut d'un club validated vers suspended.

{ "message": "Club suspendu." }

Paramètres

GET /admin/settings — Récupérer tous les paramètres

{
  "data": {
    "cgu": {
      "key": "cgu",
      "value": "<p>Conditions générales d'utilisation...</p>",
      "type": "text"
    },
    "privacy_policy": {
      "key": "privacy_policy",
      "value": "<p>Politique de confidentialité...</p>",
      "type": "text"
    },
    "legal_mentions": {
      "key": "legal_mentions",
      "value": "<p>Mentions légales...</p>",
      "type": "text"
    },
    "faq": {
      "key": "faq",
      "value": [
        { "question": "Comment créer une partie ?", "answer": "..." }
      ],
      "type": "json"
    },
    "match_reminder_delay": {
      "key": "match_reminder_delay",
      "value": "2",
      "type": "number"
    }
  }
}

PUT /admin/settings — Mettre à jour les paramètres

Mise à jour en batch : envoyer uniquement les clés à modifier.

{
  "settings": {
    "cgu": "<p>Nouveau contenu CGU</p>",
    "match_reminder_delay": "24"
  }
}
{ "message": "Paramètres mis à jour avec succès." }

Route publique

GET /settings/{key} — Paramètre public

Accessible sans authentification. Clés autorisées : cgu, privacy_policy, legal_mentions, faq.

{
  "data": {
    "key": "cgu",
    "value": "<p>Conditions générales...</p>",
    "type": "text"
  }
}
{ "message": "Paramètre non trouvé." }

Logs système

GET /admin/logs — Lister les fichiers de log

Retourne la liste des fichiers de log journaliers disponibles sur le serveur.

{
  "data": [
    {
      "date": "2026-03-10",
      "size": 245760,
      "size_human": "240.0 KB",
      "entries_count": 142
    },
    {
      "date": "2026-03-09",
      "size": 512000,
      "size_human": "500.0 KB",
      "entries_count": 310
    }
  ]
}

GET /admin/logs/{date} — Consulter les entrées d'un fichier

Retourne les entrées de log d'un fichier journalier, avec filtrage et pagination.

Paramètre Type Description
date path Date au format YYYY-MM-DD
search query Filtrer par mot-clé dans le message
level query Filtrer par niveau (emergency, alert, critical, error, warning, notice, info, debug)
page query Numéro de page (défaut : 1)
per_page query Entrées par page (défaut : 50, max : 200)
sort query Tri : asc ou desc (défaut : desc)
{
  "data": [
    {
      "timestamp": "2026-03-10 14:30:22",
      "level": "error",
      "message": "Database connection timeout after 5000ms",
      "context": {
        "exception": "PDOException",
        "connection": "pgsql"
      },
      "extra": {}
    },
    {
      "timestamp": "2026-03-10 14:25:00",
      "level": "info",
      "message": "User logged in successfully",
      "context": {},
      "extra": {}
    }
  ],
  "meta": {
    "current_page": 1,
    "last_page": 3,
    "per_page": 50,
    "total": 142
  }
}
{ "message": "Log file not found for this date." }
{ "message": "Invalid date format. Expected YYYY-MM-DD." }

Sécurité

Le paramètre date est validé pour empêcher toute tentative de path traversal. Seuls les fichiers laravel-YYYY-MM-DD.log du répertoire storage/logs/ sont accessibles.


Analytics

POST /analytics/track — Enregistrer une visite (public)

Endpoint public

Cet endpoint ne nécessite pas d'authentification. Il est protégé par un rate limit de 60 requêtes/minute par IP.

Enregistre une visite de page de manière anonyme (sans lien avec un utilisateur).

{
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "page_path": "/clubs/3",
  "referrer": "https://google.com",
  "duration_seconds": 45
}
Champ Type Requis Description
session_id string oui UUID de session (max 64 car.)
page_path string oui Chemin de la page (max 500 car.)
referrer string non URL référente
duration_seconds integer non Durée de visite en secondes (0–86400)
{ "message": "ok" }
{ "message": "Too Many Attempts." }

Données collectées automatiquement

Le backend déduit automatiquement : type d'appareil (User-Agent), pays (Accept-Language), hash anonyme de l'IP.


GET /admin/analytics/overview — KPIs globaux

Retourne les indicateurs clés de fréquentation pour une période donnée.

Paramètre Type Description
period query today, 7d, 30d, 90d (défaut : 7d)
{
  "data": {
    "unique_visitors": 342,
    "page_views": 1250,
    "avg_duration": 127.3,
    "bounce_rate": 35.2
  }
}

GET /admin/analytics/top-pages — Pages les plus visitées

Paramètre Type Description
period query today, 7d, 30d, 90d (défaut : 7d)
limit query Nombre max de résultats (défaut : 10, max : 50)
{
  "data": [
    {
      "page_path": "/",
      "views": 450,
      "unique_visitors": 280,
      "avg_duration": 95.2
    },
    {
      "page_path": "/clubs",
      "views": 220,
      "unique_visitors": 150,
      "avg_duration": 180.5
    }
  ]
}

GET /admin/analytics/trend — Courbe de visites

Paramètre Type Description
period query today, 7d, 30d, 90d (défaut : 30d)
granularity query day, week, month (défaut : day)
{
  "data": [
    { "date": "2026-03-08", "visits": 180, "unique_visitors": 95 },
    { "date": "2026-03-09", "visits": 210, "unique_visitors": 120 },
    { "date": "2026-03-10", "visits": 195, "unique_visitors": 110 }
  ]
}

GET /admin/analytics/devices — Répartition par appareil

Paramètre Type Description
period query today, 7d, 30d, 90d (défaut : 7d)
{
  "data": {
    "desktop": 180,
    "mobile": 120,
    "tablet": 25
  }
}

GET /admin/analytics/sources — Sources de trafic

Paramètre Type Description
period query today, 7d, 30d, 90d (défaut : 7d)
{
  "data": [
    { "source": "Direct", "visits": 150, "percentage": 46.2 },
    { "source": "https://google.com", "visits": 100, "percentage": 30.8 },
    { "source": "https://facebook.com", "visits": 75, "percentage": 23.1 }
  ]
}