/api/wallets/receipts
GETView 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:
- List Mode (no filename parameter): Returns a list of all receipt files available
- 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.
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
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
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 to inspect. If omitted, the Default wallet is used.
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
"receipts" in list mode.Receipts folder.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
"receipt" in read mode..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.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.).