# MyCloudVault Backup Restore API

## Overview

The Backup Restore API enables Android devices to download and restore backup files from MyCloudVault servers. It includes backup listing, downloading, and deletion capabilities with device authorization.

---

## API Endpoints

### Base URL
```
https://vm6tgfyizy.preview.c24.airoapp.ai
```

---

## 1. List Backups

**Endpoint:** `GET /api/backup/list`

**Purpose:** Get all backups for a device.

**Query Parameters:**
- `deviceId` (required): Device ID
- `limit` (optional): Number of backups to return (default: 50, max: 200)
- `offset` (optional): Pagination offset (default: 0)

**Example Request:**
```
GET /api/backup/list?deviceId=android-123&limit=10
```

**Response:**
```json
{
  "success": true,
  "backups": [
    {
      "id": 1,
      "backupId": "a1b2c3d4e5f6...",
      "deviceId": "android-123",
      "backupType": "full",
      "status": "completed",
      "size": 1250,
      "filePath": "/private/backups/android-123/a1b2c3d4e5f6_1702411200000.zip",
      "metadata": "{\"appVersion\":\"1.0.0\"}",
      "startedAt": "2025-12-12T21:00:00.000Z",
      "completedAt": "2025-12-12T21:00:30.000Z"
    },
    {
      "id": 2,
      "backupId": "b2c3d4e5f6g7...",
      "deviceId": "android-123",
      "backupType": "incremental",
      "status": "completed",
      "size": 450,
      "filePath": "/private/backups/android-123/b2c3d4e5f6g7_1702497600000.zip",
      "startedAt": "2025-12-13T21:00:00.000Z",
      "completedAt": "2025-12-13T21:00:15.000Z"
    }
  ],
  "total": 2,
  "limit": 10,
  "offset": 0
}
```

---

## 2. Download Backup

**Endpoint:** `GET /api/backup/download/:backupId`

**Purpose:** Download a backup file for restore.

**Query Parameters:**
- `deviceId` (required): Device ID for authorization

**Example Request:**
```
GET /api/backup/download/a1b2c3d4e5f6?deviceId=android-123
```

**Response:**
- **Content-Type:** `application/octet-stream`
- **Content-Disposition:** `attachment; filename="a1b2c3d4e5f6_1702411200000.zip"`
- **Body:** Binary file stream

**Error Response:**
```json
{
  "success": false,
  "error": "Backup not found"
}
```

**Status Codes:**
- `200`: Success - file stream
- `400`: Bad request - missing parameters
- `403`: Forbidden - unauthorized device
- `404`: Not found - backup doesn't exist
- `500`: Server error

---

## 3. Delete Backup

**Endpoint:** `DELETE /api/backup/delete/:backupId`

**Purpose:** Delete a backup file and its database record.

**Query Parameters:**
- `deviceId` (required): Device ID for authorization

**Example Request:**
```
DELETE /api/backup/delete/a1b2c3d4e5f6?deviceId=android-123
```

**Response:**
```json
{
  "success": true,
  "message": "Backup deleted successfully"
}
```

**Error Response:**
```json
{
  "success": false,
  "error": "Unauthorized: Backup belongs to different device"
}
```

---

## Implementation Examples

### Android (Kotlin) - List Backups

```kotlin
import okhttp3.*
import org.json.JSONObject

class BackupManager(private val deviceId: String) {
    private val client = OkHttpClient()
    private val baseUrl = "https://vm6tgfyizy.preview.c24.airoapp.ai"

    fun listBackups(limit: Int = 50): List<Backup> {
        val request = Request.Builder()
            .url("$baseUrl/api/backup/list?deviceId=$deviceId&limit=$limit")
            .get()
            .build()

        val response = client.newCall(request).execute()
        if (!response.isSuccessful) {
            throw Exception("Failed to fetch backups: ${response.message}")
        }

        val json = JSONObject(response.body()?.string())
        val backupsArray = json.getJSONArray("backups")
        
        return (0 until backupsArray.length()).map { i ->
            val backup = backupsArray.getJSONObject(i)
            Backup(
                id = backup.getInt("id"),
                backupId = backup.getString("backupId"),
                backupType = backup.getString("backupType"),
                status = backup.getString("status"),
                size = backup.getInt("size"),
                completedAt = backup.getString("completedAt")
            )
        }
    }
}

data class Backup(
    val id: Int,
    val backupId: String,
    val backupType: String,
    val status: String,
    val size: Int,
    val completedAt: String
)

// Usage
val manager = BackupManager("android-123")
val backups = manager.listBackups()
backups.forEach { backup ->
    println("${backup.backupType} backup: ${backup.size} MB")
}
```

