{
 "openapi": "3.0.3",
 "info": {
  "title": "API publique Nalyora",
  "version": "1.0.0",
  "description": "Les données publiques du réseau Nalyora (NalyoraCore, NGuilds, NalyoraAuction).\nLecture seule, sans clé, 10 requêtes par seconde et par adresse IP.\n",
  "license": {
   "name": "Usage libre pour les outils de la communauté"
  }
 },
 "servers": [
  {
   "url": "https://api.nalyora.fr/v1"
  }
 ],
 "tags": [
  {
   "name": "Serveur",
   "description": "État du réseau et joueurs en ligne."
  },
  {
   "name": "Joueurs",
   "description": "Profils publics."
  },
  {
   "name": "Classements",
   "description": "Meilleurs joueurs et meilleures guildes."
  },
  {
   "name": "Guildes",
   "description": "Guildes du réseau (NGuilds)."
  },
  {
   "name": "Hôtel des ventes",
   "description": "Annonces en cours (NalyoraAuction)."
  },
  {
   "name": "Statut",
   "description": "Activité et santé de l'API elle-même."
  }
 ],
 "paths": {
  "/statut": {
   "get": {
    "tags": [
     "Statut"
    ],
    "operationId": "statutApi",
    "summary": "Activité et état de l'API",
    "description": "Métriques des 10 dernières minutes : requêtes par minute, latence côté serveur, erreurs, et état de chaque module.\nCette route n'est pas comptée dans les statistiques qu'elle renvoie. Les requêtes refusées par la limite de débit (429) ne sont pas comptées non plus.\n",
    "responses": {
     "200": {
      "description": "Activité récente.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Statut"
        },
        "example": {
         "etat": "operationnel",
         "periode_minutes": 10,
         "requetes": {
          "total": 145,
          "par_minute": [
           {
            "minute": "2026-11-05T03:14:00.000Z",
            "total": 15,
            "erreurs": 0
           },
           {
            "minute": "2026-11-05T03:15:00.000Z",
            "total": 0,
            "erreurs": 0
           },
           {
            "minute": "2026-11-05T03:16:00.000Z",
            "total": 6,
            "erreurs": 0
           },
           {
            "minute": "2026-11-05T03:17:00.000Z",
            "total": 28,
            "erreurs": 1
           },
           {
            "minute": "2026-11-05T03:18:00.000Z",
            "total": 20,
            "erreurs": 0
           },
           {
            "minute": "2026-11-05T03:19:00.000Z",
            "total": 7,
            "erreurs": 0
           },
           {
            "minute": "2026-11-05T03:20:00.000Z",
            "total": 24,
            "erreurs": 0
           },
           {
            "minute": "2026-11-05T03:21:00.000Z",
            "total": 10,
            "erreurs": 0
           },
           {
            "minute": "2026-11-05T03:22:00.000Z",
            "total": 2,
            "erreurs": 0
           },
           {
            "minute": "2026-11-05T03:23:00.000Z",
            "total": 33,
            "erreurs": 9
           }
          ]
         },
         "latence_ms": {
          "moyenne": 6,
          "p50": 5,
          "p95": 25
         },
         "erreurs": {
          "client": 10,
          "serveur": 0,
          "taux": 0.069
         },
         "modules": [
          {
           "id": "serveur",
           "nom": "Serveur",
           "etat": "operationnel",
           "requetes": 20,
           "erreurs_serveur": 0,
           "latence_ms": 5.5
          },
          {
           "id": "joueurs",
           "nom": "Joueurs",
           "etat": "operationnel",
           "requetes": 24,
           "erreurs_serveur": 0,
           "latence_ms": 6.9
          },
          {
           "id": "classements",
           "nom": "Classements",
           "etat": "operationnel",
           "requetes": 76,
           "erreurs_serveur": 0,
           "latence_ms": 6.6
          },
          {
           "id": "guildes",
           "nom": "Guildes",
           "etat": "operationnel",
           "requetes": 13,
           "erreurs_serveur": 0,
           "latence_ms": 4.5
          },
          {
           "id": "encheres",
           "nom": "Hôtel des ventes",
           "etat": "operationnel",
           "requetes": 12,
           "erreurs_serveur": 0,
           "latence_ms": 3.3
          },
          {
           "id": "base",
           "nom": "Base de données",
           "etat": "operationnel",
           "requetes": null,
           "erreurs_serveur": null,
           "latence_ms": 1.5
          }
         ],
         "disponible_depuis": "2026-11-05T03:23:09.162Z",
         "mis_a_jour": "2026-11-05T03:23:47.103Z"
        }
       }
      }
     },
     "429": {
      "$ref": "#/components/responses/TropDeRequetes"
     }
    }
   }
  },
  "/serveur/etat": {
   "get": {
    "tags": [
     "Serveur"
    ],
    "operationId": "etatServeur",
    "summary": "État du réseau",
    "description": "Nombre de joueurs connectés et répartition par serveur.",
    "responses": {
     "200": {
      "description": "État actuel.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/EtatServeur"
        },
        "example": {
         "en_ligne": 0,
         "serveurs": {
          "events": 0,
          "resource": 0,
          "survival": 0
         },
         "mis_a_jour": "2026-11-05T03:23:47.052Z"
        }
       }
      }
     },
     "429": {
      "$ref": "#/components/responses/TropDeRequetes"
     }
    }
   }
  },
  "/serveur/joueurs": {
   "get": {
    "tags": [
     "Serveur"
    ],
    "operationId": "joueursEnLigne",
    "summary": "Joueurs en ligne",
    "description": "Liste des joueurs actuellement connectés au réseau.",
    "responses": {
     "200": {
      "description": "Joueurs connectés.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "total": {
           "type": "integer",
           "example": 2,
           "description": "Nombre total de résultats (avant pagination)"
          },
          "joueurs": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/JoueurEnLigne"
           }
          }
         }
        },
        "example": {
         "total": 2,
         "joueurs": [
          {
           "uuid": "fe315713-2634-335c-aa1b-cb2672898020",
           "pseudo": "lobo413",
           "serveur": "survival"
          },
          {
           "uuid": "086b5ccc-d74d-3909-9e25-7ed1b27fb543",
           "pseudo": "Stardewk",
           "serveur": "events"
          }
         ]
        }
       }
      }
     },
     "429": {
      "$ref": "#/components/responses/TropDeRequetes"
     }
    }
   }
  },
  "/joueurs/{joueur}": {
   "get": {
    "tags": [
     "Joueurs"
    ],
    "operationId": "profilJoueur",
    "summary": "Profil d'un joueur",
    "description": "Pseudo, UUID, dates, niveau, guilde et statut de connexion.\nLes membres du staff sont masqués : leur profil répond une 404 avec le code `joueur_masque` et une phrase fun.\n",
    "parameters": [
     {
      "$ref": "#/components/parameters/Joueur"
     }
    ],
    "responses": {
     "200": {
      "description": "Profil public.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Joueur"
        },
        "example": {
         "uuid": "fe315713-2634-335c-aa1b-cb2672898020",
         "pseudo": "lobo413",
         "premiere_connexion": "2026-11-04T21:14:08.991Z",
         "derniere_connexion": "2026-11-04T21:14:08.991Z",
         "en_ligne": false,
         "niveau": {
          "niveau": 1,
          "xp": 0
         },
         "guilde": null
        }
       }
      }
     },
     "404": {
      "$ref": "#/components/responses/Introuvable"
     },
     "429": {
      "$ref": "#/components/responses/TropDeRequetes"
     }
    }
   }
  },
  "/joueurs/{joueur}/guilde": {
   "get": {
    "tags": [
     "Joueurs"
    ],
    "operationId": "guildeDuJoueur",
    "summary": "Guilde d'un joueur",
    "parameters": [
     {
      "$ref": "#/components/parameters/Joueur"
     }
    ],
    "responses": {
     "200": {
      "description": "Guilde du joueur.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Guilde"
        }
       }
      }
     },
     "404": {
      "$ref": "#/components/responses/Introuvable"
     },
     "429": {
      "$ref": "#/components/responses/TropDeRequetes"
     }
    }
   }
  },
  "/classements/niveaux": {
   "get": {
    "tags": [
     "Classements"
    ],
    "operationId": "classementNiveaux",
    "summary": "Meilleurs niveaux",
    "description": "Les membres du staff n'y figurent pas.",
    "parameters": [
     {
      "$ref": "#/components/parameters/Limite"
     },
     {
      "$ref": "#/components/parameters/Decalage"
     }
    ],
    "responses": {
     "200": {
      "description": "Joueurs triés par XP décroissante.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/PageClassementJoueurs"
        }
       }
      }
     },
     "429": {
      "$ref": "#/components/responses/TropDeRequetes"
     }
    }
   }
  },
  "/classements/argent": {
   "get": {
    "tags": [
     "Classements"
    ],
    "operationId": "classementArgent",
    "summary": "Joueurs les plus riches",
    "description": "Les membres du staff n'y figurent pas.",
    "parameters": [
     {
      "name": "monnaie",
      "in": "query",
      "description": "Monnaie : vault (argent), ecoshop (boutique) ou afk (points AFK).",
      "schema": {
       "type": "string",
       "enum": [
        "vault",
        "ecoshop",
        "afk"
       ],
       "default": "vault"
      }
     },
     {
      "$ref": "#/components/parameters/Limite"
     },
     {
      "$ref": "#/components/parameters/Decalage"
     }
    ],
    "responses": {
     "200": {
      "description": "Joueurs triés par solde décroissant.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/PageClassementJoueurs"
        },
        "example": {
         "total": 252,
         "monnaie": "vault",
         "joueurs": [
          {
           "rang": 1,
           "uuid": "fe315713-2634-335c-aa1b-cb2672898020",
           "pseudo": "lobo413",
           "valeur": 6741252.88
          },
          {
           "rang": 2,
           "uuid": "086b5ccc-d74d-3909-9e25-7ed1b27fb543",
           "pseudo": "Stardewk",
           "valeur": 4174890.27
          },
          {
           "rang": 3,
           "uuid": "d53f324e-9f8f-323d-8a77-352bc2d8e32a",
           "pseudo": "chihiro_12",
           "valeur": 3972396.28
          }
         ]
        }
       }
      }
     },
     "429": {
      "$ref": "#/components/responses/TropDeRequetes"
     }
    }
   }
  },
  "/classements/guildes": {
   "get": {
    "tags": [
     "Classements"
    ],
    "operationId": "classementGuildes",
    "summary": "Classement des guildes",
    "description": "Classement de la saison en cours, par points de saison.",
    "parameters": [
     {
      "$ref": "#/components/parameters/Limite"
     },
     {
      "$ref": "#/components/parameters/Decalage"
     }
    ],
    "responses": {
     "200": {
      "description": "Guildes actives triées par points de saison.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "saison": {
           "type": "string",
           "example": "2026-11",
           "description": "Saison en cours (AAAA-MM)"
          },
          "total": {
           "type": "integer",
           "description": "Nombre total de résultats (avant pagination)"
          },
          "guildes": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Guilde"
           },
           "description": "Guildes de la page"
          }
         }
        },
        "example": {
         "saison": "2026-11",
         "total": 1,
         "guildes": [
          {
           "id": 2,
           "nom": "NalyoraDev",
           "nom_mini_message": "NalyoraDev",
           "palier": 1,
           "xp": 0,
           "points_saison": 0,
           "banque": 0,
           "membres": 1,
           "suspendue": false,
           "creee_le": "2026-11-02T18:48:26.979Z"
          }
         ]
        }
       }
      }
     },
     "429": {
      "$ref": "#/components/responses/TropDeRequetes"
     }
    }
   }
  },
  "/guildes": {
   "get": {
    "tags": [
     "Guildes"
    ],
    "operationId": "listeGuildes",
    "summary": "Liste des guildes",
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "description": "Recherche dans le nom.",
      "schema": {
       "type": "string",
       "maxLength": 20
      }
     },
     {
      "$ref": "#/components/parameters/Limite"
     },
     {
      "$ref": "#/components/parameters/Decalage"
     }
    ],
    "responses": {
     "200": {
      "description": "Guildes actives.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "total": {
           "type": "integer",
           "description": "Nombre total de résultats (avant pagination)"
          },
          "guildes": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Guilde"
           },
           "description": "Guildes de la page"
          }
         }
        },
        "example": {
         "total": 1,
         "guildes": [
          {
           "id": 2,
           "nom": "NalyoraDev",
           "nom_mini_message": "NalyoraDev",
           "palier": 1,
           "xp": 0,
           "points_saison": 0,
           "banque": 0,
           "membres": 1,
           "suspendue": false,
           "creee_le": "2026-11-02T18:48:26.979Z"
          }
         ]
        }
       }
      }
     },
     "429": {
      "$ref": "#/components/responses/TropDeRequetes"
     }
    }
   }
  },
  "/guildes/{guilde}": {
   "get": {
    "tags": [
     "Guildes"
    ],
    "operationId": "detailGuilde",
    "summary": "Détail d'une guilde",
    "parameters": [
     {
      "$ref": "#/components/parameters/GuildeRef"
     }
    ],
    "responses": {
     "200": {
      "description": "La guilde.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Guilde"
        },
        "example": {
         "id": 2,
         "nom": "NalyoraDev",
         "nom_mini_message": "NalyoraDev",
         "palier": 1,
         "xp": 0,
         "points_saison": 0,
         "banque": 0,
         "membres": 1,
         "suspendue": false,
         "creee_le": "2026-11-02T18:48:26.979Z"
        }
       }
      }
     },
     "404": {
      "$ref": "#/components/responses/Introuvable"
     },
     "429": {
      "$ref": "#/components/responses/TropDeRequetes"
     }
    }
   }
  },
  "/guildes/{guilde}/membres": {
   "get": {
    "tags": [
     "Guildes"
    ],
    "operationId": "membresGuilde",
    "summary": "Membres d'une guilde",
    "parameters": [
     {
      "$ref": "#/components/parameters/GuildeRef"
     }
    ],
    "responses": {
     "200": {
      "description": "Membres, du rang le plus haut au plus bas.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "total": {
           "type": "integer",
           "description": "Nombre total de résultats (avant pagination)"
          },
          "membres": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/MembreGuilde"
           },
           "description": "Nombre de membres"
          }
         }
        },
        "example": {
         "total": 1,
         "membres": [
          {
           "uuid": "4ece5b9d-2916-341c-8fe3-7428bcc0ef23",
           "pseudo": "NotKoda_",
           "role": "chef",
           "contribution_saison": 0,
           "rejoint_le": "2026-11-02T18:48:26.979Z"
          }
         ]
        }
       }
      }
     },
     "404": {
      "$ref": "#/components/responses/Introuvable"
     },
     "429": {
      "$ref": "#/components/responses/TropDeRequetes"
     }
    }
   }
  },
  "/encheres": {
   "get": {
    "tags": [
     "Hôtel des ventes"
    ],
    "operationId": "listeEncheres",
    "summary": "Annonces en cours",
    "description": "Annonces actives de l'hôtel des ventes. La recherche ignore les accents.",
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "description": "Objet recherché.",
      "schema": {
       "type": "string",
       "maxLength": 64
      }
     },
     {
      "name": "vendeur",
      "in": "query",
      "description": "Pseudo du vendeur.",
      "schema": {
       "type": "string",
       "maxLength": 16
      }
     },
     {
      "name": "prix_min",
      "in": "query",
      "schema": {
       "type": "number",
       "minimum": 0
      }
     },
     {
      "name": "prix_max",
      "in": "query",
      "schema": {
       "type": "number",
       "minimum": 0
      }
     },
     {
      "name": "tri",
      "in": "query",
      "schema": {
       "type": "string",
       "enum": [
        "recent",
        "prix_asc",
        "prix_desc",
        "expiration"
       ],
       "default": "recent"
      }
     },
     {
      "$ref": "#/components/parameters/Limite"
     },
     {
      "$ref": "#/components/parameters/Decalage"
     }
    ],
    "responses": {
     "200": {
      "description": "Page d'annonces.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "total": {
           "type": "integer",
           "description": "Nombre total de résultats (avant pagination)"
          },
          "annonces": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Annonce"
           },
           "description": "Annonces de la page"
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/RequeteInvalide"
     },
     "429": {
      "$ref": "#/components/responses/TropDeRequetes"
     }
    }
   }
  },
  "/encheres/{id}": {
   "get": {
    "tags": [
     "Hôtel des ventes"
    ],
    "operationId": "detailAnnonce",
    "summary": "Détail d'une annonce",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "integer",
       "format": "int64"
      },
      "example": 128
     }
    ],
    "responses": {
     "200": {
      "description": "L'annonce.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Annonce"
        }
       }
      }
     },
     "404": {
      "$ref": "#/components/responses/Introuvable"
     },
     "429": {
      "$ref": "#/components/responses/TropDeRequetes"
     }
    }
   }
  },
  "/encheres/statistiques": {
   "get": {
    "tags": [
     "Hôtel des ventes"
    ],
    "operationId": "statistiquesEncheres",
    "summary": "Statistiques de l'hôtel des ventes",
    "responses": {
     "200": {
      "description": "Chiffres globaux.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "annonces_actives": {
           "type": "integer",
           "example": 214,
           "description": "Nombre d'annonces en cours"
          },
          "vendeurs": {
           "type": "integer",
           "example": 57,
           "description": "Nombre de vendeurs distincts"
          },
          "prix_moyen": {
           "type": "number",
           "example": 1850.5,
           "description": "Prix moyen des annonces actives"
          }
         }
        },
        "example": {
         "annonces_actives": 0,
         "vendeurs": 0,
         "prix_moyen": 0
        }
       }
      }
     },
     "429": {
      "$ref": "#/components/responses/TropDeRequetes"
     }
    }
   }
  }
 },
 "components": {
  "parameters": {
   "Joueur": {
    "name": "joueur",
    "in": "path",
    "required": true,
    "description": "Pseudo ou UUID.",
    "schema": {
     "type": "string"
    },
    "example": "lobo413"
   },
   "GuildeRef": {
    "name": "guilde",
    "in": "path",
    "required": true,
    "description": "Identifiant numérique ou nom sans mise en forme.",
    "schema": {
     "type": "string"
    },
    "example": "NalyoraDev"
   },
   "Limite": {
    "name": "limite",
    "in": "query",
    "schema": {
     "type": "integer",
     "minimum": 1,
     "maximum": 100,
     "default": 20
    }
   },
   "Decalage": {
    "name": "decalage",
    "in": "query",
    "description": "Nombre de résultats à sauter.",
    "schema": {
     "type": "integer",
     "minimum": 0,
     "default": 0
    }
   }
  },
  "responses": {
   "Introuvable": {
    "description": "La ressource n'existe pas.",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Erreur"
      },
      "example": {
       "erreur": {
        "code": "introuvable",
        "message": "Joueur inconnu."
       }
      }
     }
    }
   },
   "RequeteInvalide": {
    "description": "Paramètre invalide.",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Erreur"
      }
     }
    }
   },
   "TropDeRequetes": {
    "description": "Plus de 10 requêtes par seconde. Réessaie après le délai de `Retry-After`.",
    "headers": {
     "Retry-After": {
      "schema": {
       "type": "integer"
      },
      "description": "Secondes à attendre."
     }
    },
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Erreur"
      }
     }
    }
   }
  },
  "schemas": {
   "Erreur": {
    "type": "object",
    "properties": {
     "erreur": {
      "type": "object",
      "properties": {
       "code": {
        "type": "string",
        "example": "introuvable",
        "description": "Code d'erreur stable, utilisable dans ton programme"
       },
       "message": {
        "type": "string",
        "description": "Explication lisible"
       }
      }
     }
    }
   },
   "Statut": {
    "type": "object",
    "properties": {
     "etat": {
      "type": "string",
      "enum": [
       "operationnel",
       "degrade",
       "panne"
      ],
      "description": "État global : le pire état parmi les modules"
     },
     "periode_minutes": {
      "type": "integer",
      "description": "Durée couverte par les mesures",
      "example": 10
     },
     "requetes": {
      "type": "object",
      "properties": {
       "total": {
        "type": "integer",
        "description": "Requêtes traitées sur la période"
       },
       "par_minute": {
        "type": "array",
        "description": "Une entrée par minute, de la plus ancienne à la minute en cours",
        "items": {
         "type": "object",
         "properties": {
          "minute": {
           "type": "string",
           "format": "date-time"
          },
          "total": {
           "type": "integer",
           "description": "Nombre total de résultats (avant pagination)"
          },
          "erreurs": {
           "type": "integer",
           "description": "Réponses 4xx et 5xx"
          }
         }
        }
       }
      }
     },
     "latence_ms": {
      "type": "object",
      "description": "Temps de traitement côté serveur, null sans requête",
      "properties": {
       "moyenne": {
        "type": "number",
        "nullable": true
       },
       "p50": {
        "type": "number",
        "nullable": true,
        "description": "Médiane (valeur approchée)"
       },
       "p95": {
        "type": "number",
        "nullable": true,
        "description": "95 % des requêtes vont plus vite (valeur approchée)"
       }
      }
     },
     "erreurs": {
      "type": "object",
      "properties": {
       "client": {
        "type": "integer",
        "description": "Réponses 4xx"
       },
       "serveur": {
        "type": "integer",
        "description": "Réponses 5xx"
       },
       "taux": {
        "type": "number",
        "description": "Part de réponses en erreur",
        "de 0 à 1": null
       }
      }
     },
     "modules": {
      "type": "array",
      "items": {
       "type": "object",
       "properties": {
        "id": {
         "type": "string",
         "example": "guildes",
         "description": "Identifiant numérique"
        },
        "nom": {
         "type": "string",
         "example": "Guildes",
         "description": "Nom de la guilde, sans mise en forme"
        },
        "etat": {
         "type": "string",
         "enum": [
          "operationnel",
          "degrade",
          "panne"
         ]
        },
        "requetes": {
         "type": "integer",
         "nullable": true
        },
        "erreurs_serveur": {
         "type": "integer",
         "nullable": true
        },
        "latence_ms": {
         "type": "number",
         "nullable": true
        }
       }
      }
     },
     "disponible_depuis": {
      "type": "string",
      "format": "date-time",
      "description": "Dernier démarrage du service"
     },
     "mis_a_jour": {
      "type": "string",
      "format": "date-time",
      "description": "Date de la mesure"
     }
    }
   },
   "EtatServeur": {
    "type": "object",
    "properties": {
     "en_ligne": {
      "type": "integer",
      "description": "Nombre de joueurs connectés au réseau"
     },
     "serveurs": {
      "type": "object",
      "additionalProperties": {
       "type": "integer"
      },
      "description": "Joueurs connectés, par serveur du réseau"
     },
     "mis_a_jour": {
      "type": "string",
      "format": "date-time",
      "description": "Date de la mesure"
     }
    }
   },
   "JoueurEnLigne": {
    "type": "object",
    "properties": {
     "uuid": {
      "type": "string",
      "format": "uuid",
      "description": "UUID Minecraft"
     },
     "pseudo": {
      "type": "string",
      "description": "Pseudo Minecraft"
     },
     "serveur": {
      "type": "string",
      "description": "Serveur du réseau où se trouve le joueur"
     }
    }
   },
   "Niveau": {
    "type": "object",
    "properties": {
     "niveau": {
      "type": "integer",
      "description": "Niveau atteint"
     },
     "xp": {
      "type": "integer",
      "format": "int64",
      "description": "Expérience totale"
     }
    }
   },
   "Joueur": {
    "type": "object",
    "properties": {
     "uuid": {
      "type": "string",
      "format": "uuid",
      "description": "UUID Minecraft"
     },
     "pseudo": {
      "type": "string",
      "description": "Pseudo Minecraft"
     },
     "premiere_connexion": {
      "type": "string",
      "format": "date-time",
      "description": "Date de la première connexion"
     },
     "derniere_connexion": {
      "type": "string",
      "format": "date-time",
      "description": "Date de la dernière connexion"
     },
     "en_ligne": {
      "type": "boolean",
      "description": "Vrai si le joueur est connecté"
     },
     "niveau": {
      "$ref": "#/components/schemas/Niveau",
      "description": "Niveau et expérience du joueur"
     },
     "guilde": {
      "nullable": true,
      "type": "object",
      "properties": {
       "id": {
        "type": "integer",
        "format": "int64",
        "description": "Identifiant numérique"
       },
       "nom": {
        "type": "string",
        "description": "Nom de la guilde, sans mise en forme"
       },
       "role": {
        "type": "string",
        "enum": [
         "chef",
         "officier",
         "membre",
         "recrue"
        ],
        "description": "Rang dans la guilde : chef, officier, membre ou recrue"
       }
      },
      "description": "Guilde du joueur, ou null s'il n'en a pas"
     }
    }
   },
   "EntreeClassementJoueur": {
    "type": "object",
    "properties": {
     "rang": {
      "type": "integer",
      "description": "Position dans le classement, à partir de 1"
     },
     "niveau": {
      "type": "integer",
      "description": "Niveau (classement des niveaux uniquement)."
     },
     "uuid": {
      "type": "string",
      "format": "uuid",
      "description": "UUID Minecraft"
     },
     "pseudo": {
      "type": "string",
      "description": "Pseudo Minecraft"
     },
     "valeur": {
      "type": "number",
      "description": "XP ou solde selon le classement"
     }
    }
   },
   "PageClassementJoueurs": {
    "type": "object",
    "properties": {
     "total": {
      "type": "integer",
      "description": "Nombre total de résultats (avant pagination)"
     },
     "monnaie": {
      "type": "string",
      "description": "Monnaie utilisée (classement d'argent uniquement)."
     },
     "joueurs": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/EntreeClassementJoueur"
      }
     }
    }
   },
   "Guilde": {
    "type": "object",
    "properties": {
     "id": {
      "type": "integer",
      "format": "int64",
      "description": "Identifiant numérique"
     },
     "nom": {
      "type": "string",
      "description": "Texte visible",
      "sans mise en forme.": null,
      "example": "NalyoraDev"
     },
     "nom_mini_message": {
      "type": "string",
      "description": "Nom avec sa mise en forme MiniMessage."
     },
     "palier": {
      "type": "integer",
      "minimum": 1,
      "maximum": 10,
      "description": "Palier de la guilde, de 1 à 10"
     },
     "xp": {
      "type": "integer",
      "format": "int64",
      "description": "Expérience totale"
     },
     "points_saison": {
      "type": "integer",
      "format": "int64",
      "description": "Points de la saison en cours"
     },
     "banque": {
      "type": "number",
      "description": "Argent dans la banque de la guilde"
     },
     "membres": {
      "type": "integer",
      "description": "Nombre de membres"
     },
     "suspendue": {
      "type": "boolean",
      "description": "Vrai si l'entretien est impayé (home et bonus d'XP suspendus)"
     },
     "creee_le": {
      "type": "string",
      "format": "date-time",
      "description": "Date de création"
     }
    }
   },
   "MembreGuilde": {
    "type": "object",
    "properties": {
     "uuid": {
      "type": "string",
      "format": "uuid",
      "description": "UUID Minecraft"
     },
     "pseudo": {
      "type": "string",
      "description": "Pseudo Minecraft"
     },
     "role": {
      "type": "string",
      "enum": [
       "chef",
       "officier",
       "membre",
       "recrue"
      ],
      "description": "Rang dans la guilde : chef, officier, membre ou recrue"
     },
     "contribution_saison": {
      "type": "integer",
      "format": "int64",
      "description": "Contribution du membre à la saison"
     },
     "rejoint_le": {
      "type": "string",
      "format": "date-time",
      "description": "Date d'arrivée dans la guilde"
     }
    }
   },
   "Annonce": {
    "type": "object",
    "properties": {
     "id": {
      "type": "integer",
      "format": "int64",
      "description": "Identifiant numérique"
     },
     "objet": {
      "type": "string",
      "description": "Nom de l'objet en français."
     },
     "prix": {
      "type": "number",
      "description": "Prix demandé"
     },
     "vendeur": {
      "type": "object",
      "properties": {
       "uuid": {
        "type": "string",
        "format": "uuid",
        "description": "UUID Minecraft"
       },
       "pseudo": {
        "type": "string",
        "description": "Pseudo Minecraft"
       }
      },
      "description": "Vendeur de l'annonce"
     },
     "creee_le": {
      "type": "string",
      "format": "date-time",
      "description": "Date de création"
     },
     "expire_le": {
      "type": "string",
      "format": "date-time",
      "description": "Date de fin de l'annonce"
     }
    }
   }
  }
 }
}