/api/transactions/import

POST ASYNC

Import specific CloudCoin files from absolute file paths with a transaction memo. Files are moved to the Import folder and processed asynchronously with RAIDA authentication.

POST http://localhost:8080/api/transactions/import
Content-Type: application/json

Description

The `/api/transactions/import` endpoint provides an advanced way to import CloudCoin files from specific absolute file paths anywhere on the filesystem. This is the more flexible import option compared to `/api/coins/import` (which auto-scans the Import folder), as it lets you:

  • Specify exact files: Import from any absolute path on the filesystem
  • Add transaction memo: Include a memo for record-keeping and audit trails
  • Track progress: Use the task ID to monitor the asynchronous import operation
  • Create receipts: Automatic transaction receipt generation in the Receipts folder
💡 Asynchronous Processing

This endpoint returns immediately with a task ID. The import operation runs in a background thread, authenticating coins with all 25 RAIDA servers in parallel. Use /api/transactions/task?id=[task_id] to check progress and results.

🔄 Complete Import Workflow

Step 1: Files are moved (not copied) from absolute paths to [wallet]/Import/
Step 2: Background thread authenticates coins with RAIDA (Detect command 0x010A)
Step 3: POWN strings updated based on RAIDA responses (13+ passes = authentic)
Step 4: Authenticated coins → [wallet]/Bank/
Step 5: Fracked coins (partial passes) → [wallet]/Fracked/
Step 6: Counterfeit coins → [wallet]/Counterfeit/
Step 7: Transaction receipt saved to [wallet]/Receipts/[task_id].import.txt

⚠️ Important: Atomic Move Operation

Files are moved (not copied) using atomic rename operations. The original files will no longer exist at their source paths after the import request is accepted. Ensure:

  • Files are not in use by other applications
  • You have write permissions for both source and destination paths
  • Source and destination are on the same filesystem (for atomic rename)
📊 vs. /api/coins/import

Use /api/transactions/import when: You need to import from specific paths with memos and receipts
Use /api/coins/import when: You just want to scan and import everything from the Import folder

Request Body Parameters

Send a JSON object in the request body with the following properties:

Parameter Type Required Description
files array[string] Yes Array of absolute file paths to CloudCoin files (.bin, .stack, .jpeg, .jpg, .png). Maximum 100 files per request. Each path must be absolute and accessible from the server.
memo string Optional Transaction memo for record-keeping. Will be included in the receipt file in [wallet]/Receipts/. If omitted, no memo will be recorded.
📝 Request Body Example
{
  "files": [
    "C:\\Downloads\\coins1.bin",
    "C:\\Downloads\\stack25.stack"
  ],
  "memo": "Import from exchange"
}

Response

Returns a JSON object with a task ID to track the asynchronous import operation.

Response Properties

status string
Always "success" if the request was accepted.
operation string
The operation type - "import".
task_id string
Unique task identifier to check import progress and results.
message string
Confirmation message - "Import started in background".
file_count integer
Number of files successfully moved to Import folder and queued for processing.

Example Response (Success)

{
  "status": "success",
  "operation": "import",
  "task_id": "Jan-31-25_03-45-12-PM",
  "message": "Import task started successfully",
  "file_count": 2
}

Example Error Response (Missing Parameter)

{
  "error": "Missing required parameter: files (array of absolute paths)"
}

Example Error Response (File Not Found)

{
  "error": "File not found: C:\\Downloads\\coins.stack"
}

Examples

JavaScript (fetch) - Complete Workflow

const API_HOST = 'http://localhost:8080';

async function importSpecificFiles(filePaths, memo) {
    try {
        // Step 1: Start import with POST JSON body
        const response = await fetch(`${API_HOST}/api/transactions/import`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                files: filePaths,
                memo: memo
            })
        });

        const result = await response.json();

        if (result.status === 'success') {
            console.log(`Import started with task ID: ${result.task_id}`);
            console.log(`Processing ${result.file_count} files`);

            // Step 2: Poll for completion
            const taskResult = await pollTaskStatus(result.task_id);

            // Step 3: Check receipt for details
            if (taskResult.status === 'completed') {
                console.log('Import complete! Check receipt at:');
                console.log(`[wallet]/Receipts/${result.task_id}.import.txt`);

                // Step 4: Check updated balance
                await checkBalance();
            }
        } else {
            console.error('Import failed:', result.error);
        }
    } catch (error) {
        console.error('Error importing files:', error);
    }
}

async function pollTaskStatus(taskId) {
    while (true) {
        const response = await fetch(`${API_HOST}/api/transactions/task?id=${taskId}`);
        const task = await response.json();

        console.log(`Status: ${task.status}, Progress: ${task.progress || 0}%`);

        if (task.status === 'completed') {
            console.log('Import complete:', task);
            return task;
        } else if (task.status === 'error' || task.status === 'failed') {
            console.error('Import failed:', task.message);
            throw new Error(task.message);
        }

        // Poll every second
        await new Promise(resolve => setTimeout(resolve, 1000));
    }
}

async function checkBalance() {
    const response = await fetch(`${API_HOST}/api/wallet/balance`);
    const balance = await response.json();
    console.log('New wallet balance:', balance);
}