### Android (Kotlin) - Download Backup

```kotlin
import okhttp3.*
import java.io.File
import java.io.FileOutputStream

class BackupDownloader(private val deviceId: String) {
    private val client = OkHttpClient()
    private val baseUrl = "https://vm6tgfyizy.preview.c24.airoapp.ai"

    fun downloadBackup(
        backupId: String,
        destinationFile: File,
        onProgress: (Long, Long) -> Unit
    ): Boolean {
        val request = Request.Builder()
            .url("$baseUrl/api/backup/download/$backupId?deviceId=$deviceId")
            .get()
            .build()

        val response = client.newCall(request).execute()
        if (!response.isSuccessful) {
            return false
        }

        val body = response.body() ?: return false
        val contentLength = body.contentLength()
        
        body.byteStream().use { input ->
            FileOutputStream(destinationFile).use { output ->
                val buffer = ByteArray(8192)
                var bytesRead: Int
                var totalBytesRead = 0L

                while (input.read(buffer).also { bytesRead = it } != -1) {
                    output.write(buffer, 0, bytesRead)
                    totalBytesRead += bytesRead
                    onProgress(totalBytesRead, contentLength)
                }
            }
        }

        return true
    }
}

// Usage
val downloader = BackupDownloader("android-123")
val backupFile = File("/sdcard/Download/backup.zip")

val success = downloader.downloadBackup("a1b2c3d4e5f6", backupFile) { downloaded, total ->
    val progress = (downloaded.toFloat() / total * 100).toInt()
    println("Download progress: $progress%")
}

if (success) {
    println("Backup downloaded to ${backupFile.absolutePath}")
} else {
    println("Download failed")
}
```

### Android (Kotlin) - Delete Backup

```kotlin
import okhttp3.*
import org.json.JSONObject

class BackupDeleter(private val deviceId: String) {
    private val client = OkHttpClient()
    private val baseUrl = "https://vm6tgfyizy.preview.c24.airoapp.ai"

    fun deleteBackup(backupId: String): Boolean {
        val request = Request.Builder()
            .url("$baseUrl/api/backup/delete/$backupId?deviceId=$deviceId")
            .delete()
            .build()

        val response = client.newCall(request).execute()
        if (!response.isSuccessful) {
            return false
        }

        val json = JSONObject(response.body()?.string())
        return json.getBoolean("success")
    }
}

// Usage
val deleter = BackupDeleter("android-123")
val success = deleter.deleteBackup("a1b2c3d4e5f6")

if (success) {
    println("Backup deleted successfully")
} else {
    println("Failed to delete backup")
}
```

### Android (Kotlin) - Complete Restore Flow

