API Documentation

Integrate Swim ProHub 360 analysis into your applications

Quick Start Guide

Get started with the Swim ProHub 360 API. Base URL: http://localhost:5001

1. Check API Health

GET/api/health

curl http://localhost:5001/api/health

2. Upload a Video

POST/api/analyze

curl -X POST \
  -F "[email protected]" \
  http://localhost:5001/api/analyze

3. Check Job Status

GET/api/jobs/{job_id}/status

curl http://localhost:5001/api/jobs/{job_id}/status

4. Get Analysis Results

GET/api/jobs/{job_id}/result

curl http://localhost:5001/api/jobs/{job_id}/result

5. Chat with AI Coach

POST/api/jobs/{job_id}/chat

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"message": "How can I improve?"}' \
  http://localhost:5001/api/jobs/{job_id}/chat

6. Compare Two Videos

POST/api/compare

curl -X POST \
  -F "[email protected]" \
  -F "[email protected]" \
  http://localhost:5001/api/compare

Response Metrics Explained

Metric Description Ideal Range
stroke_rate Strokes per minute 40-60 (varies by stroke)
dps Distance per stroke in meters 1.6-2.2m
swolf SWOLF score (strokes + time for 25m) Lower is better (30-50)
speed Average speed in meters/minute 60-100 m/min
avg_body_angle Average body angle deviation 10-30 degrees
body_rotation Shoulder rotation in degrees 0-10 degrees
kick_rhythm Kick frequency per minute Varies by stroke style

Flutter Flutter Integration Guide

Complete guide for integrating the Swim ProHub 360 API into your Flutter application.

1. Add Dependencies

Add these to your pubspec.yaml:

# pubspec.yaml
dependencies:
  http: ^1.1.0
  http_parser: ^4.0.2

2. Create API Service Class

import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;

class SwimAnalysisService {
  final String baseUrl;

  SwimAnalysisService({this.baseUrl = 'http://localhost:5001'});

  /// Upload video for analysis
  Future<String> uploadVideo(File videoFile) async {
    var request = http.MultipartRequest(
      'POST',
      Uri.parse('$baseUrl/api/analyze'),
    );

    request.files.add(await http.MultipartFile.fromPath(
      'video',
      videoFile.path,
    ));

    final response = await request.send();
    final body = await response.stream.bytesToString();

    if (response.statusCode == 202) {
      return jsonDecode(body)['job_id'];
    }
    throw Exception('Upload failed');
  }

  /// Get job status
  Future<Map> getJobStatus(String jobId) async {
    final response = await http.get(
      Uri.parse('$baseUrl/api/jobs/$jobId/status'),
    );
    return jsonDecode(response.body);
  }

  /// Chat with AI coach
  Future<String> askCoach(String jobId, String message) async {
    final response = await http.post(
      Uri.parse('$baseUrl/api/jobs/$jobId/chat'),
      headers: {'Content-Type': 'application/json'},
      body: jsonEncode({'message': message}),
    );
    return jsonDecode(response.body)['response'];
  }
}

3. Example Widget Usage

class VideoAnalysisScreen extends StatefulWidget {
  @override
  _VideoAnalysisScreenState createState() => _VideoAnalysisScreenState();
}

class _VideoAnalysisScreenState extends State<VideoAnalysisScreen> {
  final service = SwimAnalysisService();
  int progress = 0;

  Future<void> analyzeVideo(File video) async {
    final jobId = await service.uploadVideo(video);

    // Poll for completion
    while (true) {
      final status = await service.getJobStatus(jobId);
      setState(() => progress = status['progress']);

      if (status['status'] == 'complete') break;
      await Future.delayed(Duration(seconds: 1));
    }
  }
}