/api/wallets/receipts

GET

View transaction receipts or list all receipt files for a specified wallet.

Description

The `/api/wallets/receipts` endpoint provides access to transaction receipts stored in a wallet's Receipts folder. It operates in two modes:

  1. List Mode (no filename parameter): Returns a list of all receipt files available
  2. Read Mode (filename provided): Returns the full content of a specific receipt file

Receipts are auto-generated by CloudCoin deposit, upgrade, and locker operations and contain the aggregate totals plus a per-coin list of serial numbers, denominations, POWN authentication strings, and final bucket classifications.

💡 Use Case

This endpoint is perfect for:

  • Auditing transaction history and authentication results
  • Troubleshooting failed coin authentications
  • Reviewing detailed POWN strings for specific coins
  • Linking task IDs from transactions.csv to detailed receipts
  • Generating reports on wallet operations
📁 Receipt Storage

Receipts are stored in: [wallet]/Receipts/

Filename format: [task_id].json — the task_id is the same identifier returned by the originating deposit / upgrade / locker endpoint (e.g. Apr-23-26_10-30-12-AM-dc0f).

Example: Apr-23-26_10-30-12-AM-dc0f.json

⚠ Format Change

Receipts are now JSON documents (.json files), not plain text. The content field of a read-mode response returns a nested JSON object for new-style receipts and a string only for legacy .txt receipts still on disk. Clients that previously did JSON.parse(response.content) should use response.content directly.

Parameters

wallet_path is optional and defaults to the Default wallet. Omitting filename triggers List Mode.

wallet_path optional
string

Wallet path to inspect. If omitted, the Default wallet is used.

filename optional
string

The exact filename of the receipt to read (e.g., Apr-23-26_10-30-12-AM-dc0f.json).

If omitted: Returns list of all receipts.

If provided: Returns full content of the specified receipt file.

Response

Returns different JSON structures depending on the mode.

Mode 1: List All Receipts (No Filename)

Response Properties

command string
Always "receipts" in list mode.
success boolean
True for successful requests.
files array
Array of receipt filenames found in the Receipts folder.
count integer
Number of files returned.

Example Response (List Mode)

{
  "command": "receipts",
  "success": true,
  "files": [
    "Apr-23-26_10-30-12-AM-dc0f.json",
    "Apr-23-26_11-05-44-AM-b714.json",
    "Apr-23-26_02-18-03-PM-9c20.json"
  ],
  "count": 3
}

Mode 2: Read Specific Receipt (Filename Provided)

Response Properties

command string
Always "receipt" in read mode.
success boolean
True for successful requests.
filename string
The filename that was requested.
content object | string
The receipt body. For new-style .json receipts this is a nested JSON object matching the schema documented on the /api/transactions/deposit page (schema_version, type, totals, coins, etc.). For any legacy .txt receipts still on disk this is a string with newlines preserved. The read buffer ceiling is 1 MiB.
size integer
Number of bytes read from the receipt file.

Example Response (Read Mode — JSON receipt)

{
  "command": "receipt",
  "success": true,
  "filename": "Apr-23-26_10-30-12-AM-dc0f.json",
  "content": {
    "schema_version": 1,
    "type": "deposit",
    "date": "2026-04-23T10:30:45",
    "task_id": "Apr-23-26_10-30-12-AM-dc0f",
    "memo": "Monthly deposit",
    "totals": {
      "bank_count": 4, "fracked_count": 1,
      "limbo_count": 0, "counterfeit_count": 0,
      "duplicate_count": 0, "error_count": 0,
      "value_bank": 4, "value_fracked": 1,
      "value_limbo": 0, "value_counterfeit": 0,
      "total_deposited": 5
    },
    "per_coin_detail_truncated": false,
    "per_coin_detail_omitted_reason": null,
    "coins": [
      { "sn": 12345, "denom": 2, "pown": "AAAAA AAAAA AAAAA AAAAA AAAAA", "bucket": "Bank" },
      { "sn": 67890, "denom": 2, "pown": "AAAAA AAAAA AAAAF AAAAA AAAAA", "bucket": "Fracked" }
    ]
  },
  "size": 842
}

