Documentation
Documentation complète pour l'intégration Flutter
Toutes les requêtes API doivent inclure un token Bearer dans l'en-tête Authorization :
final response = await http.get(
Uri.parse('${baseUrl}/api/endpoint'),
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
},
);
Endpoint: /api/register
Corps de la requête:
{
"name": "John Doe",
"email": "john@example.com",
"password": "password123",
"password_confirmation": "password123",
"birth_date": "1990-01-01", // Requis
"phone": "+237600000000", // Optionnel
"address": "Yaoundé, Cameroun", // Optionnel
"speciality": "Cardiologie", // Optionnel
"medical_order_number": "12345" // Optionnel
}
Exemple de réponse:
{
"success": true,
"message": "Utilisateur créé avec succès",
"user": {
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "John Doe",
"email": "john@example.com",
"phone": "+237600000000",
"address": "Yaoundé, Cameroun",
"birth_date": "1990-01-01",
"speciality": "Cardiologie",
"medical_order_number": "12345",
"role": null,
"organization_id": null,
"has_used_trial": false,
"avatar": null,
"email_verified_at": null,
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T12:00:00.000000Z"
},
"token": "votre_token_d_acces"
}
Exemple d'intégration Flutter:
Future register({
required String name,
required String email,
required String password,
required String passwordConfirmation,
String? birthDate,
String? phone,
String? address,
String? speciality,
String? medicalOrderNumber,
}) async {
final response = await http.post(
Uri.parse('${baseUrl}/api/register'),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: jsonEncode({
'name': name,
'email': email,
'password': password,
'password_confirmation': passwordConfirmation,
if (birthDate != null) 'birth_date': birthDate,
if (phone != null) 'phone': phone,
if (address != null) 'address': address,
if (speciality != null) 'speciality': speciality,
if (medicalOrderNumber != null) 'medical_order_number': medicalOrderNumber,
}),
);
if (response.statusCode == 201) {
final data = jsonDecode(response.body);
await storage.write(key: 'token', value: data['token']);
return User.fromJson(data['user']);
}
final errorData = jsonDecode(response.body);
throw Exception(errorData['message'] ?? 'Erreur lors de l\'inscription');
}
class User {
final int id;
final String uuid;
final String name;
final String email;
final String? phone;
final String? address;
final String? speciality;
final String? medicalOrderNumber;
final DateTime? birthDate;
final DateTime? emailVerifiedAt;
final String? avatar;
final String? role; // 'owner', 'doctor', 'admin'
final int? organizationId;
final bool hasUsedTrial;
final DateTime createdAt;
final DateTime updatedAt;
User({
required this.id,
required this.uuid,
required this.name,
required this.email,
this.phone,
this.address,
this.speciality,
this.medicalOrderNumber,
this.birthDate,
this.emailVerifiedAt,
this.avatar,
this.role,
this.organizationId,
this.hasUsedTrial = false,
required this.createdAt,
required this.updatedAt,
});
factory User.fromJson(Map json) {
return User(
id: json['id'],
uuid: json['uuid'] ?? '',
name: json['name'],
email: json['email'],
phone: json['phone'],
address: json['address'],
speciality: json['speciality'],
medicalOrderNumber: json['medical_order_number'],
birthDate: json['birth_date'] != null
? DateTime.parse(json['birth_date'])
: null,
emailVerifiedAt: json['email_verified_at'] != null
? DateTime.parse(json['email_verified_at'])
: null,
avatar: json['avatar'],
role: json['role'],
organizationId: json['organization_id'],
hasUsedTrial: json['has_used_trial'] ?? false,
createdAt: DateTime.parse(json['created_at']),
updatedAt: DateTime.parse(json['updated_at']),
);
}
Map toJson() {
return {
'id': id,
'uuid': uuid,
'name': name,
'email': email,
'phone': phone,
'address': address,
'speciality': speciality,
'medical_order_number': medicalOrderNumber,
'birth_date': birthDate?.toIso8601String(),
'email_verified_at': emailVerifiedAt?.toIso8601String(),
'avatar': avatar,
'role': role,
'organization_id': organizationId,
'has_used_trial': hasUsedTrial,
'created_at': createdAt.toIso8601String(),
'updated_at': updatedAt.toIso8601String(),
};
}
}
class UserProvider extends ChangeNotifier {
User? _user;
final storage = const FlutterSecureStorage();
User? get user => _user;
Future loadUser() async {
final token = await storage.read(key: 'token');
if (token == null) return;
try {
final response = await http.get(
Uri.parse('${baseUrl}/api/me'),
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
_user = User.fromJson(data['user']);
notifyListeners();
}
} catch (e) {
await storage.delete(key: 'token');
}
}
Future updateProfile({
String? name,
String? phone,
String? address,
String? birthDate,
String? speciality,
String? medicalOrderNumber,
}) async {
final token = await storage.read(key: 'token');
if (token == null) return;
final response = await http.put(
Uri.parse('${baseUrl}/api/user/profile'),
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: jsonEncode({
if (name != null) 'name': name,
if (phone != null) 'phone': phone,
if (address != null) 'address': address,
if (birthDate != null) 'birth_date': birthDate,
if (speciality != null) 'speciality': speciality,
if (medicalOrderNumber != null) 'medical_order_number': medicalOrderNumber,
}),
);
if (response.statusCode == 200) {
_user = User.fromJson(jsonDecode(response.body));
notifyListeners();
} else {
throw Exception('Échec de la mise à jour du profil');
}
}
}
Endpoint: /api/user
Note: Pour obtenir l'utilisateur avec son organisation et son rôle, utilisez plutôt /api/me.
Exemple de réponse:
{
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "John Doe",
"email": "john@example.com",
"role": "owner",
"organization_id": 5,
"has_used_trial": false,
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T12:00:00.000000Z"
}
Endpoint: /api/auth/refresh
Permet de rafraîchir le token d'authentification sans nécessiter une nouvelle connexion.
Exemple de réponse:
{
"token": "nouveau_token_d_acces"
}
Endpoint: /api/login
Corps de la requête:
{
"email": "john@example.com",
"password": "password123"
}
Exemple de réponse:
{
"success": true,
"message": "Connexion réussie",
"token": "votre_token_d_acces",
"user": {
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "John Doe",
"email": "john@example.com",
"role": "owner",
"organization_id": 5,
"has_used_trial": false,
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T12:00:00.000000Z"
}
}
Exemple d'intégration Flutter:
Future login({
required String email,
required String password,
}) async {
final response = await http.post(
Uri.parse('${baseUrl}/api/login'),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: jsonEncode({
'email': email,
'password': password,
}),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
// Sauvegarder le token
await storage.write(key: 'token', value: data['token']);
return User.fromJson(data['user']);
}
final errorData = jsonDecode(response.body);
throw Exception(errorData['message'] ?? 'Erreur lors de la connexion');
}
Endpoint: /api/forgot-password
Corps de la requête:
{
"email": "john@example.com"
}
Exemple d'intégration Flutter:
Future forgotPassword({
required String email,
}) async {
final response = await http.post(
Uri.parse('${baseUrl}/api/forgot-password'),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: jsonEncode({
'email': email,
}),
);
if (response.statusCode != 200) {
throw Exception(jsonDecode(response.body)['message']);
}
}
Endpoint: /api/reset-password
Corps de la requête:
{
"token": "token_reçu_par_email",
"email": "john@example.com",
"password": "nouveau_mot_de_passe",
"password_confirmation": "nouveau_mot_de_passe"
}
Exemple d'intégration Flutter:
Future resetPassword({
required String token,
required String email,
required String password,
required String passwordConfirmation,
}) async {
final response = await http.post(
Uri.parse('${baseUrl}/api/reset-password'),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: jsonEncode({
'token': token,
'email': email,
'password': password,
'password_confirmation': passwordConfirmation,
}),
);
if (response.statusCode != 200) {
throw Exception(jsonDecode(response.body)['message']);
}
}
Endpoint: /api/logout
Exemple de réponse:
{
"success": true,
"message": "Déconnexion réussie"
}
Exemple d'intégration Flutter:
Future logout() async {
final token = await storage.read(key: 'token');
if (token == null) return;
final response = await http.post(
Uri.parse('${baseUrl}/api/logout'),
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
},
);
if (response.statusCode == 200) {
// Supprimer le token stocké
await storage.delete(key: 'token');
return;
}
final errorData = jsonDecode(response.body);
throw Exception(errorData['message'] ?? 'Erreur lors de la déconnexion');
}
Les routes OAuth utilisent un format générique avec le provider en paramètre :
/api/auth/{provider} (ex: /api/auth/google)/api/auth/{provider}/callback (ex: /api/auth/google/callback)Providers supportés: google, facebook, github
URL de redirection: /api/auth/google
URL de callback: /api/auth/google/callback
Le callback retourne un token et les informations utilisateur après authentification réussie.
Future signInWithGoogle() async {
final url = Uri.parse('${baseUrl}/api/auth/google');
// Utiliser url_launcher ou webview pour la redirection
if (await canLaunch(url.toString())) {
await launch(url.toString());
} else {
throw Exception('Impossible d\'ouvrir l\'URL d\'authentification');
}
}
URL de redirection: /api/auth/facebook
URL de callback: /api/auth/facebook/callback
Future signInWithFacebook() async {
final url = Uri.parse('${baseUrl}/api/auth/facebook');
if (await canLaunch(url.toString())) {
await launch(url.toString());
} else {
throw Exception('Impossible d\'ouvrir l\'URL d\'authentification');
}
}
URL de redirection: /api/auth/github
URL de callback: /api/auth/github/callback
Future signInWithGithub() async {
final url = Uri.parse('${baseUrl}/api/auth/github');
if (await canLaunch(url.toString())) {
await launch(url.toString());
} else {
throw Exception('Impossible d\'ouvrir l\'URL d\'authentification');
}
}
Endpoint: /api/register-owner
Corps de la requête:
{
"name": "Owner One",
"email": "owner@example.com",
"password": "password123",
"password_confirmation": "password123",
"organization_name": "Clinique Alpha",
"birth_date": "1990-01-01", // Optionnel
"phone": "+237600000000", // Optionnel
"address": "Yaoundé, Cameroun", // Optionnel
"speciality": "Cardiologie", // Optionnel
"medical_order_number": "12345" // Optionnel
}
Réponse:
{
"user": {
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "Owner One",
"email": "owner@example.com",
"role": "owner",
"organization_id": 5,
"has_used_trial": false,
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T12:00:00.000000Z"
},
"token": "votre_token_d_acces",
"organization": {
"id": 5,
"uuid": "660e8400-e29b-41d4-a716-446655440001",
"name": "Clinique Alpha",
"code": "ORG-XXXX",
"owner_user_id": 1,
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T12:00:00.000000Z"
},
"organization_code": "ORG-XXXX"
}
Exemple d'intégration Flutter:
Future
Endpoint: /api/register-doctor
Corps de la requête:
{
"name": "Dr Jane",
"email": "drjane@example.com",
"password": "password123",
"password_confirmation": "password123",
"organization_code": "ORG-XXXX",
"birth_date": "1990-01-01", // Optionnel
"phone": "+237600000000", // Optionnel
"address": "Yaoundé, Cameroun", // Optionnel
"speciality": "Cardiologie", // Optionnel
"medical_order_number": "12345" // Optionnel
}
Réponse:
{
"user": {
"id": 2,
"uuid": "550e8400-e29b-41d4-a716-446655440001",
"name": "Dr Jane",
"email": "drjane@example.com",
"role": "doctor",
"organization_id": 5,
"has_used_trial": false,
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T12:00:00.000000Z"
},
"token": "votre_token_d_acces",
"organization": {
"id": 5,
"uuid": "660e8400-e29b-41d4-a716-446655440001",
"name": "Clinique Alpha",
"code": "ORG-XXXX",
"owner_user_id": 1,
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T12:00:00.000000Z"
}
}
Exemple d'intégration Flutter:
Future
Endpoint: /api/me
Récupère l'utilisateur connecté avec son organisation et son rôle.
Réponse:
{
"user": {
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "Owner One",
"email": "owner@example.com",
"role": "owner",
"organization_id": 5,
"has_used_trial": false,
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T12:00:00.000000Z"
},
"organization": {
"id": 5,
"uuid": "660e8400-e29b-41d4-a716-446655440001",
"name": "Clinique Alpha",
"code": "ORG-XXXX",
"owner_user_id": 1,
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T12:00:00.000000Z"
},
"role": "owner"
}
Exemple d'intégration Flutter:
Future
Endpoint: /api/organization
Exemple de réponse:
{
"organization": {
"id": 1,
"uuid": "660e8400-e29b-41d4-a716-446655440001",
"name": "Clinique Alpha",
"code": "ORG-XXXX",
"owner_user_id": 1,
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T12:00:00.000000Z"
},
"role": "owner"
}
Exemple d'intégration Flutter:
Future
Endpoint: /api/organization
Corps de la requête:
{
"name": "Nouveau Nom de la Clinique"
}
Réponse:
{
"organization": {
"id": 1,
"uuid": "660e8400-e29b-41d4-a716-446655440001",
"name": "Nouveau Nom de la Clinique",
"code": "ORG-XXXX",
"owner_user_id": 1,
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T13:00:00.000000Z"
},
"message": "Organisation mise à jour avec succès"
}
Exemple d'intégration Flutter:
Future
Endpoint: /api/organization/rotate-code
Réponse:
{
"code": "ORG-YYYY",
"message": "Code d'invitation pivoté avec succès"
}
Exemple d'intégration Flutter:
Future rotateOrganizationCode() async {
final token = await storage.read(key: 'token');
if (token == null) throw Exception('Non authentifié');
final response = await http.post(
Uri.parse('${baseUrl}/api/organization/rotate-code'),
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
return data['code'];
}
throw Exception('Erreur lors de la rotation du code');
}
Endpoint: /api/reports/overview
Réponse:
{
"patients": {
"count": 120,
"recent": [
{ "uuid": "...", "name": "Patient Récent 1", "created_at": "..." }
]
},
"prescriptions": { "count": 350 },
"invoices": { "count": 280 }
}
Endpoint: /api/activity-log
Paramètres de filtre (optionnels): from, to, user_id, action_type, entity_type, search, limit, page.
Réponse:
{
"data": [
{
"id": 1,
"timestamp": "...",
"user_name": "Dr. John",
"action": "patient.created",
"entity_type": "patient",
"entity_uuid": "...",
"entity_name": "Nom du Patient"
}
],
"total": 50,
"page": 1,
"limit": 25
}
Endpoint: /api/admin/dashboard/stats
Réponse:
{
"stats": [ ... ],
"charts": {
"userTrend": [ ... ]
},
"recentActivities": [ ... ]
}
Lister: GET /api/admin/users
Détail: GET /api/admin/users/{id}
Mettre à jour: PUT /api/admin/users/{id}
Changer Statut: PATCH /api/admin/users/{id}/status
Supprimer: DELETE /api/admin/users/{id}
Liste paginée: /api/patients
Créer: POST /api/patients
Détail: GET /api/patients/{uuid}
MàJ: PATCH /api/patients/{uuid}
Suppression: DELETE /api/patients/{uuid}
Export: GET /api/patients/export?format=csv
Base: /api/prescriptions (CRUD REST)
Export: GET /api/prescriptions/export?format=csv
{
"uuid":"...",
"patient_uuid":"...",
"doctor_uuid":"...",
"medication":"Paracetamol 500mg",
"dosage":"3x/jour",
"duration":"7 jours",
"notes": "Après repas",
"validity_period": 30,
"file_uuid": null,
"date_issued":"2025-01-02"
}
Base: /api/invoices (CRUD REST)
{
"uuid":"...",
"patient_uuid":"...",
"doctor_uuid":"...",
"designation":"Consultation",
"unit_price":15000,
"quantity":1,
"total_amount":15000,
"file_uuid": null,
"date_issued":"2025-01-02"
}
Endpoint: /api/files (multipart/form-data)
file=@/path/to/doc.pdf
owner_type=patient|prescription|invoice
owner_uuid=...
Réponse:
{
"uuid": "...",
"path": "org_5/2025/01/....pdf",
"original_name": "ordonnance.pdf",
"mime_type": "application/pdf",
"size": 245678,
"checksum": "...",
"file_version": 1,
"created_at": "2025-01-02T16:00:00Z"
}
Endpoint: /api/files/{uuid}
Endpoint: /api/sync/changes?since=ISO8601&entities[]=patients&entities[]=prescriptions...
{
"cursor": "2025-01-02T15:30:45Z",
"changes": {
"patients": [{"uuid":"...","action":"upsert","data":{...}}],
"prescriptions": [],
"invoices": [],
"files": []
}
}
Endpoint: /api/sync/batch (≤100 éléments/entité)
{
"patients": [{"uuid":"...","name":"Jean","updated_at":"2025-01-02T11:00:00Z"}],
"prescriptions": [],
"invoices": [],
"files": []
}
Réponse:
{
"cursor": "2025-01-02T15:45:30Z",
"results": {"patients": [{"uuid":"...","status":"ok","updated_at":"..."}]},
"errors": []
}
Conflits critiques → listés dans errors (ex: organization_mismatch).
Endpoint: /api/sync/status
Réponse:
{
"pending_count": 12,
"error_count": 1,
"last_sync_at": "2025-01-02T15:45:30Z",
"errors": [
{
"timestamp": "2025-01-02T15:40:00Z",
"message": "Erreur de synchronisation",
"metadata": { ... }
}
]
}
/api/login: 5/min/api/register*: 3/h/api/sync/*: 60/h/api/files (upload): 20/hEndpoint: /api/user/profile
Paramètres: Aucun
Exemple de réponse:
{
"user": {
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "John Doe",
"email": "john@example.com",
"avatar": "1_1743615420.jpg",
"phone": "+237600000000",
"address": "Yaoundé, Cameroun",
"birth_date": "1990-01-01",
"speciality": "Cardiologie",
"medical_order_number": "12345",
"role": "owner",
"organization_id": 5,
"has_used_trial": true,
"email_verified_at": "2024-02-14T12:00:00.000000Z",
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T12:00:00.000000Z"
},
"message": "Profil récupéré avec succès"
}
Endpoint: /api/user/profile
Corps de la requête (multipart/form-data):
{
"name": "John Doe", // Optionnel
"birth_date": "1990-01-01", // Optionnel
"phone": "+237600000000", // Optionnel
"address": "Yaoundé, Cameroun", // Optionnel
"speciality": "Cardiologie", // Optionnel
"medical_order_number": "12345", // Optionnel
"avatar": [FICHIER IMAGE] // Optionnel, max 2MB
}
Exemple de réponse:
{
"message": "Profil mis à jour avec succès",
"user": {
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "John Doe",
"email": "john@example.com",
"avatar": "1_1743615420.jpg",
"phone": "+237600000000",
"address": "Yaoundé, Cameroun",
"birth_date": "1990-01-01",
"speciality": "Cardiologie",
"medical_order_number": "12345",
"role": "owner",
"organization_id": 5,
"has_used_trial": true,
"email_verified_at": "2024-02-14T12:00:00.000000Z",
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T12:00:00.000000Z"
}
}
Exemple d'intégration Flutter (avec upload d'avatar):
Future updateProfile({
String? name,
String? phone,
String? address,
String? birthDate,
String? speciality,
String? medicalOrderNumber,
File? avatarFile,
}) async {
final token = await storage.read(key: 'token');
if (token == null) throw Exception('Non authentifié');
final request = http.MultipartRequest(
'PUT',
Uri.parse('${baseUrl}/api/user/profile'),
);
request.headers.addAll({
'Authorization': 'Bearer $token',
'Accept': 'application/json',
});
if (name != null) request.fields['name'] = name;
if (phone != null) request.fields['phone'] = phone;
if (address != null) request.fields['address'] = address;
if (birthDate != null) request.fields['birth_date'] = birthDate;
if (speciality != null) request.fields['speciality'] = speciality;
if (medicalOrderNumber != null) request.fields['medical_order_number'] = medicalOrderNumber;
if (avatarFile != null) {
request.files.add(
await http.MultipartFile.fromPath('avatar', avatarFile.path),
);
}
final streamedResponse = await request.send();
final response = await http.Response.fromStream(streamedResponse);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
return User.fromJson(data['user']);
}
throw Exception('Échec de la mise à jour du profil');
}
Endpoint: /api/user/profile/email
Corps de la requête:
{
"email": "nouveau@example.com",
"current_password": "mot_de_passe_actuel"
}
Exemple de réponse:
{
"message": "Adresse email mise à jour avec succès",
"user": {
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "John Doe",
"email": "nouveau@example.com",
"email_verified_at": null,
"role": "owner",
"organization_id": 5,
"has_used_trial": true,
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T12:00:00.000000Z"
}
}
Exemple d'intégration Flutter:
Future updateEmail({
required String email,
required String currentPassword,
}) async {
final token = await storage.read(key: 'token');
if (token == null) throw Exception('Non authentifié');
final response = await http.put(
Uri.parse('${baseUrl}/api/user/profile/email'),
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: jsonEncode({
'email': email,
'current_password': currentPassword,
}),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
return User.fromJson(data['user']);
}
throw Exception('Échec de la mise à jour de l\'email');
}
Endpoint: /api/user/profile/password
Corps de la requête:
{
"current_password": "mot_de_passe_actuel",
"password": "nouveau_mot_de_passe",
"password_confirmation": "nouveau_mot_de_passe"
}
Exemple de réponse:
{
"message": "Mot de passe mis à jour avec succès"
}
Endpoint: /api/user/profile/avatar
Paramètres: Aucun
Exemple de réponse:
{
"message": "Avatar supprimé avec succès",
"user": {
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "John Doe",
"email": "john@example.com",
"avatar": null,
"role": "owner",
"organization_id": 5,
"has_used_trial": true,
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T12:00:00.000000Z"
}
}
Exemple d'intégration Flutter:
Future deleteAvatar() async {
final token = await storage.read(key: 'token');
if (token == null) throw Exception('Non authentifié');
final response = await http.delete(
Uri.parse('${baseUrl}/api/user/profile/avatar'),
headers: {
'Authorization': 'Bearer $token',
'Accept': 'application/json',
},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
return User.fromJson(data['user']);
}
throw Exception('Échec de la suppression de l\'avatar');
}
Endpoint: /api/user/profile/join-organization
Corps de la requête:
{
"organization_code": "ORG-XXXX"
}
Exemple de réponse:
{
"message": "Organisation rejointe avec succès",
"organization": {
"id": 5,
"uuid": "660e8400-e29b-41d4-a716-446655440001",
"name": "Clinique Alpha",
"code": "ORG-XXXX",
"owner_user_id": 1,
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T12:00:00.000000Z"
},
"user": {
"id": 1,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "John Doe",
"email": "john@example.com",
"organization_id": 5,
"role": "doctor",
"created_at": "2024-02-14T12:00:00.000000Z",
"updated_at": "2024-02-14T12:00:00.000000Z"
}
}
Exemple d'intégration Flutter:
Future
Endpoint: /api/admin/users
Paramètres:
Future
Exemple de réponse:
{
"data": [
{
"id": "1",
"name": "John Doe",
"email": "john@example.com",
"status": "active",
"createdAt": "2024-01-01T00:00:00.000Z",
"phone": "+237600000000",
"address": "Yaoundé, Cameroun",
"speciality": "Cardiologie",
"medical_order_number": "12345"
}
],
"total": 50,
"currentPage": 1,
"perPage": 10,
"lastPage": 5
}
Endpoint: /api/admin/users/{id}
Future
Exemple de réponse:
{
"user": {
"id": "1",
"name": "John Doe",
"email": "john@example.com",
"phone": "+237600000000",
"address": "Yaoundé, Cameroun",
"birth_date": "1990-01-01",
"speciality": "Cardiologie",
"medical_order_number": "12345",
"createdAt": "2024-01-01T00:00:00.000Z",
"status": "active",
"roles": ["doctor"]
}
}
class AdminUser {
final String id;
final String name;
final String email;
final String? phone;
final String? address;
final String? speciality;
final String? medicalOrderNumber;
final String status;
final DateTime createdAt;
AdminUser({
required this.id,
required this.name,
required this.email,
this.phone,
this.address,
this.speciality,
this.medicalOrderNumber,
required this.status,
required this.createdAt,
});
factory AdminUser.fromJson(Map json) {
return AdminUser(
id: json['id'].toString(),
name: json['name'],
email: json['email'],
phone: json['phone'],
address: json['address'],
speciality: json['speciality'],
medicalOrderNumber: json['medical_order_number'],
status: json['status'],
createdAt: DateTime.parse(json['createdAt']),
);
}
}