Dashboard

AIX Control Panel

Project

No project selected

Labels

No labels added yet

Operations

Model Conversion

Select a .PT file to start conversion

Model Export

Complete training to enable downloads

Ready to initialize AIX

Terminal Logs

šŸ¤– AIX Terminal Ready
Monitor AIX operations here

File Manager

Path: sandbox/
Drop files here
Name Size Actions

Loading...

Dataset Upload

Drop files here

Auto-sorted by type

Project Selection

No project selected

Labels

No labels available

Tools

Actions

Image Viewer

Select a project and image to start labeling

Images

0 / 0

No images found

Annotations

0

No annotations

Stats

Images: 0
Labeled: 0
Progress: 0%
Annotations: 0

API Overview

The AIX API allows external applications to interact with our machine learning training platform. Upload datasets, start training jobs, and retrieve trained models programmatically.

Key Features:

  • Upload training datasets (images + labels)
  • Initialize and start training jobs
  • Download trained models (.pt and .rknn)
  • Convert PyTorch models to RKNN for RK3588
  • Monitor training progress
  • Secure API key authentication

Base URL:

Loading... URL will be detected automatically based on your environment

Authentication

All API requests require an API key in the Authorization header:

Request Header
Authorization: Bearer YOUR_API_KEY

Generate API Key:

API Endpoints

Authentication Methods

šŸ” Session-based Auth: For UI operations (create, upload, init, train) - Login required via web interface

šŸ”‘ Bearer Token Auth: For API operations (model download/convert) - Use API key in Authorization header

Example: Authorization: Bearer aix_test123

POST /api/v1/projects šŸ”‘ Bearer Create new project
Request Body:
JSON
{
  "name": "my-project",
  "description": "My AI training project"
}
cURL Example
curl -X POST "/api/v1/projects" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "my-project", "description": "My AI training project"}'
POST /api/v1/projects/{project_id}/upload šŸ”‘ Bearer Upload training dataset
Path Parameters:
project_id String Project ID or name
Multipart Form Data:
files File[] Training images and labels (JPG, PNG, TXT, JSON)
cURL Example
curl -X POST "/api/v1/projects/my-project/upload" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "files=@image1.jpg" \
  -F "files=@image2.jpg" \
  -F "files=@label1.txt" \
  -F "files=@label2.txt"
POST /api/v1/projects/{project_id}/train šŸ”‘ Bearer Start model training
Path Parameters:
project_id String Project ID or name
Request Body (Optional):
JSON
{
  "epochs": 100,
  "batch_size": 16,
  "learning_rate": 0.001,
  "model_type": "yolo"
}
cURL Example
curl -X POST "/api/v1/projects/my-project/train" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"epochs": 100, "batch_size": 16, "learning_rate": 0.001}'
GET /api/v1/projects/{project_id}/status šŸ”‘ Bearer Check training status and progress
Path Parameters:
project_id String Project ID or name

Monitor training progress and check current status of the project.

Response:
JSON Response
{
  "status": "training",
  "progress": 75,
  "current_epoch": 75,
  "total_epochs": 100,
  "estimated_time_remaining": "250 seconds"
}
cURL Example
curl -X GET "/api/v1/projects/my-project/status" \
  -H "Authorization: Bearer YOUR_API_KEY"
POST /api/v1/projects/{project_id}/init šŸ”‘ Bearer Initialize project with AIX
Path Parameters:
project_id String Project ID or name
Request Body:
JSON
{
  "labels": "person,car,bike"
}
cURL Example
curl -X POST "/api/v1/projects/my-project/init" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"labels": "person,car,bike"}'
POST /api/v1/projects/{project_id}/convert šŸ”‘ Bearer Convert model to RKNN format
Path Parameters:
project_id String Project ID or name
Request Body (Optional):
JSON
{
  "target_platform": "rk3588"
}
cURL Example
curl -X POST "/api/v1/projects/my-project/convert" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"target_platform": "rk3588"}'
GET /api/v1/projects/{project_id}/download šŸ”‘ Bearer Download trained PT model
Path Parameters:
project_id String Project ID or name

Download the trained PyTorch model file (.pt) for the specified project. Training must be completed first.

cURL Example
curl -X GET "/api/v1/projects/my-project/download" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -o "my-project_best.pt"
GET /api/v1/projects/{project_id}/download-rknn šŸ”‘ Bearer Download RKNN model
Path Parameters:
project_id String Project ID or name

Download the converted RKNN model file (.rknn) for the specified project. Model conversion must be completed first.

