# API Usage Flow Guide ## Overview This document provides detailed workflows for different user types and common scenarios in the Attune Heart Therapy API system. ## User Types and Flows ### 1. Client User Flow (Regular Users) #### A. New User Registration & First Booking ```mermaid sequenceDiagram participant C as Client participant API as API Server participant DB as Database participant Stripe as Stripe participant Jitsi as Jitsi C->>API: POST /api/auth/register API->>DB: Create user record API->>C: User created successfully C->>API: POST /api/auth/login API->>DB: Validate credentials API->>C: JWT token + user info C->>API: GET /api/schedules?date=2024-12-15 API->>DB: Query available slots API->>C: Available time slots C->>API: POST /api/bookings (with JWT) API->>DB: Create booking record API->>Jitsi: Generate room details API->>C: Booking created + room info C->>API: POST /api/payments/intent (with JWT) API->>Stripe: Create payment intent API->>C: Payment intent + client secret C->>Stripe: Process payment (frontend) Stripe->>API: POST /api/payments/webhook API->>DB: Update booking payment status C->>API: POST /api/payments/confirm (with JWT) API->>Stripe: Confirm payment API->>DB: Update booking status API->>C: Payment confirmed ``` **Step-by-step breakdown:** 1. **Registration** (`POST /api/auth/register`) ```json { "first_name": "Sarah", "last_name": "Johnson", "email": "sarah.johnson@email.com", "phone": "+1234567890", "location": "New York, NY", "password": "securePassword123" } ``` 2. **Login** (`POST /api/auth/login`) ```json { "email": "sarah.johnson@email.com", "password": "securePassword123" } ``` *Store the returned JWT token for subsequent requests* 3. **Browse Available Slots** (`GET /api/schedules?date=2024-12-15`) *No authentication required - public endpoint* 4. **Create Booking** (`POST /api/bookings`) ```json { "schedule_id": 5, "duration": 60, "notes": "First therapy session - anxiety management" } ``` *Requires JWT token in Authorization header* 5. **Process Payment** (`POST /api/payments/intent`) ```json { "amount": 15000, "currency": "usd" } ``` *Amount in cents ($150.00)* 6. **Confirm Payment** (`POST /api/payments/confirm`) ```json { "payment_intent_id": "pi_1234567890abcdef" } ``` #### B. Returning User Flow ```mermaid sequenceDiagram participant C as Client participant API as API Server participant DB as Database C->>API: POST /api/auth/login API->>C: JWT token C->>API: GET /api/bookings (with JWT) API->>DB: Get user's bookings API->>C: List of bookings C->>API: GET /api/auth/profile (with JWT) API->>C: User profile data alt Update Profile C->>API: PUT /api/auth/profile (with JWT) API->>DB: Update user data API->>C: Updated profile end alt Cancel Booking C->>API: PUT /api/bookings/123/cancel (with JWT) API->>DB: Update booking status API->>C: Booking cancelled end alt Reschedule Booking C->>API: PUT /api/bookings/123/reschedule (with JWT) API->>DB: Update booking schedule API->>C: Booking rescheduled end ``` ### 2. Admin User Flow #### A. Admin Dashboard & Management ```mermaid sequenceDiagram participant A as Admin participant API as API Server participant DB as Database A->>API: POST /api/auth/login (admin credentials) API->>A: JWT token (with admin privileges) A->>API: GET /api/admin/dashboard (with admin JWT) API->>DB: Aggregate statistics API->>A: Dashboard stats A->>API: POST /api/admin/schedules (with admin JWT) API->>DB: Create schedule slots API->>A: Schedule created A->>API: GET /api/admin/users?limit=50&offset=0 API->>DB: Query users with pagination API->>A: User list A->>API: GET /api/admin/bookings?limit=50&offset=0 API->>DB: Query all bookings API->>A: Booking list A->>API: GET /api/admin/reports/financial?start_date=2024-01-01&end_date=2024-12-31 API->>DB: Generate financial report API->>A: Financial data ``` #### B. Schedule Management Flow ```mermaid sequenceDiagram participant A as Admin participant API as API Server participant DB as Database Note over A,DB: Creating Weekly Schedule loop For each day of the week A->>API: POST /api/admin/schedules Note right of A: Create morning slot (9:00-10:00) API->>DB: Insert schedule record A->>API: POST /api/admin/schedules Note right of A: Create afternoon slot (14:00-15:00) API->>DB: Insert schedule record A->>API: POST /api/admin/schedules Note right of A: Create evening slot (18:00-19:00) API->>DB: Insert schedule record end A->>API: GET /api/schedules?date=2024-12-15 API->>A: Verify created slots are available ``` ## Common Integration Patterns ### 1. Frontend Application Integration #### React/Vue.js Example Flow ```javascript // 1. Authentication Service class AuthService { async login(email, password) { const response = await fetch('/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) }); const data = await response.json(); if (data.token) { localStorage.setItem('authToken', data.token); localStorage.setItem('user', JSON.stringify(data.user)); } return data; } getAuthHeader() { const token = localStorage.getItem('authToken'); return token ? { 'Authorization': `Bearer ${token}` } : {}; } } // 2. Booking Service class BookingService { constructor(authService) { this.authService = authService; } async getAvailableSlots(date) { const response = await fetch(`/api/schedules?date=${date}`); return response.json(); } async createBooking(scheduleId, duration, notes) { const response = await fetch('/api/bookings', { method: 'POST', headers: { 'Content-Type': 'application/json', ...this.authService.getAuthHeader() }, body: JSON.stringify({ schedule_id: scheduleId, duration, notes }) }); return response.json(); } async getUserBookings() { const response = await fetch('/api/bookings', { headers: this.authService.getAuthHeader() }); return response.json(); } } // 3. Payment Service class PaymentService { constructor(authService) { this.authService = authService; } async createPaymentIntent(amount, currency = 'usd') { const response = await fetch('/api/payments/intent', { method: 'POST', headers: { 'Content-Type': 'application/json', ...this.authService.getAuthHeader() }, body: JSON.stringify({ amount, currency }) }); return response.json(); } async confirmPayment(paymentIntentId) { const response = await fetch('/api/payments/confirm', { method: 'POST', headers: { 'Content-Type': 'application/json', ...this.authService.getAuthHeader() }, body: JSON.stringify({ payment_intent_id: paymentIntentId }) }); return response.json(); } } ``` ### 2. Mobile Application Integration #### React Native Example ```javascript // API Client with automatic token management class APIClient { constructor() { this.baseURL = 'http://localhost:8080'; this.token = null; } async setToken(token) { this.token = token; await AsyncStorage.setItem('authToken', token); } async getToken() { if (!this.token) { this.token = await AsyncStorage.getItem('authToken'); } return this.token; } async request(endpoint, options = {}) { const token = await this.getToken(); const headers = { 'Content-Type': 'application/json', ...(token && { 'Authorization': `Bearer ${token}` }), ...options.headers }; const response = await fetch(`${this.baseURL}${endpoint}`, { ...options, headers }); if (response.status === 401) { // Token expired, redirect to login await AsyncStorage.removeItem('authToken'); this.token = null; // Navigate to login screen } return response.json(); } } ``` ## Error Handling Patterns ### 1. Client-Side Error Handling ```javascript class APIErrorHandler { static handle(error, response) { switch (response.status) { case 400: return { type: 'VALIDATION_ERROR', message: error.details || error.error }; case 401: return { type: 'AUTH_ERROR', message: 'Please login again' }; case 403: return { type: 'PERMISSION_ERROR', message: 'Access denied' }; case 409: return { type: 'CONFLICT_ERROR', message: error.error }; case 422: return { type: 'PAYMENT_ERROR', message: error.error }; case 500: return { type: 'SERVER_ERROR', message: 'Server error, please try again' }; default: return { type: 'UNKNOWN_ERROR', message: 'An unexpected error occurred' }; } } } // Usage in service methods async createBooking(data) { try { const response = await fetch('/api/bookings', { method: 'POST', headers: this.getHeaders(), body: JSON.stringify(data) }); const result = await response.json(); if (!response.ok) { const error = APIErrorHandler.handle(result, response); throw error; } return result; } catch (error) { if (error.type) { // Handled API error throw error; } else { // Network or other error throw { type: 'NETWORK_ERROR', message: 'Network error, please check your connection' }; } } } ``` ### 2. Retry Logic for Failed Requests ```javascript class RetryableAPIClient { async requestWithRetry(endpoint, options = {}, maxRetries = 3) { let lastError; for (let attempt = 1; attempt <= maxRetries; attempt++) { try { const response = await fetch(`${this.baseURL}${endpoint}`, options); if (response.ok) { return response.json(); } // Don't retry client errors (4xx) if (response.status >= 400 && response.status < 500) { throw await response.json(); } lastError = await response.json(); if (attempt < maxRetries) { // Exponential backoff await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000) ); } } catch (error) { lastError = error; if (attempt < maxRetries && this.isRetryableError(error)) { await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000) ); } else { break; } } } throw lastError; } isRetryableError(error) { return error.code === 'NETWORK_ERROR' || error.code === 'TIMEOUT' || (error.status >= 500); } } ``` ## Testing Workflows ### 1. Postman Collection Testing Flow ```javascript // Collection-level pre-request script pm.collectionVariables.set("baseUrl", "http://localhost:8080"); // Test script for login request if (pm.response.code === 200) { const response = pm.response.json(); pm.collectionVariables.set("authToken", response.token); pm.collectionVariables.set("userId", response.user.id); pm.test("Login successful", function () { pm.expect(response.token).to.not.be.empty; pm.expect(response.user.email).to.not.be.empty; }); } // Test script for booking creation if (pm.response.code === 201) { const response = pm.response.json(); pm.collectionVariables.set("bookingId", response.booking.id); pm.test("Booking created successfully", function () { pm.expect(response.booking.id).to.be.a('number'); pm.expect(response.booking.jitsi_room_url).to.not.be.empty; }); } ``` ### 2. Automated Testing Sequence ```bash # Run the complete user journey newman run "Attune Heart Therapy API.postman_collection.json" \ -e "Local Environment.postman_environment.json" \ --folder "Authentication" \ --folder "Schedules & Bookings" \ --folder "Payments" \ --reporters cli,json \ --reporter-json-export results.json ``` ## Performance Considerations ### 1. Caching Strategy ```javascript // Client-side caching for available slots class CachedBookingService { constructor() { this.cache = new Map(); this.cacheTimeout = 5 * 60 * 1000; // 5 minutes } async getAvailableSlots(date) { const cacheKey = `slots_${date}`; const cached = this.cache.get(cacheKey); if (cached && Date.now() - cached.timestamp < this.cacheTimeout) { return cached.data; } const data = await this.fetchAvailableSlots(date); this.cache.set(cacheKey, { data, timestamp: Date.now() }); return data; } } ``` ### 2. Pagination Handling ```javascript // Efficient pagination for admin endpoints class PaginatedDataService { async getAllUsers(pageSize = 50) { let allUsers = []; let offset = 0; let hasMore = true; while (hasMore) { const response = await fetch( `/api/admin/users?limit=${pageSize}&offset=${offset}`, { headers: this.getAuthHeaders() } ); const data = await response.json(); allUsers = [...allUsers, ...data.users]; hasMore = data.users.length === pageSize; offset += pageSize; } return allUsers; } } ``` ## Security Best Practices ### 1. Token Management ```javascript // Secure token storage and refresh class SecureAuthService { constructor() { this.tokenRefreshThreshold = 5 * 60 * 1000; // 5 minutes before expiry } async getValidToken() { const token = localStorage.getItem('authToken'); const tokenExpiry = localStorage.getItem('tokenExpiry'); if (!token || !tokenExpiry) { throw new Error('No valid token found'); } const expiryTime = new Date(tokenExpiry).getTime(); const now = Date.now(); if (now >= expiryTime - this.tokenRefreshThreshold) { // Token is about to expire, refresh it await this.refreshToken(); return localStorage.getItem('authToken'); } return token; } async refreshToken() { // Implement token refresh logic // This would require a refresh token endpoint } } ``` ### 2. Input Validation ```javascript // Client-side validation before API calls class ValidationService { static validateBookingData(data) { const errors = []; if (!data.schedule_id || !Number.isInteger(data.schedule_id)) { errors.push('Valid schedule ID is required'); } if (!data.duration || data.duration < 15 || data.duration > 480) { errors.push('Duration must be between 15 and 480 minutes'); } if (data.notes && data.notes.length > 1000) { errors.push('Notes cannot exceed 1000 characters'); } return { isValid: errors.length === 0, errors }; } static validateUserRegistration(data) { const errors = []; const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!data.first_name || data.first_name.length < 2) { errors.push('First name must be at least 2 characters'); } if (!data.last_name || data.last_name.length < 2) { errors.push('Last name must be at least 2 characters'); } if (!data.email || !emailRegex.test(data.email)) { errors.push('Valid email address is required'); } if (!data.password || data.password.length < 8) { errors.push('Password must be at least 8 characters'); } return { isValid: errors.length === 0, errors }; } } ``` This comprehensive flow guide should help developers understand how to integrate with your API effectively and handle various scenarios that may arise during implementation.