```kotlin
import android.app.Activity
import android.os.Bundle
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.*

class RestoreActivity : Activity() {
    private val deviceId = "android-123"
    private val backupManager = BackupManager(deviceId)
    private val backupDownloader = BackupDownloader(deviceId)
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_restore)
        
        loadBackups()
    }
    
    private fun loadBackups() {
        CoroutineScope(Dispatchers.IO).launch {
            try {
                val backups = backupManager.listBackups()
                withContext(Dispatchers.Main) {
                    displayBackups(backups)
                }
            } catch (e: Exception) {
                withContext(Dispatchers.Main) {
                    showError("Failed to load backups: ${e.message}")
                }
            }
        }
    }
    
    private fun restoreBackup(backup: Backup) {
        CoroutineScope(Dispatchers.IO).launch {
            try {
                val tempFile = File(cacheDir, "restore_${backup.backupId}.zip")
                
                withContext(Dispatchers.Main) {
                    showProgress("Downloading backup...")
                }
                
                val success = backupDownloader.downloadBackup(
                    backup.backupId,
                    tempFile
                ) { downloaded, total ->
                    val progress = (downloaded.toFloat() / total * 100).toInt()
                    CoroutineScope(Dispatchers.Main).launch {
                        updateProgress(progress)
                    }
                }
                
                if (success) {
                    withContext(Dispatchers.Main) {
                        showProgress("Extracting backup...")
                    }
                    
                    // Extract and restore files
                    extractBackup(tempFile)
                    
                    withContext(Dispatchers.Main) {
                        showSuccess("Backup restored successfully")
                    }
                } else {
                    withContext(Dispatchers.Main) {
                        showError("Failed to download backup")
                    }
                }
            } catch (e: Exception) {
                withContext(Dispatchers.Main) {
                    showError("Restore failed: ${e.message}")
                }
            }
        }
    }
    
    private fun extractBackup(zipFile: File) {
        // Implement zip extraction and file restoration
        // This is app-specific based on what was backed up
    }
}
```

---

## Security & Authorization

### Device Ownership Verification

All endpoints verify that the requesting device owns the backup:

```kotlin
// Server-side check
if (backupRecord.deviceId !== deviceId) {
  return res.status(403).json({
    success: false,
    error: 'Unauthorized: Backup belongs to different device'
  });
}
```

### Best Practices

1. **Always include deviceId**: Required for authorization
2. **Handle 403 errors**: Device doesn't own the backup
3. **Verify file integrity**: Check file size after download
4. **Clean up temp files**: Delete downloaded files after restore
5. **Show progress**: Keep user informed during long downloads

---

## Error Handling

### Common Errors

| Status Code | Error | Solution |
|-------------|-------|----------|
| 400 | Missing deviceId | Include deviceId query parameter |
| 403 | Unauthorized | Verify device owns the backup |
| 404 | Backup not found | Check backupId is correct |
| 500 | Server error | Retry with exponential backoff |

### Retry Logic

```kotlin
fun downloadWithRetry(
    backupId: String,
    destinationFile: File,
    maxRetries: Int = 3
): Boolean {
    var attempt = 0
    var delay = 1000L // Start with 1 second
    
    while (attempt < maxRetries) {
        try {
            return downloadBackup(backupId, destinationFile) { _, _ -> }
        } catch (e: Exception) {
            attempt++
            if (attempt >= maxRetries) {
                throw e
            }
            Thread.sleep(delay)
            delay *= 2 // Exponential backoff
        }
    }
    
    return false
}
```

---

## Dashboard Integration

The MyCloudVault dashboard displays backup history with restore options:

### Features

- **Backup List**: Shows all backups with type, size, and date
- **Download Button**: Downloads backup file to browser
- **Delete Button**: Removes backup with confirmation
- **Auto-refresh**: Updates every 10 seconds
- **Real-time Status**: Shows loading states and errors

### Usage

1. Navigate to dashboard
2. View backup history section
3. Click "Download" to restore a backup
4. Click trash icon to delete old backups

---

## Performance Considerations

### Large File Downloads

- Files are streamed, not loaded into memory
- Progress tracking available
- Resume capability (future enhancement)

### Bandwidth Optimization

- Use chunked transfer encoding
- Compress backups before upload
- Consider incremental backups for large datasets

---

## Future Enhancements

1. **Resume Downloads**: Continue interrupted downloads
2. **Backup Verification**: Checksum validation
3. **Selective Restore**: Restore specific files/folders
4. **Backup Encryption**: End-to-end encryption
5. **Backup Scheduling**: Automatic restore scheduling
6. **Version Comparison**: Compare backup versions

---

## Support

For issues or questions, refer to the main MyCloudVault documentation.