cURL Example
curl -X GET "/api/v1/projects/my-project/download-rknn" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -o "my-project_model.rknn"
GET /api/v1/projects/{project_id}/models šŸ”‘ Bearer Check model availability
Path Parameters:
project_id String Project ID or name

Check which model formats are available for download.

Response:
JSON Response
{
  "pt_model": true,
  "rknn_model": false
}
cURL Example
curl -X GET "/api/v1/projects/my-project/models" \
  -H "Authorization: Bearer YOUR_API_KEY"
DELETE /api/v1/projects/{project_id}/clear šŸ”‘ Bearer Clear project data
Path Parameters:
project_id String Project ID or name

Clear all project data including images, labels, training outputs, and reset project status. This allows you to upload new data and start fresh training.

Warning

This action permanently deletes all project data including trained models. This cannot be undone.

Response:
JSON Response
{
  "message": "Project data cleared successfully",
  "project_id": "my-project",
  "status": "created",
  "cleared_at": "2024-01-15T10:30:00.000Z",
  "note": "Project is ready for new data upload and initialization"
}
cURL Example
curl -X DELETE "/api/v1/projects/my-project/clear" \
  -H "Authorization: Bearer YOUR_API_KEY"

Additional APIs (New Features)

POST /api/aix/convert-model-independent šŸ”‘ Bearer Convert .PT model to .RKNN independently

Upload and convert any .PT model to .RKNN format without requiring a project. Perfect for converting pre-trained models.

Request Body (Multipart Form):
modelFile File PyTorch model file (.pt format)
Response:
JSON Response
{
  "success": true,
  "message": "Model converted successfully",
  "rknnPath": "/temp/conversion/1642598400000/model.rknn",
  "modelFile": "my-model.pt",
  "conversionTime": "45.2 seconds"
}
cURL Example
curl -X POST "/api/aix/convert-model-independent" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "modelFile=@my-model.pt"
POST /api/aix/download-converted-rknn šŸ”‘ Bearer Download independently converted RKNN model

Download the converted .RKNN model file after independent conversion. Use the rknnPath from conversion response.

Request Body:
JSON
{
  "rknnPath": "/temp/conversion/1642598400000/model.rknn"
}
cURL Example
curl -X POST "/api/aix/download-converted-rknn" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"rknnPath": "/temp/conversion/1642598400000/model.rknn"}' \
  -o "converted-model.rknn"
GET /api/config šŸŒ Public Get server configuration

Retrieve server configuration information including base URL, host, port, and environment details.

Response:
JSON Response
{
  "serverUrl": "http://localhost:3000",
  "host": "localhost",
  "port": 3000,
  "isProduction": false
}
cURL Example
curl -X GET "/api/config"

Code Examples

Installation Requirements

Python Dependencies
# Install required Python packages
pip install requests pathlib

# Or create requirements.txt:
# requests>=2.28.0
# pathlib2>=2.3.0  # For Python < 3.4
Node.js Dependencies
# Install required Node.js packages
npm install axios form-data

# Or add to package.json:
# {
#   "dependencies": {
#     "axios": "^1.0.0",
#     "form-data": "^4.0.0"
#   }
# }

Python Example - Complete Client

Python requests
#!/usr/bin/env python3
"""
AIX API Python Client Example
Complete workflow for training and deploying AI models
"""

import requests
import os
import time
import json
from pathlib import Path

