backend-service/docs/API_FLOW.md
ats-tech25 04f2d02afc docs(api comprehensive API documentation for attune Heart Therapy
Add detailed API:
- Complete API documentation for In Format Usage flow diagrams for authentication and booking processes
- Comprehensive endpoint descriptions with request/response examples
- Detailed authentication and booking flow explanations
- Structured documentation for health checks, authentication, and booking endpoints
-: - Includes JWT authentication details
usage
- Provides clear API usage patterns for users and clients and administrators
system interactions
- Enhances project documentation with provides clear, structured API reference
- Improves developer and user understanding of system capabilities
2025-11-07 19:22:46 +00:00

16 KiB

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

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)

    {
      "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)

    {
      "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)

    {
      "schedule_id": 5,
      "duration": 60,
      "notes": "First therapy session - anxiety management"
    }
    

    Requires JWT token in Authorization header

  5. Process Payment (POST /api/payments/intent)

    {
      "amount": 15000,
      "currency": "usd"
    }
    

    Amount in cents ($150.00)

  6. Confirm Payment (POST /api/payments/confirm)

    {
      "payment_intent_id": "pi_1234567890abcdef"
    }
    

B. Returning User Flow

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

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

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

// 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

// 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

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

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

// 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

# 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

// 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

// 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

// 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

// 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.