API HealthLens

Bienvenue dans la documentation de l'API HealthLens. Cette API REST permet de gérer l'authentification des utilisateurs, les analyses de santé et les abonnements.

URL de base

https://healthlens.jh-it.be/api

Headers requis

Header Valeur
Content-Type application/json
Accept application/json
Authorization Bearer {token} (routes protégées)

Authentification

L'API utilise Laravel Sanctum pour l'authentification. Après connexion, vous recevez un token Bearer à inclure dans le header Authorization pour toutes les requêtes authentifiées.

Note: Les tokens n'expirent pas automatiquement mais peuvent être révoqués lors de la déconnexion ou du refresh.

Gestion des erreurs

Code Description
400 Requête invalide
401 Non authentifié
403 Accès refusé (quota atteint, non autorisé)
404 Ressource non trouvée
422 Erreur de validation
429 Trop de requêtes (rate limit)

Rate Limiting

Endpoint Limite
API général 60 requêtes/minute
Authentification 30 requêtes/minute
Scans 30 requêtes/minute
Subscription 10 requêtes/minute

Authentification

POST /api/auth/register

Créer un nouveau compte utilisateur.

Body (JSON)

{
    "first_name": "Jean",
    "last_name": "Dupont",
    "email": "jean@exemple.com",
    "password": "MotDePasse123!",
    "password_confirmation": "MotDePasse123!"
}

Réponse (201)

{
    "message": "Compte créé avec succès.",
    "user": {
        "id": 1,
        "first_name": "Jean",
        "last_name": "Dupont",
        "email": "jean@exemple.com"
    },
    "token": "1|abc123..."
}
POST /api/auth/login

Connecter un utilisateur existant.

Body (JSON)

{
    "email": "jean@exemple.com",
    "password": "MotDePasse123!",
    "device_name": "iPhone 15 Pro"
}

Réponse (200)

{
    "message": "Connexion réussie.",
    "user": {
        "id": 1,
        "first_name": "Jean",
        "last_name": "Dupont",
        "email": "jean@exemple.com"
    },
    "token": "2|xyz789..."
}
POST /api/auth/logout Auth Required

Déconnecter l'utilisateur (révoque le token actuel).

Réponse (200)

{
    "message": "Déconnexion réussie."
}
POST /api/auth/refresh Auth Required