class AIXClient:
    def __init__(self, base_url="http://localhost:3000", api_key=None):
        """
        Initialize AIX API client
        
        Args:
            base_url: AIX server URL (default: http://localhost:3000)
            api_key: API key for Bearer token authentication (required for model operations)
        """
        self.base_url = base_url.rstrip('/')
        self.api_key = api_key
        self.session = requests.Session()
        
        # Set headers for API operations (model download/convert)
        if api_key:
            self.session.headers.update({
                'Authorization': f'Bearer {api_key}'
            })
    
    def create_project(self, name, description=""):
        """Create new project"""
        url = f"{self.base_url}/api/v1/projects"
        data = {"name": name, "description": description}
        
        response = self.session.post(url, json=data)
        response.raise_for_status()
        return response.json()
    
    def upload_dataset(self, project_id, images_dir, labels_dir=None):
        """
        Upload training dataset
        
        Args:
            project_id: Project ID or name
            images_dir: Directory containing training images
            labels_dir: Directory containing YOLO label files (optional)
        """
        url = f"{self.base_url}/api/v1/projects/{project_id}/upload"
        
        files = []
        
        # Upload images
        images_path = Path(images_dir)
        for img_file in images_path.glob("*"):
            if img_file.suffix.lower() in ['.jpg', '.jpeg', '.png', '.bmp']:
                files.append(('files', (img_file.name, open(img_file, 'rb'), 'image/jpeg')))
        
        # Upload labels if provided
        if labels_dir:
            labels_path = Path(labels_dir)
            for label_file in labels_path.glob("*.txt"):
                files.append(('files', (label_file.name, open(label_file, 'rb'), 'text/plain')))
        
        try:
            response = self.session.post(url, files=files)
            response.raise_for_status()
            return response.json()
        finally:
            # Close all opened files
            for _, file_tuple in files:
                if hasattr(file_tuple[1], 'close'):
                    file_tuple[1].close()
    
    def initialize_project(self, project_name):
        """Initialize AIX project"""
        url = f"{self.base_url}/api/aix/init"
        data = {"projectName": project_name}
        
        response = self.session.post(url, json=data)
        response.raise_for_status()
        return response.json()
    
    def start_training(self, project_name):
        """Start AIX training"""
        url = f"{self.base_url}/api/aix/train"
        data = {"projectName": project_name}
        
        response = self.session.post(url, json=data)
        response.raise_for_status()
        return response.json()
    
    def check_model_status(self, project_name):
        """Check if models are available for download"""
        if not self.api_key:
            raise ValueError("API key required for model operations")
            
        url = f"{self.base_url}/api/aix/model-status/{project_name}"
        response = self.session.get(url)
        response.raise_for_status()
        return response.json()
    
    def download_pytorch_model(self, project_name, output_path=None):
        """Download trained PyTorch model"""
        if not self.api_key:
            raise ValueError("API key required for model operations")
            
        url = f"{self.base_url}/api/aix/download-model/{project_name}"
        
        if not output_path:
            output_path = f"{project_name}_best.pt"
        
        response = self.session.get(url, stream=True)
        response.raise_for_status()
        
        with open(output_path, 'wb') as f:
            for chunk in response.iter_content(chunk_size=8192):
                f.write(chunk)
        
        return output_path
    
    def convert_to_rknn(self, project_name):
        """Convert PyTorch model to RKNN format"""
        if not self.api_key:
            raise ValueError("API key required for model operations")
            
        url = f"{self.base_url}/api/aix/convert-rknn/{project_name}"
        
        response = self.session.post(url, json={})
        response.raise_for_status()
        return response.json()
    
    def download_rknn_model(self, project_name, output_path=None):
        """Download converted RKNN model"""
        if not self.api_key:
            raise ValueError("API key required for model operations")
            
        url = f"{self.base_url}/api/aix/download-rknn/{project_name}"
        
        if not output_path:
            output_path = f"{project_name}_model.rknn"
        
        response = self.session.get(url, stream=True)
        response.raise_for_status()
        
        with open(output_path, 'wb') as f:
            for chunk in response.iter_content(chunk_size=8192):
                f.write(chunk)
        
        return output_path

