API Documentation
Welcome to the WootHealth Backend API.
Authentication
API requests are authenticated using session cookies. The login and signup endpoints are available to create and authenticate a user.
Endpoints
POST /signup
Create a new user.
Body:
{
"email": "user@example.com",
"password": "password"
}
Flutter:
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> signup(String email, String password) async {
final response = await http.post(
Uri.parse('http://your-server.com/signup'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'email': email,
'password': password,
}),
);
if (response.statusCode == 200 || response.statusCode == 201) {
print('Signup successful');
}
}
POST /login
Login a user.
Body:
{
"email": "user@example.com",
"password": "password"
}
Flutter:
Future<void> login(String email, String password) async {
final response = await http.post(
Uri.parse('http://your-server.com/login'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'email': email,
'password': password,
}),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
print('Login successful');
}
}
GET /providers
Get a list of providers.
GET /plans
Get the logged-in user's active plan, coverage summary, and quick actions.
Response (example):
{
"success": true,
"data": {
"activePlan": {
"name": "Retail Quantum Plan",
"monthlyPremium": 34100,
"coveredMembers": 4,
"nextRenewal": "2025-01-10",
"planType": "Family Coverage",
"hmoId": "111076",
"coverageActive": true
},
"coverageSummary": [
{
"title": "Hospital Care",
"annualLimit": 5000000,
"used": 450000,
"utilizedPercent": 9
},
{
"title": "Pharmacy & Drugs",
"annualLimit": 500000,
"used": 120000,
"utilizedPercent": 24
}
],
"quickActions": [
{"key": "reimbursement", "label": "Reimbursement"},
{"key": "find_provider", "label": "Find a Provider"},
{"key": "upgrade_plan", "label": "Upgrade Plan"},
{"key": "add_dependent", "label": "Add Dependent"}
]
}
}
GET /logout
Logout the current user.
Business Endpoints
Endpoints for users with role=business. All require an active session. Base path: /business/{feature}
GET /business/overview
Dashboard summary: total employees, active reimbursements, wallet balance, annual coverage data, plan breakdown, and recent activities.
GET POST /business/employees
GET: List enrolled employees with stats (total, active, slots available). Supports ?search=, ?limit=, ?offset=.
POST: Add a new employee (enrolle). Enforces slot limits from active plan.
Body (POST):
{ "email": "jane@example.com", "firstName": "Jane", "lastName": "Doe",
"phone": "+234...", "department": "Finance", "dateOfBirth": "1990-01-01",
"gender": "Female", "plan": "Quantum", "status": "active" }
GET PUT DELETE /business/employees/{id}
GET: Single employee detail. PUT: Update employee fields. DELETE: Remove employee from business account.
GET /business/billings
Billing/invoice history. Filter by type with ?type=credit|debit|pending.
GET /business/billings/{id}
Single invoice detail including bill-to, bill-from, line items, payment info.
GET PUT /business/profile
GET: Company profile (industry, address, registration number). PUT: Update profile fields.
GET POST /business/profile/administrators
GET: List account administrators. POST: Add a new administrator.
Body (POST):
{ "name": "Oluwaseun Adeyemi", "email": "user@co.com", "position": "HR Director", "role": "Full Access" }
GET /business/plans
List available business plans (filtered to planType=business automatically).
POST /business/plans/purchase
Purchase / activate a business plan.
Body:
{ "planId": "...", "autoRenew": true }
GET POST /business/settings/security
GET: List active device sessions. POST: Change account password.
Body (POST):
{ "newPassword": "...", "confirmPassword": "..." }
DELETE /business/settings/security/{sessionId}
Revoke a specific device session.
GET POST /business/settings/sla
GET: List uploaded SLA documents. POST: Register new SLA document metadata (file upload via Appwrite Storage separately).
Body (POST):
{ "fileName": "SLA_2025.pdf", "fileUrl": "...", "fileSize": "2.4 MB", "validUntil": "2025-12-31" }
DELETE /business/settings/sla/{id}
Delete an SLA document record.
GET POST /business/settings/payment-methods
GET: List saved payment methods/cards. POST: Add a new payment card.
Body (POST):
{ "cardType": "visa", "lastFour": "1245", "expiryMonth": "12", "expiryYear": "25", "token": "...", "isDefault": true }
DELETE /business/settings/payment-methods/{id}
Remove a saved payment method.
Admin Endpoints
All admin endpoints support both GET (retrieve data) and POST (create/update data) methods. Base path: /admin/{feature}
GET POST /admin/overview
Manage overview dashboard data. GET returns total counts of users, enrollees, clients, and telemedicine requests.
GET POST /profile
User-facing profile management. GET retrieves current user's profile, POST updates current user's profile.
Body (POST):
{
"email": "user@example.com",
"phone": "+1234567890",
"firstName": "John",
"lastName": "Doe",
"specialization": "Cardiology",
"availability": true
}
Flutter (GET):
Future<void> getProfile() async {
final response = await http.get(
Uri.parse('http://your-server.com/profile'),
headers: {'Content-Type': 'application/json'},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
print('Profile: ${data["data"]}');
}
}
Flutter (POST):
Future<void> updateProfile({
required String email,
required String phone,
required String firstName,
required String lastName,
}) async {
final response = await http.post(
Uri.parse('http://your-server.com/profile'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'email': email,
'phone': phone,
'firstName': firstName,
'lastName': lastName,
}),
);
if (response.statusCode == 200) {
print('Profile updated');
}
}
GET POST /admin/profile
Admin-only profile management. GET retrieves any user's profile, POST creates or updates user profile (admin only).
Body (POST):
{
"userId": "user_id",
"email": "user@example.com",
"password": "password",
"phone": "+1234567890",
"firstName": "John",
"lastName": "Doe",
"role": "doctor",
"specialization": "Cardiology",
"availability": true
}
GET POST /notifications
Manage user notifications. GET retrieves all notifications, POST creates new notification.
Body (POST):
{
"notificationId": "unique_id",
"message": "Notification message (max 500 characters)",
"status": "pending",
"notificationType": "alert",
"priorityLevel": 3
}
Flutter (GET):
Future<void> getNotifications() async {
final response = await http.get(
Uri.parse('http://your-server.com/notifications'),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
List notifications = data['data'];
print('Notifications: $notifications');
}
}
Flutter (POST):
Future<void> createNotification({
required String notificationId,
required String message,
required String status,
required String notificationType,
required int priorityLevel,
}) async {
final response = await http.post(
Uri.parse('http://your-server.com/notifications'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'notificationId': notificationId,
'message': message,
'status': status,
'notificationType': notificationType,
'priorityLevel': priorityLevel,
}),
);
if (response.statusCode == 201) {
print('Notification created');
}
}
Query Parameters:
GET /notifications/{id} - Get specific notification by ID
PUT /notifications/{id} - Update notification
DELETE /notifications/{id} - Delete notification
GET POST /messages
Manage appointment messages. GET retrieves all messages (optionally filter by appointmentId), POST creates new message.
Body (POST):
{
"appointmentId": "appointment_id",
"senderId": "user_id",
"content": "Message content (max 1024 characters)",
"type": "text"
}
Flutter (GET with filter):
Future<void> getMessages({String? appointmentId}) async {
String url = 'http://your-server.com/messages';
if (appointmentId != null) {
url += '?appointmentId=$appointmentId';
}
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
List messages = data['data'];
print('Messages: $messages');
}
}
Flutter (POST):
Future<void> sendMessage({
required String appointmentId,
required String senderId,
required String content,
}) async {
final response = await http.post(
Uri.parse('http://your-server.com/messages'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'appointmentId': appointmentId,
'senderId': senderId,
'content': content,
'type': 'text',
}),
);
if (response.statusCode == 201) {
print('Message sent');
}
}
Query Parameters:
GET /messages?appointmentId=xxx - Filter by appointment
GET /messages/{id} - Get specific message
PUT /messages/{id} - Update message
DELETE /messages/{id} - Delete message
GET POST /callhistory
Manage call history records. GET retrieves all call records (optionally filter by appointmentId), POST creates new call history.
Body (POST):
{
"appointmentId": "appointment_id",
"durationSec": 3600,
"startedAt": "2026-01-02T10:30:00Z",
"endedAt": "2026-01-02T11:30:00Z"
}
Flutter (POST):
Future<void> createCallHistory({
required String appointmentId,
required int durationSec,
required String startedAt,
required String endedAt,
}) async {
final response = await http.post(
Uri.parse('http://your-server.com/callhistory'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'appointmentId': appointmentId,
'durationSec': durationSec,
'startedAt': startedAt,
'endedAt': endedAt,
}),
);
if (response.statusCode == 201) {
print('Call history recorded');
}
}
Query Parameters:
GET /callhistory?appointmentId=xxx - Filter by appointment
GET /callhistory/{id} - Get specific call record
PUT /callhistory/{id} - Update call history
DELETE /callhistory/{id} - Delete call record
GET POST /recentactivity
Manage user activity logs. GET retrieves all activities for current user, POST logs new activity.
Body (POST):
{
"activityType": "login",
"description": "User logged in from mobile app (max 500 characters)",
"metadata": {
"ipAddress": "192.168.1.1",
"device": "mobile"
}
}
Flutter (GET):
Future<void> getRecentActivities() async {
final response = await http.get(
Uri.parse('http://your-server.com/recentactivity'),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
List activities = data['data'];
print('Activities: $activities');
}
}
Flutter (POST):
Future<void> logActivity({
required String activityType,
required String description,
Map<String, dynamic>? metadata,
}) async {
final response = await http.post(
Uri.parse('http://your-server.com/recentactivity'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'activityType': activityType,
'description': description,
if (metadata != null) 'metadata': metadata,
}),
);
if (response.statusCode == 201) {
print('Activity logged');
}
}
Query Parameters:
GET /recentactivity/{id} - Get specific activity
DELETE /recentactivity/{id} - Delete activity
GET POST /patients
Manage patient records (doctor only). GET retrieves all patients handled by the doctor, POST adds/assigns a new patient.
Body (POST):
{
"patientId": "unique_patient_id",
"firstName": "John",
"lastName": "Doe",
"email": "patient@example.com",
"phone": "+1234567890",
"medicalHistory": "Patient history (optional, max 1000 characters)",
"allergies": "Penicillin (optional, max 500 characters)",
"dateOfBirth": "1990-01-15",
"gender": "male"
}
Flutter (GET with pagination):
Future<void> getPatients({int limit = 100, int offset = 0}) async {
final response = await http.get(
Uri.parse('http://your-server.com/patients?limit=$limit&offset=$offset'),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
List patients = data['data'];
int total = data['total'];
print('Patients: $patients (Total: $total)');
}
}
Flutter (POST):
Future<void> addPatient({
required String patientId,
required String firstName,
required String lastName,
required String email,
required String phone,
String? medicalHistory,
String? allergies,
}) async {
final response = await http.post(
Uri.parse('http://your-server.com/patients'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'patientId': patientId,
'firstName': firstName,
'lastName': lastName,
'email': email,
'phone': phone,
if (medicalHistory != null) 'medicalHistory': medicalHistory,
if (allergies != null) 'allergies': allergies,
}),
);
if (response.statusCode == 201) {
print('Patient added');
}
}
Query Parameters:
GET /patients?limit=100&offset=0 - Get patients with pagination
GET /patients/{id} - Get specific patient
DELETE /patients/{id} - Remove patient from doctor's list
Note: Doctor role required; can only access own patients
🆕 Appointments Management
POST /appointments
Create a new appointment. RoomId is auto-generated as 'room-{appointmentId}'
Body:
{
"patientId": "user_123",
"doctorId": "doctor_456",
"scheduledAt": "2026-02-10T10:00:00Z",
"symptoms": "Headache and fever"
}
Response:
{
"success": true,
"data": {
"appointmentId": "appt_abc123",
"roomId": "room-appt_abc123",
"patientId": "user_123",
"doctorId": "doctor_456",
"scheduledAt": "2026-02-10T10:00:00Z",
"status": "pending",
"symptoms": "Headache and fever"
},
"message": "Appointment created successfully with roomId: room-appt_abc123"
}
GET /appointments
List appointments with optional filters
Query Parameters:
patientId - Filter by patient
doctorId - Filter by doctor
status - Filter by status (pending/confirmed/cancelled/completed)
startDate - Filter from date
endDate - Filter to date
limit - Results per page (default: 25)
offset - Pagination offset (default: 0)
PUT /appointments/{id}
Update appointment status, reschedule, or cancel
Body (Update Status):
{
"status": "confirmed",
"notes": "Appointment confirmed"
}
Body (Reschedule):
{
"scheduledAt": "2026-02-11T14:00:00Z"
}
Body (Cancel):
{
"cancelReason": "Patient unavailable"
}
💳 Wallet & Payments
GET /wallet?userId={userId}
Get wallet balance for a user
Response:
{
"success": true,
"data": {
"$id": "wallet_001",
"userId": "user_123",
"balance": 25000.00,
"hasActiveCard": true,
"lastUpdated": "2026-02-06T08:30:00Z",
"currency": "NGN"
}
}
POST /wallet/topup
Initialize wallet top-up via Paystack
Body:
{
"userId": "user_123",
"email": "user@example.com",
"amount": 5000
}
Response:
{
"success": true,
"authorization_url": "https://checkout.paystack.com/...",
"reference": "TOPUP_user_123_1234567890",
"message": "Payment initialized. Redirect user to authorization_url"
}
POST /wallet/verify-payment
Verify payment and credit wallet
Body:
{
"reference": "TOPUP_user_123_1234567890"
}
Response:
{
"success": true,
"data": {
"previousBalance": 20000,
"amount": 5000,
"newBalance": 25000
},
"message": "Payment verified and wallet credited successfully"
}
GET /wallet/transactions?userId={userId}
Get transaction history
Query Parameters:
limit - Results per page (default: 50)
offset - Pagination offset (default: 0)
📋 Insurance Plans
GET /plans
List all available insurance plans
Query Parameters:
activeOnly - Show only active plans (default: true)
limit - Results per page (default: 50)
offset - Pagination offset (default: 0)
POST /plans
Create new insurance plan (Admin/Superadmin only)
Body:
{
"name": "Premium Family Plan",
"description": "Comprehensive family coverage",
"price": 50000,
"duration": 365,
"planType": "Family",
"coverage": ["Hospital Care", "Pharmacy", "Dental"],
"benefits": ["24/7 Telemedicine", "Annual Checkup"],
"isActive": true
}
POST /plans/activate
Activate a plan for a user
Body:
{
"userId": "user_123",
"planId": "plan_456",
"autoRenew": true,
"purchasedBy": ""
}
GET /plans/active/{userId}
Get active plans for a user
📝 Claims Management
POST /claims
Submit a new insurance claim
Body:
{
"userId": "user_123",
"claimType": "Hospital Care",
"dateOfService": "2026-02-05T00:00:00Z",
"hospitalProvider": "General Hospital",
"amount": 50000,
"description": "Emergency treatment",
"documents": ["https://storage.example.com/doc1.pdf"]
}
GET /claims
List claims with optional filters
Query Parameters:
userId - Filter by user
status - Filter by status (Pending/Processing/Approved/Rejected)
claimType - Filter by claim type
startDate - Filter from date
endDate - Filter to date
limit - Results per page (default: 50)
offset - Pagination offset (default: 0)
PUT /claims/{id}/process
Process claim - Approve or Reject (Admin only). Approved claims automatically credit user's wallet
Body:
{
"status": "Approved",
"reviewedBy": "admin_456",
"approvedAmount": 45000,
"reviewNotes": "Approved with 10% deductible"
}
Response:
{
"success": true,
"data": {
"claimId": "claim_123",
"status": "Approved",
"approvedAmount": 45000
},
"message": "Claim Approved successfully. Wallet credited with ₦45,000"
}
Admin Endpoints
All admin endpoints support both GET (retrieve data) and POST (create/update data) methods. Base path: /admin/{feature}
All endpoints return JSON responses. GET requests from admin endpoints return:
{
"success": true,
"data": [],
"total": 0,
"message": "List retrieved"
}
Error Handling
Errors are returned with appropriate HTTP status codes and a JSON error message:
{
"error": "Error description"
}