Obtenir un nouveau token (révoque l'ancien).

Réponse (200)

{
    "message": "Token renouvelé.",
    "token": "3|newtoken..."
}
GET /api/auth/user Auth Required

Récupérer les informations de l'utilisateur connecté.

Réponse (200)

{
    "user": {
        "id": 1,
        "first_name": "Jean",
        "last_name": "Dupont",
        "email": "jean@exemple.com",
        "email_verified_at": "2024-01-15T10:30:00Z"
    },
    "subscription": {
        "plan_type": "monthly",
        "status": "active",
        "expires_at": "2024-02-15T10:30:00Z"
    },
    "scans_remaining": null,
    "can_perform_scan": true
}
POST /api/auth/forgot-password

Demander un lien de réinitialisation de mot de passe.

Body (JSON)

{
    "email": "jean@exemple.com"
}

Réponse (200)

{
    "message": "Lien de réinitialisation envoyé."
}
POST /api/auth/reset-password

Réinitialiser le mot de passe avec le token reçu par email.

Body (JSON)

{
    "email": "jean@exemple.com",
    "token": "reset-token-from-email",
    "password": "NouveauMotDePasse123!",
    "password_confirmation": "NouveauMotDePasse123!"
}

Réponse (200)

{
    "message": "Mot de passe réinitialisé avec succès."
}

Profil Utilisateur

GET /api/user/profile Auth Required

Récupérer le profil médical de l'utilisateur (données décryptées).

Réponse (200)

{
    "profile": {
        "date_of_birth": "1990-05-15",
        "gender": "male",
        "blood_type": "A+",
        "allergies": ["pollen", "arachides"],
        "medications": ["vitamine D"],
        "medical_conditions": []
    }
}
PUT /api/user/profile Auth Required

Mettre à jour le profil médical (données cryptées côté serveur).

Body (JSON)

{
    "date_of_birth": "1990-05-15",
    "gender": "male",
    "blood_type": "A+",
    "allergies": ["pollen"],
    "medications": [],
    "medical_conditions": []
}

Réponse (200)

{
    "message": "Profil mis à jour.",
    "profile": { ... }
}
DELETE /api/user/account Auth Required

Supprimer le compte utilisateur (soft delete avec anonymisation des données).

Réponse (200)

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

Note: Cette action est irréversible. Les données personnelles sont anonymisées conformément au RGPD.

Scans

GET /api/scans Auth Required

Lister les scans de l'utilisateur (paginés).

Query Parameters

Paramètre Type Description
page integer Numéro de page (défaut: 1)
per_page integer Éléments par page (défaut: 15, max: 50)
scan_type string Filtrer par type: skin, eye, symptoms

Réponse (200)

{
    "data": [
        {
            "id": 1,
            "scan_type": "skin",
            "risk_level": "low",
            "created_at": "2024-01-15T14:30:00Z"
        }
    ],
    "meta": {
        "current_page": 1,
        "last_page": 3,
        "per_page": 15,
        "total": 42
    }
}
POST /api/scans Auth Required

Créer un nouveau scan (données cryptées côté serveur).

Body (JSON)

{
    "scan_type": "skin",
    "risk_level": "low",
    "data": {
        "result": "Analyse normale",
        "notes": "Aucune anomalie détectée",
        "image_analysis": { ... }
    }
}

Valeurs possibles

Champ Valeurs
scan_type skin, eye, symptoms
risk_level low, moderate, high

Réponse (201)

{
    "message": "Scan enregistré avec succès.",
    "scan": {
        "id": 5,
        "scan_type": "skin",
        "risk_level": "low",
        "created_at": "2024-01-15T14:30:00Z"
    },
    "scans_remaining": 2
}

Quota: Les utilisateurs gratuits sont limités à 3 scans/mois. Retourne 403 si le quota est atteint.

GET /api/scans/{id} Auth Required

Récupérer les détails d'un scan (avec données décryptées).

Réponse (200)

{
    "scan": {
        "id": 1,
        "scan_type": "skin",
        "risk_level": "low",
        "created_at": "2024-01-15T14:30:00Z",
        "data": {
            "result": "Analyse normale",
            "notes": "Aucune anomalie détectée"
        }
    }
}
DELETE /api/scans/{id} Auth Required

Supprimer un scan.

Réponse (200)

{
    "message": "Scan supprimé avec succès."
}
GET /api/scans/stats Auth Required

Statistiques agrégées des scans (données non sensibles).

Réponse (200)

{
    "total_scans": 42,
    "scans_this_month": 5,
    "by_type": {
        "skin": 20,
        "eye": 15,
        "symptoms": 7
    },
    "by_risk_level": {
        "low": 35,
        "moderate": 5,
        "high": 2
    },
    "can_perform_scan": true,
    "scans_remaining": 2
}

Abonnements

GET /api/subscription Auth Required

Récupérer les informations d'abonnement de l'utilisateur.

Réponse (200)

{
    "subscription": {
        "plan_type": "monthly",
        "status": "active",
        "store_type": "google_play",
        "starts_at": "2024-01-15T10:30:00Z",
        "expires_at": "2024-02-15T10:30:00Z",
        "days_remaining": 25,
        "is_active": true
    },
    "available_plans": [
        {
            "type": "weekly",
            "price": 299,
            "currency": "EUR",
            "description": "Scans illimités pendant 7 jours"
        },
        {
            "type": "monthly",
            "price": 999,
            "currency": "EUR",
            "description": "Scans illimités pendant 30 jours"
        }
    ]
}
POST /api/subscription/verify Auth Required

Vérifier un achat effectué via Google Play ou App Store.

Body (JSON) - Google Play

{
    "store_type": "google_play",
    "product_id": "healthlens_monthly",
    "purchase_token": "token-from-google-play..."
}

Body (JSON) - App Store

{
    "store_type": "app_store",
    "receipt": "base64-encoded-receipt..."
}

Réponse (200)

{
    "message": "Abonnement activé avec succès.",
    "subscription": {
        "plan_type": "monthly",
        "status": "active",
        "expires_at": "2024-02-15T10:30:00Z"
    }
}

Erreur (400): Si la vérification échoue, retourne un message d'erreur détaillant le problème (token invalide, achat déjà utilisé, etc.).