def main():
    """Example usage of AIX API v1 client"""
    
    # Configuration
    API_KEY = "aix_your_api_key_here"  # Generate from API docs page
    BASE_URL = "http://localhost:3000"  # Change to your AIX server URL
    
    # Project configuration
    PROJECT_NAME = "my-detection-project"
    PROJECT_DESCRIPTION = "Object detection model for cars, people, and animals"
    IMAGES_DIR = "./dataset/images"
    LABELS_DIR = "./dataset/labels"  # Optional: YOLO format labels
    
    # Initialize client
    client = AIXClient(base_url=BASE_URL, api_key=API_KEY)
    
    try:
        print("šŸš€ Starting AIX v1 API training workflow...")
        
        # Step 1: Create project
        print(f"šŸ“ Creating project: {PROJECT_NAME}")
        result = client.create_project(PROJECT_NAME, PROJECT_DESCRIPTION)
        project_id = result.get("id") or PROJECT_NAME
        print(f"āœ… Project created: {result}")
        
        # Step 2: Upload dataset
        print(f"šŸ“¤ Uploading dataset from {IMAGES_DIR}")
        result = client.upload_dataset(project_id, IMAGES_DIR, LABELS_DIR)
        print(f"āœ… Dataset uploaded: {result}")
        
        # Step 3: Start training
        print(f"šŸ‹ļø Starting training for: {project_id}")
        result = client.start_training(project_id, epochs=100, batch_size=16)
        print(f"āœ… Training started: {result}")
        
        print("ā³ Training in progress... Monitor progress via status endpoint")
        
        # Step 4: Monitor training progress
        print("\nšŸ” Monitoring training progress...")
        max_attempts = 20
        for attempt in range(max_attempts):
            try:
                status = client.get_training_status(project_id)
                print(f"šŸ“Š Training status: {status}")
                
                if status.get("status") == "completed":
                    print("šŸŽ‰ Training completed successfully!")
                    break
                elif status.get("status") == "training":
                    progress = status.get("progress", 0)
                    current_epoch = status.get("current_epoch", 0)
                    total_epochs = status.get("total_epochs", 100)
                    eta = status.get("estimated_time_remaining", "Unknown")
                    print(f"ā³ Training in progress: {progress}% ({current_epoch}/{total_epochs} epochs) - ETA: {eta}")
                    time.sleep(30)  # Wait 30 seconds before next check
                else:
                    print(f"ā³ Waiting for training to start... (attempt {attempt + 1}/{max_attempts})")
                    time.sleep(15)
                    
            except requests.exceptions.HTTPError as e:
                if e.response.status_code == 404:
                    print("ā³ Project not found or not ready yet...")
                    time.sleep(30)
                else:
                    raise
        
        # Step 5: Download trained model
        final_status = client.get_training_status(project_id)
        
        if final_status.get("status") == "completed":
            print("šŸ“„ Downloading trained model...")
            model_path = client.download_model(project_id)
            print(f"āœ… Model downloaded: {model_path}")
        else:
            print("āš ļø Training not completed yet. You can download the model later using:")
            print(f"   client.download_model('{project_id}')")
        
        print("\nšŸŽ‰ AIX v1 workflow completed successfully!")
        
    except requests.exceptions.RequestException as e:
        print(f"āŒ API request failed: {e}")
        if hasattr(e, 'response') and e.response is not None:
            print(f"Response: {e.response.text}")
    except Exception as e:
        print(f"āŒ Error: {e}")

if __name__ == "__main__":
    main()

Python Example - Simple Usage

Simple Python Script
#!/usr/bin/env python3
"""
Simple AIX API Usage Example
Quick start for training and downloading models
"""

import requests
import os

# Configuration
API_KEY = "aix_your_generated_key"  # Get from API docs page
    BASE_URL = "http://localhost:3000"  # Your AIX server URL

def create_and_train_model():
    """Simple workflow to create project and start training"""
    headers = {"Authorization": f"Bearer {API_KEY}"}
    
    # 1. Create project
    project_data = {
        "name": "my-project",
        "description": "Simple object detection project"
    }
    
    response = requests.post(f"{BASE_URL}/api/v1/projects", json=project_data, headers=headers)
    print(f"āœ… Project created: {response.json()}")
    project_id = response.json().get("id", "my-project")
    
    # 2. Upload images
    files = []
    
    # Add your images
    if os.path.exists("./images"):
        for filename in os.listdir("./images"):
            if filename.lower().endswith(('.jpg', '.jpeg', '.png')):
                files.append(("files", open(f"./images/{filename}", "rb")))
    
    response = requests.post(f"{BASE_URL}/api/v1/projects/{project_id}/upload", files=files, headers=headers)
    print(f"āœ… Images uploaded: {response.json()}")
    
    # Close files
    for _, file_obj in files:
        file_obj.close()
    
    # 3. Start training
    training_config = {
        "epochs": 50,
        "batch_size": 16,
        "learning_rate": 0.001
    }
    response = requests.post(f"{BASE_URL}/api/v1/projects/{project_id}/train", json=training_config, headers=headers)
    print("šŸ‹ļø Training started! Monitor progress using status endpoint")
    return project_id

def download_trained_model(project_id):
    """Download trained model after training completes"""
    
    headers = {"Authorization": f"Bearer {API_KEY}"}
    
    # Check training status
    response = requests.get(f"{BASE_URL}/api/v1/projects/{project_id}/status", headers=headers)
    status = response.json()
    
    if status.get("status") == "completed":
        # Download trained model
        response = requests.get(f"{BASE_URL}/api/v1/projects/{project_id}/download", headers=headers)
        
        with open(f"{project_id}_model.pt", "wb") as f:
            f.write(response.content)
        
        print(f"āœ… Model downloaded: {project_id}_model.pt")
    else:
        print(f"ā³ Training status: {status.get('status')} - Progress: {status.get('progress', 0)}%")

