/api/transactions/task
GETQuery the status, progress, and results of asynchronous operations using task IDs.
Description
The `/api/transactions/task` endpoint (also accessible as `/api/task`) retrieves the real-time status and results of asynchronous operations. When you initiate operations like import, authenticate, or fix, they return immediately with a task ID. Use this endpoint to poll for completion and retrieve final results.
- Start Operation: Call an async endpoint (e.g., /api/transactions/import)
- Receive Task ID: The response includes a unique task_id
- Poll Status: Call /api/task?task_id=... repeatedly (every 1-2 seconds)
- Check Progress: Monitor the progress field (0-100)
- Get Results: When status="success" and progress=100, read final results from data field
Task status files are stored in [data_path]/Tasks/[task_id].json and updated in real-time by background threads. This endpoint reads and returns the raw JSON file contents (max 64KB file size).
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
task_id |
string | Yes | Task identifier in format MMM-DD-YY_HH-MM-SS-AM/PM (e.g., "Jan-31-25_03-45-12-PM"). Returned by async operation endpoints. |
Response
Returns the raw task status JSON file. The structure varies by operation type, but all tasks share common fields.
Common Response Properties
Example Response (Import Operation - Completed)
{
"status": "success",
"task_id": "Oct-26-25_09-15-16-AM",
"progress": 100,
"message": "Import, authentication, and grading complete",
"data": {
"total_processed": 2,
"already_exists": 0,
"pown_results": {
"bank": 2,
"fracked": 0,
"counterfeit": 0,
"limbo": 0,
"errors": 0,
"suspect": 0
},
"receipt_id": "Oct-26-25_09-15-16-AM"
}
}
Example Response (Import Operation - In Progress)
{
"status": "running",
"task_id": "Nov-01-25_05-49-16-PM",
"progress": 45,
"message": "Authenticating coins with RAIDA servers...",
"data": {
"total_processed": 0,
"already_exists": 0,
"pown_results": {
"bank": 0,
"fracked": 0,
"counterfeit": 0,
"limbo": 0,
"errors": 0,
"suspect": 0
}
}
}
Example Response (Authenticate Operation - Completed)
{
"status": "success",
"task_id": "Jan-31-25_03-45-12-PM",
"progress": 100,
"message": "Authentication and grading complete",
"data": {
"operation": "authenticate",
"coins_processed": 12,
"coins_authenticated": 10,
"coins_fracked": 2,
"coins_counterfeit": 0,
"raida_responses": {
"average_time_ms": 1234,
"timeouts": 0,
"errors": 1
},
"receipt_id": "Jan-31-25_03-45-12-PM"
}
}
Example Response (Fix Operation - Completed)
{
"status": "success",
"task_id": "Jan-31-25_04-12-30-PM",
"progress": 100,
"message": "Healing complete - 3 coins fully recovered, 1 remains fracked",
"data": {
"operation": "fix",
"rounds_completed": 3,
"coins_healed": 3,
"coins_still_fracked": 1,
"coins_lost": 0,
"receipt_id": "Jan-31-25_04-12-30-PM"
}
}
Error Responses
Missing Parameter (400)
{
"error": "Missing required parameter: task_id"
}
Task Not Found (404)
{
"error": "Task ID not found"
}
Invalid File Size (500)
{
"error": "Invalid task status file size (must be ≤64KB)"
}
Task ID Format
Task IDs are human-readable timestamps generated by the task manager when operations start.
Format: MMM-DD-YY_HH-MM-SS-AM/PM
Examples:
Jan-31-25_03-45-12-PM- January 31, 2025 at 3:45:12 PMOct-26-25_09-15-16-AM- October 26, 2025 at 9:15:16 AMNov-01-25_05-49-16-PM- November 1, 2025 at 5:49:16 PM
Generated by: task_manager_generate_id() in C backend
Examples
JavaScript (fetch)
const API_HOST = 'http://localhost:8080';
// Simple polling function
async function getTaskStatus(taskId) {
try {
const response = await fetch(`${API_HOST}/api/task?task_id=${taskId}`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const task = await response.json();
return task;
} catch (error) {
console.error('Error fetching task status:', error);
throw error;
}
}
// Poll until completion
async function waitForTaskCompletion(taskId, pollIntervalMs = 1000) {
console.log(`Waiting for task ${taskId} to complete...`);
while (true) {
const task = await getTaskStatus(taskId);
console.log(`Progress: ${task.progress}% - ${task.message}`);
if (task.status === 'success' && task.progress === 100) {
console.log('Task completed successfully!');
console.log('Final results:', task.data);
return task;
} else if (task.status === 'error') {
console.error('Task failed:', task.message);
throw new Error(task.message);
}
// Wait before next poll
await new Promise(resolve => setTimeout(resolve, pollIntervalMs));
}
}
// Example usage
async function importAndWait(files, memo) {
// Start import
const filesParam = files.join(',');
const importUrl = `${API_HOST}/api/transactions/import?` +
`files=${encodeURIComponent(filesParam)}&` +
`memo=${encodeURIComponent(memo)}`;
const importResp = await fetch(importUrl);
const importResult = await importResp.json();
if (importResult.status !== 'success') {
throw new Error('Import failed to start');
}
console.log(`Import started with task ID: ${importResult.task_id}`);
// Wait for completion
const finalTask = await waitForTaskCompletion(importResult.task_id);
console.log(`Imported ${finalTask.data.total_processed} files`);
console.log(`Bank: ${finalTask.data.pown_results.bank} coins`);
console.log(`Fracked: ${finalTask.data.pown_results.fracked} coins`);
}
// Run example
importAndWait([
'C:\\Users\\User\\Downloads\\coins.stack'
], 'Payment received');
cURL
# Query task status (full endpoint)
curl -X GET "http://localhost:8080/api/transactions/task?task_id=Jan-31-25_03-45-12-PM"
# Query task status (short endpoint)
curl -X GET "http://localhost:8080/api/task?task_id=Oct-26-25_09-15-16-AM"
# Poll in a loop (Bash)
TASK_ID="Nov-01-25_05-49-16-PM"
while true; do
RESPONSE=$(curl -s "http://localhost:8080/api/task?task_id=$TASK_ID")
echo "$RESPONSE" | jq .
STATUS=$(echo "$RESPONSE" | jq -r .status)
PROGRESS=$(echo "$RESPONSE" | jq -r .progress)
if [ "$STATUS" = "success" ] && [ "$PROGRESS" = "100" ]; then
echo "Task completed!"
break
elif [ "$STATUS" = "error" ]; then
echo "Task failed!"
break
fi
sleep 1
done
Go
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"
)
const ApiHost = "http://localhost:8080"
type TaskStatus struct {
Status string `json:"status"`
TaskID string `json:"task_id"`
Progress int `json:"progress"`
Message string `json:"message"`
Data map[string]interface{} `json:"data"`
}
type POWNResults struct {
Bank int `json:"bank"`
Fracked int `json:"fracked"`
Counterfeit int `json:"counterfeit"`
Limbo int `json:"limbo"`
Errors int `json:"errors"`
Suspect int `json:"suspect"`
}
func getTaskStatus(taskID string) (*TaskStatus, error) {
url := fmt.Sprintf("%s/api/task?task_id=%s", ApiHost, taskID)
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
body, _ := ioutil.ReadAll(resp.Body)
return nil, fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(body))
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var task TaskStatus
if err := json.Unmarshal(body, &task); err != nil {
return nil, err
}
return &task, nil
}
func waitForCompletion(taskID string, pollInterval time.Duration) (*TaskStatus, error) {
fmt.Printf("Waiting for task %s to complete...\n", taskID)
for {
task, err := getTaskStatus(taskID)
if err != nil {
return nil, err
}
fmt.Printf("Progress: %d%% - %s\n", task.Progress, task.Message)
if task.Status == "success" && task.Progress == 100 {
fmt.Println("Task completed successfully!")
return task, nil
} else if task.Status == "error" {
return nil, fmt.Errorf("task failed: %s", task.Message)
}
time.Sleep(pollInterval)
}
}
func main() {
// Example: Check specific task
taskID := "Oct-26-25_09-15-16-AM"
task, err := getTaskStatus(taskID)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Task Status: %s\n", task.Status)
fmt.Printf("Progress: %d%%\n", task.Progress)
fmt.Printf("Message: %s\n", task.Message)
// Pretty print data
dataJSON, _ := json.MarshalIndent(task.Data, "", " ")
fmt.Printf("Data:\n%s\n", string(dataJSON))
// Example: Wait for completion
// finalTask, err := waitForCompletion(taskID, 1*time.Second)
// if err != nil {
// fmt.Printf("Error: %v\n", err)
// }
}
Implementation Details
The endpoint is fully implemented as a pass-through file reader:
- Validates
task_idparameter exists - Constructs file path:
[data_path]/Tasks/[task_id].json - Checks if file exists (404 if not found)
- Reads JSON file contents (max 64KB)
- Returns raw JSON content with
Content-Type: application/json
Source: api_handlers.c lines 598-664
- Created: When async operation starts (by background thread)
- Updated: Continuously during operation (progress, status, data)
- Finalized: When operation completes or errors
- Persisted: Files remain in Tasks folder for historical reference
Related Endpoints
/api/transactions/import
Import CloudCoin files from absolute paths. Returns a task_id for progress tracking.
/api/coins/authenticate
Authenticate coins with RAIDA servers. Async operation returns task_id.
/api/wallet/receipt
View detailed transaction receipts. Tasks include a receipt_id field linking to full receipts.
/api/wallet/transactions
List all transaction history. Each transaction has an associated task_id.