Student App API Vision

This document outlines potential API designs for optimizing the FindU iOS app experience. Currently, the app communicates directly with Supabase.
This is a design reference document. These endpoints do not currently exist. The iOS app uses Supabase Swift SDK for all operations.

Current Implementation

The iOS app currently:
  • Uses Supabase Swift SDK
  • Handles authentication via Supabase Auth
  • Queries database directly
  • Manages real-time subscriptions
// Current approach
let schools = try await supabase
    .from("schools")
    .select("*")
    .order("match_score", ascending: false)
    .limit(20)
    .execute()

Future API Benefits

A dedicated Student API could provide:

1. Mobile Optimization

Reduced payload sizes and batched data:
// Future API approach
let recommendations = try await api.getRecommendations(
    compressed: true,
    includeImages: .thumbnail
)

2. Offline Support

Cache-friendly endpoints with sync capabilities:
// Sync local changes when online
let syncResult = try await api.syncOfflineActions(
    swipes: localSwipes,
    messages: localDrafts
)

3. Simplified Data Access

Pre-computed and enriched responses:
// Get everything needed for home screen in one call
let homeData = try await api.getHomeScreen()
// Returns: recommendations, unread messages, new matches, etc.

Proposed Endpoint Structure

Authentication & Profile

POST /student/auth/apple
POST /student/auth/google
POST /student/auth/refresh
GET  /student/profile
POST /student/profile
PATCH /student/profile
POST /student/profile/avatar

Discovery & Matching

GET  /student/recommendations
POST /student/swipe
GET  /student/schools/:id
POST /student/schools/:id/save
GET  /student/matches
GET  /student/match/:schoolId/details

Messaging

GET  /student/conversations
GET  /student/conversations/:id
POST /student/messages
PATCH /student/messages/:id/read
GET  /student/notifications

Social Features

GET  /student/friends
POST /student/friends/add
POST /student/friends/share-profile
GET  /student/friends/:id/schools
POST /student/compare-schools

Scholarships

GET  /student/scholarships
GET  /student/scholarships/saved
POST /student/scholarships/:id/save
GET  /student/scholarships/:id

Mobile-First Design Patterns

Compressed Responses

// Full response
interface School {
  id: string;
  name: string;
  location: { city: string; state: string; };
  stats: { /* 20+ fields */ };
  images: string[];
}

// Compressed for lists
interface SchoolCompressed {
  i: string;    // id
  n: string;    // name
  l: string;    // location "City, ST"
  m: number;    // matchScore
  img: string;  // thumbnail
}

Progressive Data Loading

// Initial load - minimal data
GET /student/recommendations?fields=minimal

// User shows interest - load details
GET /student/schools/:id?fields=full

// Background sync - preload next batch
GET /student/recommendations/preload

Optimistic Updates

// Immediate response with pending status
POST /student/swipe
Response: { status: 'pending', tempId: 'tmp_123' }

// Confirm via websocket or polling
WS: { event: 'swipe.confirmed', tempId: 'tmp_123', id: 'swipe_456' }

Performance Optimizations

Caching Strategy

// Cache headers for different resources
interface CachePolicy {
  schools: 'max-age=3600',           // 1 hour
  profile: 'max-age=300',            // 5 minutes  
  recommendations: 'private, max-age=1800', // 30 minutes
  messages: 'no-cache'               // Always fresh
}

Batch Operations

// Batch multiple operations
POST /student/batch
{
  operations: [
    { method: 'POST', path: '/swipe', body: {...} },
    { method: 'GET', path: '/recommendations' },
    { method: 'PATCH', path: '/messages/123/read' }
  ]
}

Delta Sync

// Only get changes since last sync
GET /student/sync?since=2024-01-15T10:00:00Z
Response: {
  newMessages: [...],
  updatedSchools: [...],
  deletedItems: [...]
}

Push Notification Integration

// Register for notifications
POST /student/devices
{
  token: "APNS_TOKEN",
  platform: "ios",
  preferences: {
    messages: true,
    matches: true,
    reminders: true
  }
}

// Notification payload
{
  aps: {
    alert: "MIT liked you back! 🎉",
    badge: 1,
    sound: "match.caf"
  },
  findu: {
    type: "match",
    schoolId: "mit_123",
    deepLink: "findu://school/mit_123"
  }
}

Implementation Considerations

iOS SDK Design

// Clean SDK interface
class FindUAPI {
    func getRecommendations() async throws -> [School]
    func recordSwipe(_ direction: SwipeDirection, for school: School) async throws
    func sendMessage(_ text: String, to conversation: Conversation) async throws
}

// With offline support
class FindUOfflineAPI: FindUAPI {
    private let cache: CacheManager
    private let queue: OfflineQueue
    
    override func recordSwipe(...) async throws {
        try queue.enqueue(.swipe(direction, school))
        try await syncIfOnline()
    }
}

Error Handling

enum FindUError: LocalizedError {
    case offline
    case invalidProfile(missing: [String])
    case rateLimited(retryAfter: TimeInterval)
    case schoolNotFound
    
    var errorDescription: String? {
        switch self {
        case .offline:
            return "You're offline. Changes will sync when connected."
        case .invalidProfile(let fields):
            return "Complete your profile: \(fields.joined(separator: ", "))"
        case .rateLimited(let retry):
            return "Too many requests. Try again in \(Int(retry)) seconds."
        case .schoolNotFound:
            return "This school is no longer available."
        }
    }
}

Migration Strategy

If implementing this API:
  1. Phase 1: Read-only endpoints
    • Recommendations
    • School details
    • Profile data
  2. Phase 2: Core interactions
    • Swipe recording
    • Message sending
    • Profile updates
  3. Phase 3: Advanced features
    • Offline sync
    • Batch operations
    • Push notifications

Current Alternative

For now, the iOS app can optimize using:
  • Supabase SDK with selective queries
  • Local caching with UserDefaults/CoreData
  • Background refresh tasks
  • Supabase real-time for instant updates
See iOS App Architecture for current implementation details.