Example Response (Read Mode — legacy .txt receipt)

{
  "command": "receipt",
  "success": true,
  "filename": "2025-01-30_15-30-45.pown.txt",
  "content": "=== DEPOSIT RECEIPT ===\nDate: 2025-01-30 15:30:45\n...",
  "size": 320
}

Receipt File Format

New-style receipts are JSON documents. The full schema is documented on the /api/transactions/deposit page and is the same for deposits, upgrades, and locker operations; only the type field and the per-coin bucket values differ by operation.

Receipt Filename Patterns

Receipt filenames are [task_id].json. The task_id is the identifier returned by the originating async or locker endpoint — format MMM-DD-YY_HH-MM-SS-AM-XXXX where XXXX is a 4-hex random suffix (e.g. Apr-23-26_10-30-12-AM-dc0f).

Any legacy .txt receipts produced by older server builds are still readable via this endpoint — the content field is returned as a string in that case.

POWN String Interpretation

Each coin's pown field is a 29-character string: 25 status characters grouped into 5 blocks of 5 separated by spaces (e.g. "AAAAA AAAAA AAAAF AAAAA AAAAA"). Each character corresponds to one RAIDA server's authentication outcome:

  • A: Authentic & confirmed (success response)
  • F: Failed & confirmed (coin rejected)
  • a: Authentic, not yet re-tried on this run
  • N: Authentic last known, network error this run
  • S: Authentic last known, server error this run
  • T: Failed last known, timeout this run
  • X: Failed last known, network error this run
  • E: Failed last known, server error this run
  • t: Unknown, timeout this run
  • n: Unknown, network error this run
  • s: Unknown, server error this run
  • .: Unknown & untried
  • ?: Reserved / unrecognised state

Authentication threshold: 13+ As (out of 25) required for a coin to grade to the Bank bucket. 1-12 As grades to Fracked; 0 grades to Counterfeit; mixed unknown states land in Limbo.

Error Responses

No Active Wallet (HTTP 400)

{
  "command": "error",
  "message": "Wallet not found"
}

Receipt File Not Found (HTTP 404)

{
  "command": "error",
  "message": "Receipt file not found"
}

Examples

JavaScript (fetch)

Example 1: List All Receipts

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

async function listAllReceipts() {
    try {
        const response = await fetch(`${API_HOST}/api/wallets/receipts?wallet_path=${encodeURIComponent(walletPath)}`);
        const result = await response.json();

        console.log(`Wallet: ${result.wallet}`);
        console.log(`Total receipts: ${result.receipts.length}`);

        result.receipts.forEach(receipt => {
            console.log(`- ${receipt.filename}`);
        });
    } catch (error) {
        console.error('Error listing receipts:', error);
    }
}

listAllReceipts();

Example 2: Read Specific Receipt

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

async function readReceipt(walletPath, filename) {
    try {
        const encodedPath = encodeURIComponent(walletPath);
        const url = `${API_HOST}/api/wallets/receipts?wallet_path=${encodedPath}&filename=${encodeURIComponent(filename)}`;
        const response = await fetch(url);
        const result = await response.json();

        if (result.success) {
            console.log(`Receipt: ${result.filename}`);
            console.log('Content:');
            console.log(result.content);
        } else {
            console.error(`Error: ${result.message}`);
        }
    } catch (error) {
        console.error('Error reading receipt:', error);
    }
}

// Usage - Windows
readReceipt('E:/Client_Data/Wallets/Default', 'Apr-23-26_10-30-12-AM-dc0f.json');

// Usage - Linux/macOS
// readReceipt('E:/Client_Data/Wallets/Default', 'Apr-23-26_10-30-12-AM-dc0f.json');

Example 3: Parse Receipt Content

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

