/backup

POST ASYNC

Creates a compressed backup of a specific wallet or all existing wallets to a specified folder on the server.

POST /api/v1/backup
Alias: /create-wallet-backup

Description

The `/backup` endpoint is a critical tool for data preservation and disaster recovery. It creates a compressed `.zip` archive of all coin files from either a single specified wallet or all wallets in the system. The backup is saved to a folder on the server's local filesystem.

You can specify a wallet by `name` or omit it to back up all wallets. An optional `tag` can be added for easier identification of the backup file.

💡 Data Safety

Regularly backing up your wallets is the most important step in protecting your assets against data loss. This endpoint provides a simple, automatable way to secure your data.

Asynchronous Workflow

Understanding Asynchronous API Calls

This endpoint is asynchronous, which means:

  1. You send a `POST` request with the backup parameters.
  2. The server immediately responds with a task ID.
  3. You then periodically poll the /api/v1/tasks/{id} endpoint to check the progress.
  4. Once the `status` is "completed", the `data` field will contain a summary of the backup operation.

Request Body

The request must include a JSON body specifying the backup destination and parameters.

Parameter Type Required Description
folder string Yes The absolute path to a folder on the server where the backup file(s) will be saved.
name string No The name of the wallet to back up. If omitted or empty, all wallets will be backed up.
tag string No An optional tag to include in the backup filename for easier identification (e.g., "monthly-backup").

Example Request (Backup a Single Wallet)

{
    "name": "Default",
    "folder": "/var/backups/cloudcoin",
    "tag": "user_archive"
}

Example Request (Backup All Wallets)

{
    "name": "",
    "folder": "/var/backups/cloudcoin",
    "tag": "full_system_backup"
}

Response

After the asynchronous task finishes successfully, the task status endpoint (/api/v1/tasks/{id}) returns a `200 OK` response. The `payload` of this response contains the final status and the result of the backup operation in the `data` field.

Response Properties (within `data` object)

wallets_processedinteger
The total number of wallets that were processed.
coins_backed_upinteger
The total number of individual coin files included in the backup(s).
output_filesarray of strings
A list of the full paths to the generated backup `.zip` files.

Example Response (from task endpoint after completion)

{
  "status": "success",
  "payload": {
    "id": "e8a1b2c3-d4e5-f678-9012-34567890abcd",
    "status": "completed",
    "progress": 100,
    "message": "Command Completed",
    "data": {
      "wallets_processed": 1,
      "coins_backed_up": 1250,
      "output_files": [
        "/var/backups/cloudcoin/Default-monthly-backup-20250708.zip"
      ]
    }
  }
}

Examples

JavaScript (async/await)

const API_HOST = 'http://localhost:8006';
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

async function backupWallet() {
    try {
        const backupPayload = {
            name: "Default",
            folder: "/var/backups/cloudcoin",
            tag: "monthly-backup"
        };
        const initialResponse = await fetch(`${API_HOST}/api/v1/backup`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(backupPayload)
        });
        const task = await initialResponse.json();
        console.log(`Backup task created with ID: ${task.id}`);
        while (true) {
            const statusResponse = await fetch(`${API_HOST}/api/v1/tasks/${task.id}`);
            const taskStatus = await statusResponse.json();
            console.log(`Task progress: ${taskStatus.progress}%`);
            if (taskStatus.status === 'completed') {
                console.log('Backup complete:', taskStatus.data);
                break;
            } else if (taskStatus.status === 'error') {
                 console.error('Task failed:', taskStatus.message);
                 break;
            }
            await sleep(1000);
        }
    } catch (error) {
        console.error('An error occurred:', error);
    }
}

backupWallet();

cURL

# Step 1: Initiate the backup task
TASK_ID=$(curl -s -X POST "http://localhost:8006/api/v1/backup" \
-H "Content-Type: application/json" \
-d '{"name": "Default", "folder": "/var/backups/cloudcoin", "tag": "manual"}' | jq -r .id)
echo "Backup task started with ID: $TASK_ID"

# Step 2: Poll the task endpoint until finished
while true; do
  RESPONSE=$(curl -s "http://localhost:8006/api/v1/tasks/$TASK_ID")
  STATUS=$(echo $RESPONSE | jq -r .status)
  echo "Polling task... Status: $STATUS"
  if [[ "$STATUS" == "completed" || "$STATUS" == "error" ]]; then
    echo "Final Response:"
    echo $RESPONSE | jq
    break
  fi
  sleep 2
done

Go

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
    "time"
)

const ApiHost = "http://localhost:8006"
type BackupRequest struct {
    Name   string `json:"name"`
    Folder string `json:"folder"`
    Tag    string `json:"tag"`
}
type TaskResponse struct {
    ID       string          `json:"id"`
    Status   string          `json:"status"`
    Progress int             `json:"progress"`
    Data     json.RawMessage `json:"data,omitempty"`
}

func main() {
    backupPayload := BackupRequest{Name: "Default", Folder: "/var/backups/cloudcoin", Tag: "go-backup"}
    payloadBytes, _ := json.Marshal(backupPayload)
    
    req, _ := http.NewRequest("POST", fmt.Sprintf("%s/api/v1/backup", ApiHost), bytes.NewBuffer(payloadBytes))
    req.Header.Set("Content-Type", "application/json")
    
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil { panic(err) }
    defer resp.Body.Close()

    var task TaskResponse
    json.NewDecoder(resp.Body).Decode(&task)
    fmt.Printf("Backup task created with ID: %s\n", task.ID)
    
    for {
        taskResp, _ := http.Get(fmt.Sprintf("%s/api/v1/tasks/%s", ApiHost, task.ID))
        var taskStatus TaskResponse
        json.NewDecoder(taskResp.Body).Decode(&taskStatus)
        taskResp.Body.Close()
        
        fmt.Printf("Task status: %s, Progress: %d%%\n", taskStatus.Status, taskStatus.Progress)
        if taskStatus.Status == "completed" || taskStatus.Status == "error" {
            fmt.Printf("Final result: %s\n", string(taskStatus.Data))
            break
        }
        time.Sleep(1 * time.Second)
    }
}