The Ashfolio application provides a local REST API for accessing portfolio data. The API is available only on localhost and requires no authentication, making it suitable for local development, testing, and personal automation scripts.
Base URL: http://localhost:4000/api/v1
Authentication: None required (localhost-only access)
Content-Type: application/json
Get a comprehensive summary of the portfolio including total value, returns, and key metrics.
GET /api/v1/portfolio/summaryResponse:
{
"total_value": "25000.00",
"cost_basis": "22500.00",
"total_return": "2500.00",
"total_return_percent": "11.11",
"holdings_count": 5,
"last_updated": "2025-08-06T10:30:00Z"
}Response Fields:
total_value: Current total portfolio value in USDcost_basis: Total amount invested (cost basis) in USDtotal_return: Dollar amount of gains/losses in USDtotal_return_percent: Percentage return on investmentholdings_count: Number of unique holdings in portfoliolast_updated: Timestamp of last price update (ISO 8601 format)
Get detailed information about all current holdings in the portfolio.
GET /api/v1/holdingsResponse:
{
"holdings": [
{
"symbol": "AAPL",
"name": "Apple Inc.",
"quantity": "100.00",
"current_price": "150.00",
"current_value": "15000.00",
"cost_basis": "13500.00",
"average_cost": "135.00",
"unrealized_pnl": "1500.00",
"unrealized_pnl_pct": "11.11"
},
{
"symbol": "MSFT",
"name": "Microsoft Corporation",
"quantity": "50.00",
"current_price": "200.00",
"current_value": "10000.00",
"cost_basis": "9000.00",
"average_cost": "180.00",
"unrealized_pnl": "1000.00",
"unrealized_pnl_pct": "11.11"
}
]
}Holdings Object Fields:
symbol: Stock ticker symbolname: Company or security namequantity: Number of shares heldcurrent_price: Current market price per sharecurrent_value: Total current value (quantity × current_price)cost_basis: Total amount paid for this holdingaverage_cost: Average cost per share (cost_basis ÷ quantity)unrealized_pnl: Unrealized profit/loss in dollarsunrealized_pnl_pct: Unrealized profit/loss as percentage
Get information about all investment accounts.
GET /api/v1/accountsResponse:
{
"accounts": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Schwab Brokerage",
"platform": "Schwab",
"balance": "25000.00",
"is_excluded": false,
"transaction_count": 15,
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-08-06T10:30:00Z"
}
]
}Account Object Fields:
id: Unique account identifier (UUID)name: User-defined account nameplatform: Brokerage platform (e.g., "Schwab", "Fidelity")balance: Current account balance in USDis_excluded: Whether account is excluded from portfolio calculationstransaction_count: Number of transactions in this accountcreated_at: Account creation timestamp (ISO 8601)updated_at: Last modification timestamp (ISO 8601)
Get all transactions with optional filtering by account or date range.
GET /api/v1/transactions
GET /api/v1/transactions?account_id={account_id}
GET /api/v1/transactions?start_date={YYYY-MM-DD}&end_date={YYYY-MM-DD}Query Parameters:
account_id(optional): Filter transactions by account UUIDstart_date(optional): Filter transactions from this date (YYYY-MM-DD format)end_date(optional): Filter transactions to this date (YYYY-MM-DD format)limit(optional): Maximum number of transactions to return (default: 100)offset(optional): Number of transactions to skip for pagination (default: 0)
Response:
{
"transactions": [
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"type": "BUY",
"symbol": "AAPL",
"symbol_name": "Apple Inc.",
"account_name": "Schwab Brokerage",
"quantity": "100.00",
"price": "135.00",
"fee": "9.95",
"total_amount": "13509.95",
"date": "2025-01-15",
"comment": "Initial AAPL position",
"created_at": "2025-01-15T14:30:00Z"
}
],
"pagination": {
"total": 150,
"limit": 100,
"offset": 0,
"has_more": true
}
}Transaction Object Fields:
id: Unique transaction identifier (UUID)type: Transaction type (BUY, SELL, DIVIDEND, FEE, INTEREST)symbol: Stock ticker symbolsymbol_name: Company or security nameaccount_name: Name of the account this transaction belongs toquantity: Number of shares (positive for BUY, negative for SELL)price: Price per share at time of transactionfee: Transaction fee charged by brokertotal_amount: Total transaction amount including feesdate: Transaction date (YYYY-MM-DD format)comment: Optional user commentcreated_at: Transaction creation timestamp (ISO 8601)
Trigger a manual refresh of current market prices for all holdings.
POST /api/v1/prices/refreshResponse:
{
"status": "success",
"message": "Prices refreshed successfully",
"updated_symbols": ["AAPL", "MSFT", "GOOGL"],
"failed_symbols": [],
"refresh_timestamp": "2025-08-06T10:35:00Z"
}Response Fields:
status: "success" or "error"message: Human-readable status messageupdated_symbols: Array of symbols that were successfully updatedfailed_symbols: Array of symbols that failed to updaterefresh_timestamp: Timestamp when refresh was completed
All endpoints may return error responses in the following format:
{
"error": {
"code": "INVALID_REQUEST",
"message": "The requested resource was not found",
"details": "Account with ID 550e8400-e29b-41d4-a716-446655440000 does not exist"
}
}Common Error Codes:
INVALID_REQUEST: Malformed request or invalid parametersNOT_FOUND: Requested resource does not existSERVER_ERROR: Internal server errorSERVICE_UNAVAILABLE: External service (e.g., Yahoo Finance) unavailable
HTTP Status Codes:
200 OK: Request successful400 Bad Request: Invalid request parameters404 Not Found: Resource not found500 Internal Server Error: Server error503 Service Unavailable: External service unavailable
curl http://localhost:4000/api/v1/portfolio/summarycurl http://localhost:4000/api/v1/holdings | jq '.holdings[] | select(.unrealized_pnl_pct > 10)'curl -X POST http://localhost:4000/api/v1/prices/refreshcurl http://localhost:4000/api/v1/transactions | jq -r '.transactions[] | [.date, .type, .symbol, .quantity, .price, .total_amount] | @csv'The API has no rate limiting since it's designed for localhost-only access. However, the price refresh endpoint is limited to one request per minute to avoid overwhelming external market data providers.
- ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ) for timestamps, YYYY-MM-DD for date-only fields
- USD amounts as decimal strings with 2 decimal places (e.g., "1234.56")
- Share quantities as decimal strings with up to 6 decimal places (e.g., "100.000000")
- Percentage values as decimal strings (e.g., "11.11" for 11.11%)
- The API is only accessible from localhost (127.0.0.1)
- No API keys or authentication required
- Uses HTTP since it's localhost-only
- Cross-origin requests are not supported
This API is designed for local development, testing, and personal automation. It should not be exposed to external networks or used in production environments without proper security measures.