if __name__ == "__main__":
    print("šŸš€ AIX v1 API Simple Example")
    
    # Step 1: Create project and start training
    project_id = create_and_train_model()
    
    # Step 2: Download models (run this after training completes)
    # Uncomment the line below when training is done
    # download_trained_model(project_id)

JavaScript/Node.js Example

Node.js / Browser
#!/usr/bin/env node
/**
 * AIX API JavaScript/Node.js Client Example
 * Complete workflow for training and deploying AI models
 */

const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
const path = require('path');

class AIXClient {
    constructor(baseUrl = 'http://localhost:3000', apiKey = null) {
        this.baseUrl = baseUrl.replace(/\/$/, '');
        this.apiKey = apiKey;
        
        // Create axios instance with default config
        this.client = axios.create({
            baseURL: this.baseUrl,
            timeout: 300000, // 5 minutes timeout for large uploads
        });
        
        // Set authorization header if API key provided
        if (apiKey) {
            this.client.defaults.headers.common['Authorization'] = `Bearer ${apiKey}`;
        }
    }
    
    async createProject(name, labels) {
        const response = await this.client.post('/api/aix/create-project', {
            name,
            labels
        });
        return response.data;
    }
    
    async uploadDataset(projectName, imagesDir, labelsDir = null) {
        const formData = new FormData();
        
        // Add project name
        formData.append('projectName', projectName);
        
        // Add images
        const imageFiles = fs.readdirSync(imagesDir);
        const imageExtensions = ['.jpg', '.jpeg', '.png', '.bmp'];
        
        for (const file of imageFiles) {
            const ext = path.extname(file).toLowerCase();
            if (imageExtensions.includes(ext)) {
                const filePath = path.join(imagesDir, file);
                formData.append('files', fs.createReadStream(filePath), file);
            }
        }
        
        // Add labels if provided
        if (labelsDir && fs.existsSync(labelsDir)) {
            const labelFiles = fs.readdirSync(labelsDir);
            for (const file of labelFiles) {
                if (path.extname(file).toLowerCase() === '.txt') {
                    const filePath = path.join(labelsDir, file);
                    formData.append('files', fs.createReadStream(filePath), file);
                }
            }
        }
        
        const response = await this.client.post('/api/aix/upload', formData, {
            headers: {
                ...formData.getHeaders(),
            },
            maxContentLength: Infinity,
            maxBodyLength: Infinity,
        });
        
        return response.data;
    }
    
    async initializeProject(projectName) {
        const response = await this.client.post('/api/aix/init', {
            projectName
        });
        return response.data;
    }
    
    async startTraining(projectName) {
        const response = await this.client.post('/api/aix/train', {
            projectName
        });
        return response.data;
    }
    
    async checkModelStatus(projectName) {
        if (!this.apiKey) {
            throw new Error('API key required for model operations');
        }
        
        const response = await this.client.get(`/api/aix/model-status/${projectName}`);
        return response.data;
    }
    
    async downloadPyTorchModel(projectName, outputPath = null) {
        if (!this.apiKey) {
            throw new Error('API key required for model operations');
        }
        
        if (!outputPath) {
            outputPath = `${projectName}_best.pt`;
        }
        
        const response = await this.client.get(`/api/aix/download-model/${projectName}`, {
            responseType: 'stream'
        });
        
        return new Promise((resolve, reject) => {
            const writer = fs.createWriteStream(outputPath);
            response.data.pipe(writer);
            
            writer.on('finish', () => resolve(outputPath));
            writer.on('error', reject);
        });
    }
    
    async convertToRKNN(projectName) {
        if (!this.apiKey) {
            throw new Error('API key required for model operations');
        }
        
        const response = await this.client.post(`/api/aix/convert-rknn/${projectName}`, {});
        return response.data;
    }
    
    async downloadRKNNModel(projectName, outputPath = null) {
        if (!this.apiKey) {
            throw new Error('API key required for model operations');
        }
        
        if (!outputPath) {
            outputPath = `${projectName}_model.rknn`;
        }
        
        const response = await this.client.get(`/api/aix/download-rknn/${projectName}`, {
            responseType: 'stream'
        });
        
        return new Promise((resolve, reject) => {
            const writer = fs.createWriteStream(outputPath);
            response.data.pipe(writer);
            
            writer.on('finish', () => resolve(outputPath));
            writer.on('error', reject);
        });
    }
}