async function analyzeReceipt(walletPath, filename) {
    try {
        const encodedPath = encodeURIComponent(walletPath);
        const url = `${API_HOST}/api/wallets/receipts?wallet_path=${encodedPath}&filename=${encodeURIComponent(filename)}`;
        const response = await fetch(url);
        const result = await response.json();

        if (result.status !== 'success') {
            console.error(`Error: ${result.message}`);
            return;
        }

        const lines = result.content.split('\n');

        // Parse summary section
        const totalMatch = lines.find(l => l.includes('Total coins:'));
        const authMatch = lines.find(l => l.includes('Authenticated:'));
        const frackedMatch = lines.find(l => l.includes('Fracked:'));

        if (totalMatch && authMatch && frackedMatch) {
            const total = parseInt(totalMatch.split(':')[1].trim());
            const authenticated = parseInt(authMatch.split(':')[1].trim());
            const fracked = parseInt(frackedMatch.split(':')[1].trim());

            console.log(`Analysis of ${filename}:`);
            console.log(`- Success rate: ${((authenticated / total) * 100).toFixed(1)}%`);
            console.log(`- Fracked: ${fracked}`);
        }

        // Extract POWN strings
        const coinResults = lines.filter(l => l.includes('SN '));
        console.log('\nCoin Details:');
        coinResults.forEach(line => {
            const match = line.match(/SN (\d+) \((\d+)\): ([pufnebd]+)/);
            if (match) {
                const [, sn, denom, pown] = match;
                const passCount = (pown.match(/p/g) || []).length;
                console.log(`  SN ${sn}: ${passCount}/25 passes`);
            }
        });
    } catch (error) {
        console.error('Error analyzing receipt:', error);
    }
}

// Usage - Windows
analyzeReceipt('E:/Client_Data/Wallets/Default', 'Apr-23-26_10-30-12-AM-dc0f.json');

// Usage - Linux/macOS
// analyzeReceipt('E:/Client_Data/Wallets/Default', 'Apr-23-26_10-30-12-AM-dc0f.json');

cURL

Example 1: List All Receipts

# Windows
curl -X GET "http://localhost:8080/api/wallets/receipts?wallet_path=E:\Client_Data\Wallets\Default"

# Linux/macOS
# curl -X GET "http://localhost:8080/api/wallets/receipts?wallet_path=E:/Client_Data/Wallets/Default"

Example 2: Read Specific Receipt

# Windows
curl -X GET "http://localhost:8080/api/wallets/receipts?wallet_path=E:\Client_Data\Wallets\Default&filename=Apr-23-26_10-30-12-AM-dc0f.json"

# Linux/macOS
# curl -X GET "http://localhost:8080/api/wallets/receipts?wallet_path=E:/Client_Data/Wallets/Default&filename=Apr-23-26_10-30-12-AM-dc0f.json"

Example 3: Pretty Print Receipt Content

# Windows — .content is a JSON object for .json receipts; drill with jq
curl -X GET "http://localhost:8080/api/wallets/receipts?wallet_path=E:\Client_Data\Wallets\Default&filename=Apr-23-26_10-30-12-AM-dc0f.json" | jq '.content'

# Linux/macOS
# curl -X GET "http://localhost:8080/api/wallets/receipts?wallet_path=E:/Client_Data/Wallets/Default&filename=Apr-23-26_10-30-12-AM-dc0f.json" | jq '.content'

Go

Example 1: List All Receipts

package main

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

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

type Receipt struct {
    Filename string `json:"filename"`
}

type ReceiptListResponse struct {
    Status    string    `json:"command"`
    Operation string    `json:"success"`
    Wallet    string    `json:"wallet"`
    Receipts  []Receipt `json:"receipts"`
}

