Référence de l'API
Cette page liste toutes les routes HTTP du backend. Le tableau est généré à la construction de la documentation en lisant backend/src/app.ts et chaque fichier *.routes.ts : méthode, chemin complet, accès requis, middlewares de contrôle et résumé OpenAPI. Les règles métier, les corps de requête et les erreurs de chaque route sont détaillés dans les pages Modules métier.
Swagger UI
Le serveur publie une interface Swagger sur /api/docs, par exemple http://localhost:2053/api/docs en local. La spécification OpenAPI 3.0 est construite au démarrage par swagger-jsdoc à partir des blocs @openapi placés au-dessus de chaque route (backend/src/config/swagger.config.ts). Elle lit les fichiers src/api/**/*.routes.ts en développement et dist/src/api/**/*.routes.js après compilation.
| Élément | Valeur |
|---|---|
| Titre | BlockLucky EtherBay API, version 1.0.0 |
| Serveur déclaré | http://localhost:<PORT> uniquement |
| Sécurité | schéma bearerAuth (HTTP, bearer, format JWT) appliqué par défaut à toutes les opérations |
| Chemins documentés | sous le préfixe /api/... non versionné |
Les blocs OpenAPI ne contiennent qu'une étiquette et un résumé : ni paramètres, ni corps, ni réponses. Swagger UI sert donc d'index cliquable et de console pour envoyer une requête avec un jeton (bouton Authorize), pas de contrat d'interface. La route /api/docs est servie dans tous les environnements, production comprise, et passe par le rate limiting global.
Préfixes
| Préfixe | Usage |
|---|---|
/api/v1/... |
préfixe recommandé pour tout nouveau client |
/api/... |
même routeur, monté une seconde fois pour compatibilité ; c'est celui qu'utilisent aujourd'hui le web (NEXT_PUBLIC_API_URL=http://localhost:2053/api dans la stack Docker) et les blocs OpenAPI |
| racine | sondes /health*, /api/config et /metrics, hors routeur versionné |
Les deux préfixes partagent les mêmes compteurs de rate limiting et les mêmes clés d'idempotence par utilisateur, mais pas le même chemin : une clé d'idempotence utilisée sur /api/lottery/buy n'est pas reconnue sur /api/v1/lottery/buy.
Authentification
Les routes protégées attendent un jeton de session dans l'en-tête Authorization :
GET /api/v1/user/profile HTTP/1.1
Host: localhost:2053
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIwMTlhN2MzZS...Le jeton s'obtient par POST /auth/login puis POST /auth/2fa/verify (voir Authentification). Il n'y a ni cookie de session, ni jeton de rafraîchissement : à l'expiration (12 heures par défaut), le client doit se reconnecter. Le préfixe Bearer est sensible à la casse.
| Colonne « Accès » du tableau | Signification |
|---|---|
public |
aucun jeton requis ; certaines routes l'exploitent s'il est fourni (optionalAuthenticate) |
connecté |
authenticate : jeton valide et non révoqué |
rôle ... |
authenticate puis requireRoles(...) : rôle vérifié dans le jeton et relu en base |
Idempotence
Cinq routes acceptent l'en-tête Idempotency-Key : POST /lottery/buy, POST /lottery/gift, POST /lottery/claim-prize, POST /marketplace/claim et POST /marketplace/scratch. Le middleware backend/src/middlewares/idempotency.middleware.ts protège contre le double clic et les nouvelles tentatives réseau d'une opération qui dépense des ethers ou des points.
POST /api/v1/lottery/buy HTTP/1.1
Authorization: Bearer eyJhbGciOi...
Content-Type: application/json
Idempotency-Key: 6b0f3c2e-9d41-4a7e-b5a8-1c2d3e4f5a6b
{"quantity":1}| Règle | Détail |
|---|---|
| Format | 8 à 128 caractères [A-Za-z0-9_-], sinon 400 En-tête Idempotency-Key invalide |
| Portée | clé Redis idempotency:<userId>:<méthode>:<chemin>:<clé> : propre à l'utilisateur, à la méthode et au chemin exact |
| Première requête | verrou __pending__ posé pour 60 secondes, puis la réponse est mémorisée 24 heures si son statut est inférieur à 500 |
| Requête identique en cours | 409 Une requête identique est déjà en cours de traitement avec Retry-After: 1 |
| Requête rejouée | réponse d'origine, même statut et même corps, avec l'en-tête Idempotent-Replayed: true |
| Réponse 5xx | la clé est effacée : la requête peut être retentée avec la même clé |
| Sans en-tête | aucun contrôle |
Le corps de la requête ne fait pas partie de la clé : la même clé avec un autre corps rejoue la première réponse. Une erreur 400 ou 409 est mémorisée comme un succès ; après une erreur de validation, il faut une nouvelle clé. Sans Redis, les clés sont gardées dans la mémoire du process et ne protègent plus contre un rejeu reçu par une autre instance.
Limites de débit
| Limiteur | Portée | Limite |
|---|---|---|
globalRateLimiter |
toutes les routes après la maintenance, sauf sondes, /api/config et /metrics |
300 requêtes par 15 minutes et par IP |
authRateLimiter |
/auth/login, /signup, /signin, /password/forgot, /password/reset, /password/change, /email/change, /email/confirm, /oauth/google, /2fa/verify, /2fa/disable |
30 requêtes par 10 minutes et par IP pour l'ensemble de ces routes, en plus de la limite globale |
identityUploadRateLimiter |
POST /user/identity |
10 requêtes par heure et par IP, en plus de la limite globale |
supportRateLimiter |
POST /user/support |
5 messages par heure et par compte (par IP à défaut), en plus de la limite globale |
Les réponses portent les en-têtes RateLimit et RateLimit-Policy (format draft-7 de l'IETF), exposés aux navigateurs par CORS. Au-delà de la limite, la réponse est un 429 au format habituel, par exemple { "success": false, "message": "Trop de requêtes depuis cette adresse IP, veuillez réessayer plus tard." }. Les compteurs sont dans Redis (ratelimit:global:, ratelimit:auth:, ratelimit:identity: et ratelimit:support:) ; si Redis répond en erreur, la requête passe (passOnStoreError). Derrière un proxy, TRUST_PROXY doit être réglé, sinon tous les clients partagent l'IP du proxy.
Corps et formats
Les corps sont en JSON (Content-Type: application/json) ou en formulaire URL-encodé, 1 Mo au plus, sauf POST /user/identity, qui accepte 12 Mo de JSON pour les deux photos encodées en base64. Un JSON mal formé renvoie 400 Corps de requête JSON invalide, un corps trop gros 413 Corps de requête trop volumineux. Les réponses suivent le format décrit dans Réponses et erreurs, sauf trois exceptions : les sondes /health*, les métadonnées POAP GET /lottery/poap/:file et /metrics.
Lire les résumés OpenAPI
La colonne « Résumé » du tableau reprend le summary du bloc @openapi placé au-dessus de chaque route, celui qu'affiche aussi Swagger. Les résumés ont été alignés sur le comportement réel du code. Quelques nuances ne tiennent pas dans une ligne : elles sont détaillées dans les pages de modules.
| Route | Nuance |
|---|---|
POST /auth/login |
La déclaration de majorité est déclarative ; l'achat exige en plus la vérification d'âge par pièce d'identité. |
POST /auth/2fa/verify |
Un code d'application n'est accepté qu'avec le loginTicket reçu après le premier facteur ou avec une session du compte. |
POST /auth/oauth/google |
Répond 503 tant que GOOGLE_CLIENT_IDS est vide, ce qui est le cas par défaut. |
POST /lottery/gift |
Le destinataire est désigné par son email, mais aucun email ne lui est envoyé ; seul l'âge de l'expéditeur est vérifié. |
POST /lottery/refund |
En mode simulé, seul le statut du tour change ; le remboursement réel n'existe qu'en mode onchain. |
GET /lottery/my-tickets |
En mode simulé, les badges POAP sont fictifs. |
POST /partners/offers |
La date d'expiration est enregistrée dans Redis mais n'est jamais appliquée. |
GET /user/notifications |
Les trois notifications renvoyées sont codées en dur. |
GET /analytics/dashboard |
En l'absence de données, la répartition par âge affichée est fictive. |
POST /admin/treasury/withdraw |
Le montant amountEth envoyé est ignoré : toute la commission accumulée est versée. |
GET /admin/reports/export |
Le format pdf produit en réalité un fichier JSON. |
Routes
Chaque route est servie sous /api/v1 et, pour compatibilité, sous /api. Les sondes et métriques du module système sont à la racine du serveur.
L'API expose 70 routes réparties en 9 modules.
Système
Fichier source : backend/src/api/system/system.routes.ts
| Méthode | Chemin | Accès | Contrôles | Résumé (OpenAPI) |
|---|---|---|---|---|
GET |
/health |
public | - | Vérifier que l'API répond, avec l'état du disjoncteur du Smart Contract |
GET |
/health/live |
public | - | Sonde de vivacité (le process répond, aucune dépendance testée) |
GET |
/health/ready |
public | - | Sonde de disponibilité (PostgreSQL joignable, serveur non en cours d'arrêt) |
GET |
/health/deep |
public | - | Diagnostic détaillé de chaque dépendance avec latence (mis en cache 5 secondes) |
GET |
/api/config |
public | - | Configuration runtime pour les clients (version mobile minimale, mode maintenance) |
Authentification
Fichier source : backend/src/api/auth/auth.routes.ts
| Méthode | Chemin | Accès | Contrôles | Résumé (OpenAPI) |
|---|---|---|---|---|
POST |
/api/v1/auth/signup |
public | authRateLimiter, validation signupSchema |
Créer un compte avec email et mot de passe, puis recevoir un code à 6 chiffres par email (le compte est créé à la vérification du code via /auth/2fa/verify) |
POST |
/api/v1/auth/signin |
public | authRateLimiter, validation signinSchema |
Connexion par email et mot de passe, avec étape 2FA si elle est activée sur le compte |
POST |
/api/v1/auth/password/forgot |
public | authRateLimiter, validation forgotPasswordSchema |
Demander un code de réinitialisation du mot de passe par email (réponse identique que le compte existe ou non) |
POST |
/api/v1/auth/password/reset |
public | authRateLimiter, validation resetPasswordSchema |
Définir un nouveau mot de passe avec le code reçu par email et révoquer toutes les sessions du compte |
POST |
/api/v1/auth/password/change |
connecté | authRateLimiter, validation changePasswordSchema |
Modifier son mot de passe (mot de passe actuel exigé s'il en existe un, sinon définition d'un premier mot de passe), révoquer toutes les sessions et recevoir une nouvelle session |
POST |
/api/v1/auth/email/change |
connecté | authRateLimiter, validation emailChangeRequestSchema |
Demander le changement d'adresse email (mot de passe exigé s'il en existe un) et recevoir un code à 6 chiffres sur la nouvelle adresse |
POST |
/api/v1/auth/email/confirm |
connecté | authRateLimiter, validation emailChangeConfirmSchema |
Confirmer la nouvelle adresse email avec le code reçu, puis prévenir l'ancienne adresse |
POST |
/api/v1/auth/oauth/google |
public | authRateLimiter, validation googleOAuthSchema |
Connexion ou inscription avec un jeton d'identité Google vérifié côté serveur |
GET |
/api/v1/auth/onboarding |
public | - | Récupérer les écrans illustrés de l'onboarding interactif |
POST |
/api/v1/auth/login |
public | authRateLimiter, validation socialLoginSchema |
Connexion sans mot de passe avec déclaration de majorité (18+), avec envoi d'un code à 6 chiffres par email |
POST |
/api/v1/auth/2fa/setup |
connecté | validation setup2FASchema |
Initialiser la configuration 2FA (QR Code Google Authenticator ou Email OTP) |
POST |
/api/v1/auth/2fa/verify |
public | authRateLimiter, optionalAuthenticate, validation verify2FASchema |
Vérifier le code OTP à 6 chiffres (Email, ou App avec le loginTicket délivré après le premier facteur ou une session authentifiée) |
POST |
/api/v1/auth/logout |
connecté | validation logoutSchema |
Révoquer la session courante, ou toutes les sessions du compte avec allDevices=true |
POST |
/api/v1/auth/2fa/disable |
connecté | authRateLimiter, validation disable2FASchema |
Désactiver la double authentification 2FA |
Loterie
Fichier source : backend/src/api/lottery/lottery.routes.ts
| Méthode | Chemin | Accès | Contrôles | Résumé (OpenAPI) |
|---|---|---|---|---|
GET |
/api/v1/lottery/status |
public | - | Obtenir le compte à rebours, la jauge de progression vers le plafond du tour, les paliers et la preuve Chainlink VRF |
GET |
/api/v1/lottery/transparency-charter |
public | - | Obtenir la charte de transparence du Smart Contract vulgarisée |
GET |
/api/v1/lottery/leaderboard |
public | - | Obtenir le classement anonymisé des meilleurs ambassadeurs d'EtherBay |
GET |
/api/v1/lottery/poap/:file |
public | - | Métadonnées ERC-721 (roundId.json) et visuel (roundId.svg) du badge POAP d'un tour |
POST |
/api/v1/lottery/buy |
connecté | requireAgeVerification, idempotence, validation buyTicketSchema |
Acheter son ticket unique du grand tirage en 1 clic (âge vérifié requis), transaction signée par le portefeuille intégré du citoyen, et gagner 50 EtherPoints |
POST |
/api/v1/lottery/gift |
connecté | requireAgeVerification, idempotence, validation giftTicketSchema |
Offrir un ticket à un proche désigné par son email, acheté pour son portefeuille intégré (âge vérifié requis, un ticket par participant) |
GET |
/api/v1/lottery/my-tickets |
connecté | - | Historique des tickets (liens vers l'explorateur de blocs si EXPLORER_URL est défini) et galerie des badges POAP |
GET |
/api/v1/lottery/wallet |
connecté | - | Portefeuille Ethereum intégré du citoyen (adresse, solde en ethers fictifs, dotation de bienvenue) |
POST |
/api/v1/lottery/claim-prize |
connecté | idempotence, validation claimPrizeSchema |
Retirer la cagnotte gagnée depuis le Smart Contract vers le portefeuille du gagnant |
POST |
/api/v1/lottery/draw |
rôle ADMIN | validation triggerDrawSchema |
Déclencher le tirage au sort certifié Chainlink VRF (Admin) |
POST |
/api/v1/lottery/refund |
rôle ADMIN | - | Annuler le tour en cours ; en mode onchain, chaque mise devient remboursable dans le Smart Contract et est réclamée automatiquement |
Boutique et récompenses
Fichier source : backend/src/api/marketplace/marketplace.routes.ts
| Méthode | Chemin | Accès | Contrôles | Résumé (OpenAPI) |
|---|---|---|---|---|
GET |
/api/v1/marketplace/catalog |
public | - | Consulter le catalogue des récompenses et commerçants partenaires d'EtherBay |
GET |
/api/v1/marketplace/rewards/:id |
public | - | Obtenir le détail d'une récompense et sa jauge de stock restant |
GET |
/api/v1/marketplace/points |
connecté | - | Obtenir le compteur dynamique d'EtherPoints et l'historique du Ledger |
POST |
/api/v1/marketplace/claim |
connecté | requireAgeVerification, idempotence, validation claimRewardSchema |
Échanger ses EtherPoints contre une carte à gratter virtuelle (Scratch Card) |
POST |
/api/v1/marketplace/scratch |
connecté | requireAgeVerification, idempotence, validation scratchTicketSchema |
Acheter un ticket à gratter en EtherPoints (violet ou lucky, âge vérifié requis) qui attribue au hasard une récompense partenaire en stock |
GET |
/api/v1/marketplace/my-codes |
connecté | - | Obtenir son Wallet de Récompenses (Mes Codes Promos + QR Codes à scanner) |
POST |
/api/v1/marketplace/redeem |
rôle PARTNER, ADMIN | validation usePromoCodeSchema |
Valider un QR Code / Code Promo client en magasin (Partenaire ou Admin) |
Partenaires
Fichier source : backend/src/api/partners/partners.routes.ts
| Méthode | Chemin | Accès | Contrôles | Résumé (OpenAPI) |
|---|---|---|---|---|
GET |
/api/v1/partners/ |
public | - | Lister toutes les entreprises locales partenaires d'EtherBay |
POST |
/api/v1/partners/ |
rôle PARTNER, ADMIN | validation createPartnerSchema |
Enregistrer une nouvelle entreprise partenaire locale |
POST |
/api/v1/partners/offers |
rôle PARTNER, ADMIN | validation createRewardOfferSchema |
Créer une offre de récompense (titre, coût en EtherPoints, stock, date d'expiration indicative) |
POST |
/api/v1/partners/codes/upload |
rôle PARTNER, ADMIN | validation uploadCodesBatchSchema |
Importer un lot de codes promos uniques, jusqu'à 5 000 (CSV ou tableau JSON) |
GET |
/api/v1/partners/:partnerId/consumption |
rôle PARTNER, ADMIN | - | Indicateur circulaire de consommation des codes promos réclamés par les habitants |
Utilisateur et RGPD
Fichier source : backend/src/api/user/user.routes.ts
| Méthode | Chemin | Accès | Contrôles | Résumé (OpenAPI) |
|---|---|---|---|---|
GET |
/api/v1/user/profile |
connecté | - | Obtenir le profil complet du citoyen connecté |
PATCH |
/api/v1/user/profile |
connecté | validation updateProfileSchema |
Modifier son prénom et son nom (50 caractères au plus, lettres, espaces, traits d'union et apostrophes ; une chaîne vide efface le champ) |
POST |
/api/v1/user/support |
connecté | supportRateLimiter, validation supportRequestSchema |
Envoyer un message au support de la Ville d'EtherBay (5 messages par heure au plus) |
POST |
/api/v1/user/identity |
connecté | identityUploadRateLimiter, identityUploadJsonParser, validation submitIdentitySchema |
Envoyer le recto et le verso de sa pièce d'identité (JPEG ou PNG en base64, 4 Mo au plus chacun) pour la vérification d'âge par la Mairie |
GET |
/api/v1/user/identity |
connecté | - | Consulter le statut de sa vérification d'âge (date d'envoi, date de décision et motif d'un refus) |
GET |
/api/v1/user/referrals |
connecté | - | Obtenir son lien de parrainage unique et les boutons de partage rapide (SMS, WhatsApp, Twitter) |
GET |
/api/v1/user/quests |
connecté | - | Obtenir la liste des quêtes sociales (Tasks) disponibles |
POST |
/api/v1/user/quests/complete |
connecté | validation completeSocialQuestSchema |
Valider une quête sociale et gagner des EtherPoints bonus |
PUT |
/api/v1/user/preferences |
connecté | validation updatePreferencesSchema |
Modifier le thème (clair, sombre ou système), la langue (FR/EN), l'interrupteur général des notifications et leurs catégories (rappels de tirage, résultats, récompenses, parrainage) |
GET |
/api/v1/user/notifications |
connecté | - | Consulter le centre de notifications (contenu de démonstration, aucun envoi push), sans les catégories désactivées dans les préférences |
GET |
/api/v1/user/gdpr/export |
connecté | - | Exporter l'intégralité de ses données personnelles au format JSON (RGPD) |
POST |
/api/v1/user/gdpr/delete-request |
connecté | - | Demander la suppression/anonymisation de son compte avec envoi d'email de confirmation |
POST |
/api/v1/user/gdpr/confirm-delete |
public | validation confirmGdprDeletionSchema |
Confirmer définitivement la suppression/anonymisation RGPD via le jeton reçu par email |
Analytique
Fichier source : backend/src/api/analytics/analytics.routes.ts
| Méthode | Chemin | Accès | Contrôles | Résumé (OpenAPI) |
|---|---|---|---|---|
POST |
/api/v1/analytics/track |
public | optionalAuthenticate, validation trackEventSchema |
Enregistrer un événement analytique ou un tag d'acquisition UTM (Twitter, Instagram...) |
GET |
/api/v1/analytics/dashboard |
rôle ADMIN | - | Obtenir la répartition par tranche d'âge et les courbes d'acquisition UTM (Mairie) |
Administration Mairie
Fichier source : backend/src/api/admin/admin.routes.ts
| Méthode | Chemin | Accès | Contrôles | Résumé (OpenAPI) |
|---|---|---|---|---|
GET |
/api/v1/admin/dashboard |
rôle ADMIN | - | Tableau de Bord Central Mairie (KPIs globaux, Cagnotte, Tickets vendus, Démographie) |
POST |
/api/v1/admin/circuit-breaker |
rôle ADMIN | validation circuitBreakerSchema |
Interrupteur d'Urgence (Circuit Breaker) pour mettre en pause ou reprendre le Smart Contract |
POST |
/api/v1/admin/treasury/withdraw |
rôle ADMIN | validation treasuryWithdrawalSchema |
Reverser toute la commission accumulée dans le Smart Contract vers l'adresse de trésorerie de la Mairie |
PATCH |
/api/v1/admin/partners/:partnerId/status |
rôle ADMIN | validation approvePartnerSchema |
Approuver ou suspendre une entreprise partenaire locale |
GET |
/api/v1/admin/reports/export |
rôle ADMIN | - | Générer un rapport analytique et comptable (CSV, ou export JSON pour le format pdf) |
GET |
/api/v1/admin/identity-verifications |
rôle ADMIN | validation listIdentityVerificationsSchema |
Lister les demandes de vérification d'âge par statut (PENDING par défaut), paginées |
GET |
/api/v1/admin/identity-verifications/:id |
rôle ADMIN | validation identityVerificationIdSchema |
Consulter une demande de vérification d'âge avec le recto et le verso déchiffrés tant qu'elle est en attente (consultation journalisée dans l'audit) |
POST |
/api/v1/admin/identity-verifications/:id/decision |
rôle ADMIN | validation identityDecisionSchema |
Approuver ou refuser (motif obligatoire) une vérification d'âge, effacer les images, prévenir le citoyen par email et tracer la décision |
GET |
/api/v1/admin/accounts |
rôle ADMIN | validation listStaffAccountsSchema |
Lister les comptes Mairie et partenaires (filtre par rôle, recherche par email ou nom, paginé) avec leurs établissements rattachés |
POST |
/api/v1/admin/accounts |
rôle ADMIN | validation createStaffAccountSchema |
Créer un compte Mairie ou partenaire, ou attribuer ce rôle à un compte existant, puis envoyer l'invitation par email (action journalisée) |
PATCH |
/api/v1/admin/accounts/:id/role |
rôle ADMIN | validation updateStaffRoleSchema |
Modifier ou retirer le rôle d'un compte (refus sur son propre compte et sur le dernier compte Mairie, sessions révoquées, action journalisée) |
GET |
/api/v1/admin/audit-logs |
rôle ADMIN | - | Tableau chronologique de traçabilité des actions effectuées par les administrateurs Mairie |
Webhooks
Fichier source : backend/src/api/webhooks/webhooks.routes.ts
| Méthode | Chemin | Accès | Contrôles | Résumé (OpenAPI) |
|---|---|---|---|---|
POST |
/api/v1/webhooks/blockchain |
public | requireWebhookSignature, validation blockchainWebhookSchema |
Webhook signé d'indexation des événements, réservé au mode simulé (409 en mode onchain) |