async function main() {
    // Configuration
    const API_KEY = 'aix_your_api_key_here'; // Generate from API docs page
    const BASE_URL = 'http://localhost:3000'; // Change to your AIX server URL
    
    // Project configuration
    const PROJECT_NAME = 'my-detection-project';
    const LABELS = ['person', 'car', 'bicycle', 'dog', 'cat'];
    const IMAGES_DIR = './dataset/images';
    const LABELS_DIR = './dataset/labels'; // Optional: YOLO format labels
    
    // Initialize client
    const client = new AIXClient(BASE_URL, API_KEY);
    
    try {
        console.log('šŸš€ Starting AIX training workflow...');
        
        // Step 1: Create project
        console.log(`šŸ“ Creating project: ${PROJECT_NAME}`);
        const createResult = await client.createProject(PROJECT_NAME, LABELS);
        console.log('āœ… Project created:', createResult);
        
        // Step 2: Upload dataset
        console.log(`šŸ“¤ Uploading dataset from ${IMAGES_DIR}`);
        const uploadResult = await client.uploadDataset(PROJECT_NAME, IMAGES_DIR, LABELS_DIR);
        console.log('āœ… Dataset uploaded:', uploadResult);
        
        // Step 3: Initialize project
        console.log(`āš™ļø Initializing project: ${PROJECT_NAME}`);
        const initResult = await client.initializeProject(PROJECT_NAME);
        console.log('āœ… Project initialized:', initResult);
        
        // Step 4: Start training
        console.log(`šŸ‹ļø Starting training for: ${PROJECT_NAME}`);
        const trainResult = await client.startTraining(PROJECT_NAME);
        console.log('āœ… Training started:', trainResult);
        
        console.log('ā³ Training in progress... Monitor progress in AIX terminal');
        console.log('šŸ’” You can check model status periodically or wait for training completion');
        
        // Step 5: Wait and check model status (example polling)
        console.log('\nšŸ” Checking model status...');
        const maxAttempts = 10;
        let status;
        
        for (let attempt = 0; attempt < maxAttempts; attempt++) {
            try {
                status = await client.checkModelStatus(PROJECT_NAME);
                console.log('šŸ“Š Model status:', status);
                
                if (status.hasPt) {
                    console.log('šŸŽ‰ PyTorch model is ready!');
                    break;
                } else {
                    console.log(`ā³ Waiting for training completion... (attempt ${attempt + 1}/${maxAttempts})`);
                    await new Promise(resolve => setTimeout(resolve, 30000)); // Wait 30 seconds
                }
            } catch (error) {
                if (error.response?.status === 404) {
                    console.log('ā³ Model not ready yet, continuing to wait...');
                    await new Promise(resolve => setTimeout(resolve, 30000));
                } else {
                    throw error;
                }
            }
        }
        
        // Step 6: Download models if available
        status = await client.checkModelStatus(PROJECT_NAME);
        
        if (status.hasPt) {
            console.log('šŸ“„ Downloading PyTorch model...');
            const ptPath = await client.downloadPyTorchModel(PROJECT_NAME);
            console.log(`āœ… PyTorch model saved to: ${ptPath}`);
            
            // Step 7: Convert to RKNN (optional)
            console.log('šŸ”„ Converting to RKNN format...');
            const convertResult = await client.convertToRKNN(PROJECT_NAME);
            
            if (convertResult.success) {
                console.log('āœ… Model converted to RKNN successfully');
                
                // Step 8: Download RKNN model
                console.log('šŸ“„ Downloading RKNN model...');
                const rknnPath = await client.downloadRKNNModel(PROJECT_NAME);
                console.log(`āœ… RKNN model saved to: ${rknnPath}`);
            } else {
                console.log('āŒ RKNN conversion failed:', convertResult);
            }
        } else {
            console.log('āš ļø PyTorch model not available yet. Training may still be in progress.');
        }
        
        console.log('\nšŸŽ‰ AIX workflow completed successfully!');
        
    } catch (error) {
        console.error('āŒ Error:', error.response?.data || error.message);
        if (error.response?.data) {
            console.error('Response data:', error.response.data);
        }
    }
}

// Run if this file is executed directly
if (require.main === module) {
    main().catch(console.error);
}

module.exports = { AIXClient };

Response Codes

200 Success - Request completed successfully
201 Created - Resource created successfully
400 Bad Request - Invalid request format or parameters
401 Unauthorized - Invalid or missing API key
404 Not Found - Project or resource not found
500 Server Error - Internal server error