func main() {
    // Windows path
    walletPath := "E:/Client_Data/Wallets/Default"
    // Linux/macOS path
    // walletPath := "E:/Client_Data/Wallets/Default"

    url := fmt.Sprintf("%s/api/wallets/receipts?wallet_path=%s", ApiHost, walletPath)
    resp, err := http.Get(url)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

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

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

    fmt.Printf("Wallet: %s\n", result.Wallet)
    fmt.Printf("Total receipts: %d\n", len(result.Receipts))

    for _, receipt := range result.Receipts {
        fmt.Printf("- %s\n", receipt.Filename)
    }
}

Example 2: Read Specific Receipt

package main

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

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

type ReceiptResponse struct {
    Status    string `json:"command"`
    Operation string `json:"success"`
    Wallet    string `json:"wallet"`
    Filename  string `json:"filename"`
    Content   string `json:"content"`
}

func main() {
    // Windows path
    walletPath := "E:/Client_Data/Wallets/Default"
    // Linux/macOS path
    // walletPath := "E:/Client_Data/Wallets/Default"

    filename := "Apr-23-26_10-30-12-AM-dc0f.json"

    u, _ := url.Parse(fmt.Sprintf("%s/api/wallets/receipts", ApiHost))
    q := u.Query()
    q.Set("wallet_path", walletPath)
    q.Set("filename", filename)
    u.RawQuery = q.Encode()

    resp, err := http.Get(u.String())
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

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

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

    if result.Status == "success" {
        fmt.Printf("Receipt: %s\n", result.Filename)
        fmt.Println("Content:")
        fmt.Println(result.Content)
    } else {
        fmt.Printf("Error reading receipt\n")
    }
}

Example 3: Parse Receipt Statistics

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "net/url"
    "regexp"
    "strconv"
    "strings"
)

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

type ReceiptResponse struct {
    Status    string `json:"command"`
    Operation string `json:"success"`
    Wallet    string `json:"wallet"`
    Filename  string `json:"filename"`
    Content   string `json:"content"`
}

func analyzeReceipt(walletPath, filename string) {
    u, _ := url.Parse(fmt.Sprintf("%s/api/wallets/receipts", ApiHost))
    q := u.Query()
    q.Set("wallet_path", walletPath)
    q.Set("filename", filename)
    u.RawQuery = q.Encode()

    resp, err := http.Get(u.String())
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

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

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

    if result.Status != "success" {
        fmt.Println("Error reading receipt")
        return
    }

    lines := strings.Split(result.Content, "\n")

    // Parse summary
    for _, line := range lines {
        if strings.Contains(line, "Total coins:") {
            parts := strings.Split(line, ":")
            if len(parts) == 2 {
                fmt.Printf("Total coins: %s\n", strings.TrimSpace(parts[1]))
            }
        } else if strings.Contains(line, "Authenticated:") {
            parts := strings.Split(line, ":")
            if len(parts) == 2 {
                fmt.Printf("Authenticated: %s\n", strings.TrimSpace(parts[1]))
            }
        }
    }

    // Extract POWN strings
    re := regexp.MustCompile(`SN (\d+) \((\d+)\): ([pufnebd]+)`)
    fmt.Println("\nCoin Details:")
    for _, line := range lines {
        matches := re.FindStringSubmatch(line)
        if len(matches) == 4 {
            sn := matches[1]
            pown := matches[3]
            passCount := strings.Count(pown, "p")
            fmt.Printf("  SN %s: %d/25 passes\n", sn, passCount)
        }
    }
}

func main() {
    // Windows path
    walletPath := "E:/Client_Data/Wallets/Default"
    // Linux/macOS path
    // walletPath := "E:/Client_Data/Wallets/Default"

    analyzeReceipt(walletPath, "Apr-23-26_10-30-12-AM-dc0f.json")
}

Related Endpoints

/api/wallets/transactions

View transaction history from transactions.csv. Task IDs link to receipt files.

/api/wallets/show-coins

View coins in wallet folders (Bank, Fracked, Counterfeit, etc.).

/api/coin/pown

Authenticate coins and generate POWN receipts automatically.