// Example: Import files from Downloads folder
importSpecificFiles([
    'C:\\Downloads\\coins1.bin',
    'C:\\Downloads\\stack25.stack'
], 'Import from exchange');

cURL - Complete Workflow

# Step 1: Start import with POST JSON body
curl -X POST "http://localhost:8080/api/transactions/import" \
  -H "Content-Type: application/json" \
  -d '{
    "files": [
      "C:\\Downloads\\coins1.bin",
      "C:\\Downloads\\stack25.stack"
    ],
    "memo": "Import from exchange"
  }'

# Response:
# {
#   "status": "success",
#   "operation": "import",
#   "task_id": "Jan-31-25_03-45-12-PM",
#   "message": "Import task started successfully",
#   "file_count": 2
# }

# Step 2: Poll task status
curl -X GET "http://localhost:8080/api/transactions/task?id=Jan-31-25_03-45-12-PM"

# Step 3: Check receipt (after completion)
# Receipt saved to: [wallet]/Receipts/Jan-31-25_03-45-12-PM.import.txt

# Step 4: Check wallet balance
curl -X GET "http://localhost:8080/api/wallet/balance"

# Example: Single file import with no memo
curl -X POST "http://localhost:8080/api/transactions/import" \
  -H "Content-Type: application/json" \
  -d '{
    "files": ["/tmp/payment.stack"]
  }'

Go - Complete Workflow

package main

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

const ApiHost = "http://localhost:8080"

type ImportRequest struct {
    Files []string `json:"files"`
    Memo  string   `json:"memo,omitempty"`
}

type ImportResponse struct {
    Status    string `json:"status"`
    Operation string `json:"operation"`
    TaskID    string `json:"task_id"`
    Message   string `json:"message"`
    FileCount int    `json:"file_count"`
}

type TaskStatus struct {
    Status   string `json:"status"`
    Progress int    `json:"progress"`
    Message  string `json:"message"`
}

type WalletBalance struct {
    TotalValue int `json:"total_value"`
    CoinCount  int `json:"coin_count"`
}

func importFiles(filePaths []string, memo string) error {
    // Step 1: Start import with POST JSON body
    requestBody := ImportRequest{
        Files: filePaths,
        Memo:  memo,
    }

    jsonData, err := json.Marshal(requestBody)
    if err != nil {
        return err
    }

    requestURL := fmt.Sprintf("%s/api/transactions/import", ApiHost)
    resp, err := http.Post(requestURL, "application/json", bytes.NewBuffer(jsonData))
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    body, _ := ioutil.ReadAll(resp.Body)

    var result ImportResponse
    if err := json.Unmarshal(body, &result); err != nil {
        return err
    }

    if result.Status != "success" {
        return fmt.Errorf("import failed: %s", result.Message)
    }

    fmt.Printf("Import started with task ID: %s\n", result.TaskID)
    fmt.Printf("Processing %d files\n", result.FileCount)

    // Step 2: Poll for completion
    if err := pollTaskStatus(result.TaskID); err != nil {
        return err
    }

    // Step 3: Check receipt
    fmt.Printf("Receipt saved to: [wallet]/Receipts/%s.import.txt\n", result.TaskID)

    // Step 4: Check updated balance
    return checkBalance()
}

func pollTaskStatus(taskID string) error {
    for {
        requestURL := fmt.Sprintf("%s/api/transactions/task?id=%s", ApiHost, taskID)
        resp, err := http.Get(requestURL)
        if err != nil {
            return err
        }

        body, _ := ioutil.ReadAll(resp.Body)
        resp.Body.Close()

        var task TaskStatus
        if err := json.Unmarshal(body, &task); err != nil {
            return err
        }

        fmt.Printf("Status: %s, Progress: %d%%\n", task.Status, task.Progress)

        if task.Status == "completed" {
            fmt.Println("Import complete!")
            return nil
        } else if task.Status == "error" || task.Status == "failed" {
            return fmt.Errorf("import failed: %s", task.Message)
        }

        time.Sleep(1 * time.Second)
    }
}

func checkBalance() error {
    requestURL := fmt.Sprintf("%s/api/wallet/balance", ApiHost)
    resp, err := http.Get(requestURL)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    body, _ := ioutil.ReadAll(resp.Body)

    var balance WalletBalance
    if err := json.Unmarshal(body, &balance); err != nil {
        return err
    }

    fmt.Printf("New wallet balance: %d CloudCoins, Total value: %d\n",
        balance.CoinCount, balance.TotalValue)
    return nil
}

func main() {
    filePaths := []string{
        "C:\\Downloads\\coins1.bin",
        "C:\\Downloads\\stack25.stack",
    }

    if err := importFiles(filePaths, "Import from exchange"); err != nil {
        fmt.Printf("Error: %v\n", err)
    }
}

Related Endpoints

/api/coins/import

Simpler alternative that automatically scans and imports all files from the Import folder. Use this for basic imports without custom file paths or memos.

/api/transactions/task

Check the status and progress of the asynchronous import operation using the task ID. Essential for monitoring long-running imports.

/api/wallet/receipt

View the detailed transaction receipt after import completes. Shows authentication results, coin counts, and POWN strings.

/api/wallet/balance

After import completes, check your wallet balance to see the newly imported coins added to your Bank folder.