API Reference
Complete reference for Wealthfolio addon APIs.
API Reference
Complete reference for APIs available to Wealthfolio addons. All functions require appropriate permissions in manifest.json
.
Context Overview
The AddonContext
is provided to your addon’s enable
function:
export interface AddonContext {
api: HostAPI;
sidebar: SidebarAPI;
router: RouterAPI;
onDisable: (callback: () => void) => void;
}
Basic usage:
export default function enable(ctx: AddonContext) {
// Access APIs
const accounts = await ctx.api.accounts.getAll();
const holdings = await ctx.api.portfolio.getHoldings('account-123');
// UI integration
ctx.sidebar.addItem({ /* ... */ });
ctx.router.add({ /* ... */ });
// Cleanup
ctx.onDisable(() => {
// cleanup code
});
}
API Domains
The API is organized into 16 domains:
Domain | Description | Key Functions |
---|---|---|
Accounts | Account management | getAll , create |
Portfolio | Holdings and valuations | getHoldings , getIncomeSummary , update , recalculate |
Activities | Trading transactions | getAll , create , import , search , update |
Market | Market data and symbols | searchTicker , sync , getProviders |
Performance | Performance metrics | calculateHistory , calculateSummary |
Assets | Asset profiles | getProfile , updateProfile , updateDataSource |
Quotes | Price quotes | update , getHistory |
Goals | Financial goals | getAll , create , update , getAllocations |
Contribution Limits | Investment limits | getAll , create , update , calculateDeposits |
Exchange Rates | Currency rates | getAll , update , add |
Settings | App configuration | get , update , backupDatabase |
Files | File operations | openCsvDialog , openSaveDialog |
Events | Real-time events | onUpdateComplete , onSyncComplete , onDrop |
Secrets | Secure storage | get , set , delete |
Logger | Logging operations | error , info , warn , debug , trace |
Navigation | Route navigation | navigate |
Query | React Query integration | getClient , invalidateQueries , refetchQueries |
Accounts API
Manage user accounts with full CRUD operations.
getAll(): Promise<Account[]>
Retrieves all user accounts.
const accounts = await ctx.api.accounts.getAll();
interface Account {
id: string;
name: string;
currency: string;
isActive: boolean;
totalValue?: number;
createdAt: string;
updatedAt: string;
}
create(account: AccountCreate): Promise<Account>
Creates a new account with validation.
const newAccount = await ctx.api.accounts.create({
name: 'My Investment Account',
currency: 'USD',
isActive: true
});
Data Validation: Account creation includes validation for currency codes, name uniqueness, and other business rules.
Portfolio API
Access portfolio data, holdings, and performance information with real-time updates.
Methods
getHoldings(accountId: string): Promise<Holding[]>
Gets all holdings for a specific account with current valuations.
const holdings = await ctx.api.portfolio.getHoldings('account-123');
// Example holding structure
interface Holding {
id: string;
accountId: string;
symbol: string;
quantity: number;
marketValue: number;
totalCost: number;
averagePrice: number;
gainLoss: number;
gainLossPercent: number;
currency: string;
assetType: 'Stock' | 'ETF' | 'Bond' | 'Crypto' | 'Other';
}
getHolding(accountId: string, assetId: string): Promise<Holding | null>
Gets a specific holding with detailed information.
const holding = await ctx.api.portfolio.getHolding('account-123', 'AAPL');
update(): Promise<void>
Triggers a portfolio update/recalculation across all accounts.
await ctx.api.portfolio.update();
recalculate(): Promise<void>
Forces a complete portfolio recalculation from scratch.
await ctx.api.portfolio.recalculate();
getIncomeSummary(): Promise<IncomeSummary[]>
Gets comprehensive income summary across all accounts.
const income = await ctx.api.portfolio.getIncomeSummary();
getHistoricalValuations(accountId?: string, startDate?: string, endDate?: string): Promise<AccountValuation[]>
Gets historical portfolio valuations for charts and analysis.
const history = await ctx.api.portfolio.getHistoricalValuations(
'account-123', // optional, omit for all accounts
'2024-01-01',
'2024-12-31'
);
getLatestValuations(accountIds: string[]): Promise<AccountValuation[]>
Gets latest valuations for a set of accounts.
const valuations = await ctx.api.portfolio.getLatestValuations(['account-1', 'account-2']);
Activities API
Manage trading activities, transactions, and data imports with advanced search capabilities.
Methods
getAll(accountId?: string): Promise<ActivityDetails[]>
Gets all activities, optionally filtered by account.
// All activities across all accounts
const allActivities = await ctx.api.activities.getAll();
// Activities for specific account
const accountActivities = await ctx.api.activities.getAll('account-123');
search(page: number, pageSize: number, filters: any, searchKeyword: string, sort: any): Promise<ActivitySearchResponse>
Advanced search with pagination and filters.
const results = await ctx.api.activities.search(
1, // page
50, // pageSize
{ // filters
accountId: 'account-123',
activityType: 'BUY',
symbol: 'AAPL',
startDate: '2024-01-01',
endDate: '2024-12-31'
},
'AAPL', // searchKeyword
{ field: 'date', direction: 'desc' } // sort
);
create(activity: ActivityCreate): Promise<Activity>
Creates a new activity with validation.
const activity = await ctx.api.activities.create({
accountId: 'account-123',
activityType: 'BUY',
symbol: 'AAPL',
quantity: 100,
unitPrice: 150.50,
currency: 'USD',
date: '2024-12-01',
isDraft: false
});
update(activity: ActivityUpdate): Promise<Activity>
Updates an existing activity with conflict detection.
const updated = await ctx.api.activities.update({
...existingActivity,
quantity: 150,
unitPrice: 145.75
});
saveMany(activities: ActivityUpdate[]): Promise<Activity[]>
Efficiently creates multiple activities in a single transaction.
const activities = await ctx.api.activities.saveMany([
{ accountId: 'account-123', activityType: 'BUY', /* ... */ },
{ accountId: 'account-123', activityType: 'DIVIDEND', /* ... */ }
]);
delete(activityId: string): Promise<void>
Deletes an activity and updates portfolio calculations.
await ctx.api.activities.delete('activity-456');
import(activities: ActivityImport[]): Promise<ActivityImport[]>
Imports validated activities with duplicate detection.
const imported = await ctx.api.activities.import(checkedActivities);
checkImport(accountId: string, activities: ActivityImport[]): Promise<ActivityImport[]>
Validates activities before import with error reporting.
const validated = await ctx.api.activities.checkImport('account-123', activities);
getImportMapping(accountId: string): Promise<ImportMappingData>
Get import mapping configuration for an account.
const mapping = await ctx.api.activities.getImportMapping('account-123');
saveImportMapping(mapping: ImportMappingData): Promise<ImportMappingData>
Save import mapping configuration.
const savedMapping = await ctx.api.activities.saveImportMapping(mapping);
Activity Types Reference
Type | Use Case | Cash Impact | Holdings Impact |
---|---|---|---|
BUY | Purchase securities | Decreases cash | Increases quantity |
SELL | Dispose of securities | Increases cash | Decreases quantity |
DIVIDEND | Cash dividend received | Increases cash | No change |
INTEREST | Interest earned | Increases cash | No change |
DEPOSIT | Add funds | Increases cash | No change |
WITHDRAWAL | Remove funds | Decreases cash | No change |
TRANSFER_IN | Assets moved in | Varies | Increases quantity |
TRANSFER_OUT | Assets moved out | Varies | Decreases quantity |
FEE | Brokerage fees | Decreases cash | No change |
TAX | Taxes paid | Decreases cash | No change |
Market Data API
Access market data, search symbols, and sync with external providers.
Methods
searchTicker(query: string): Promise<QuoteSummary[]>
Search for ticker symbols across multiple data providers.
const results = await ctx.api.market.searchTicker('AAPL');
syncHistory(): Promise<void>
Syncs historical market data for all portfolio holdings.
await ctx.api.market.syncHistory();
sync(symbols: string[], refetchAll: boolean): Promise<void>
Syncs market data for specific symbols with cache control.
// Sync latest data (uses cache if recent)
await ctx.api.market.sync(['AAPL', 'MSFT', 'GOOGL'], false);
// Force refresh all data
await ctx.api.market.sync(['AAPL', 'MSFT', 'GOOGL'], true);
getProviders(): Promise<MarketDataProviderInfo[]>
Gets available market data providers and their status.
const providers = await ctx.api.market.getProviders();
Assets API
Access and manage asset profiles and data sources.
Methods
getProfile(assetId: string): Promise<Asset>
Gets detailed asset profile information.
const asset = await ctx.api.assets.getProfile('AAPL');
updateProfile(payload: UpdateAssetProfile): Promise<Asset>
Updates asset profile information.
const updatedAsset = await ctx.api.assets.updateProfile({
symbol: 'AAPL',
name: 'Apple Inc.',
assetType: 'Stock',
// ... other profile data
});
updateDataSource(symbol: string, dataSource: string): Promise<Asset>
Updates the data source for an asset.
const asset = await ctx.api.assets.updateDataSource('AAPL', 'YAHOO');
Quotes API
Manage price quotes and historical data.
Methods
update(symbol: string, quote: Quote): Promise<void>
Updates quote information for a symbol.
await ctx.api.quotes.update('AAPL', {
symbol: 'AAPL',
price: 150.50,
date: '2024-12-01',
// ... other quote data
});
getHistory(symbol: string): Promise<Quote[]>
Gets historical quotes for a symbol.
const history = await ctx.api.quotes.getHistory('AAPL');
Performance API
Calculate portfolio and account performance metrics with historical analysis.
Methods
calculateHistory(itemType: 'account' | 'symbol', itemId: string, startDate: string, endDate: string): Promise<PerformanceMetrics>
Calculates detailed performance history for charts and analysis.
const history = await ctx.api.performance.calculateHistory(
'account',
'account-123',
'2024-01-01',
'2024-12-31'
);
calculateSummary(args: { itemType: 'account' | 'symbol'; itemId: string; startDate?: string | null; endDate?: string | null; }): Promise<PerformanceMetrics>
Calculates comprehensive performance summary with key metrics.
const summary = await ctx.api.performance.calculateSummary({
itemType: 'account',
itemId: 'account-123',
startDate: '2024-01-01',
endDate: '2024-12-31'
});
calculateAccountsSimple(accountIds: string[]): Promise<SimplePerformanceMetrics[]>
Calculates simple performance metrics for multiple accounts efficiently.
const performance = await ctx.api.performance.calculateAccountsSimple([
'account-123',
'account-456'
]);
Exchange Rates API
Manage currency exchange rates for multi-currency portfolios.
Methods
getAll(): Promise<ExchangeRate[]>
Gets all exchange rates.
const rates = await ctx.api.exchangeRates.getAll();
update(updatedRate: ExchangeRate): Promise<ExchangeRate>
Updates an existing exchange rate.
const updatedRate = await ctx.api.exchangeRates.update({
id: 'rate-123',
fromCurrency: 'USD',
toCurrency: 'EUR',
rate: 0.85,
// ... other rate data
});
add(newRate: Omit<ExchangeRate, 'id'>): Promise<ExchangeRate>
Adds a new exchange rate.
const newRate = await ctx.api.exchangeRates.add({
fromCurrency: 'USD',
toCurrency: 'GBP',
rate: 0.75,
// ... other rate data
});
Contribution Limits API
Manage investment contribution limits and calculations.
Methods
getAll(): Promise<ContributionLimit[]>
Gets all contribution limits.
const limits = await ctx.api.contributionLimits.getAll();
create(newLimit: NewContributionLimit): Promise<ContributionLimit>
Creates a new contribution limit.
const limit = await ctx.api.contributionLimits.create({
name: 'RRSP 2024',
limitType: 'RRSP',
maxAmount: 30000,
year: 2024,
// ... other limit data
});
update(id: string, updatedLimit: NewContributionLimit): Promise<ContributionLimit>
Updates an existing contribution limit.
const updatedLimit = await ctx.api.contributionLimits.update('limit-123', {
name: 'Updated RRSP 2024',
maxAmount: 31000,
// ... other updated data
});
calculateDeposits(limitId: string): Promise<DepositsCalculation>
Calculates deposits for a specific contribution limit.
const deposits = await ctx.api.contributionLimits.calculateDeposits('limit-123');
Goals API
Manage financial goals and allocations.
Methods
getAll(): Promise<Goal[]>
Gets all goals.
const goals = await ctx.api.goals.getAll();
create(goal: any): Promise<Goal>
Creates a new goal.
const goal = await ctx.api.goals.create({
name: 'Retirement Fund',
targetAmount: 500000,
targetDate: '2040-01-01',
// ... other goal data
});
update(goal: Goal): Promise<Goal>
Updates an existing goal.
const updatedGoal = await ctx.api.goals.update({
...existingGoal,
targetAmount: 600000,
});
updateAllocations(allocations: GoalAllocation[]): Promise<void>
Updates goal allocations.
await ctx.api.goals.updateAllocations([
{ goalId: 'goal-123', accountId: 'account-456', percentage: 50 },
// ... other allocations
]);
getAllocations(): Promise<GoalAllocation[]>
Gets goal allocations.
const allocations = await ctx.api.goals.getAllocations();
Settings API
Manage application settings and configuration.
Methods
get(): Promise<Settings>
Gets application settings.
const settings = await ctx.api.settings.get();
update(settingsUpdate: Settings): Promise<Settings>
Updates application settings.
const updatedSettings = await ctx.api.settings.update({
...currentSettings,
baseCurrency: 'EUR',
// ... other settings
});
backupDatabase(): Promise<{ filename: string; data: Uint8Array }>
Creates a database backup.
const backup = await ctx.api.settings.backupDatabase();
Files API
Handle file operations and dialogs.
Methods
openCsvDialog(): Promise<null | string | string[]>
Opens a CSV file selection dialog.
const files = await ctx.api.files.openCsvDialog();
if (files) {
// Process selected files
}
openSaveDialog(fileContent: Uint8Array | Blob | string, fileName: string): Promise<any>
Opens a file save dialog.
const result = await ctx.api.files.openSaveDialog(
fileContent,
'export.csv'
);
Secrets API
Securely store and retrieve sensitive data like API keys and tokens. All data is scoped to your addon for security.
Methods
set(key: string, value: string): Promise<void>
Stores a secret value encrypted and scoped to your addon.
// Store API key securely
await ctx.api.secrets.set('api-key', 'your-secret-api-key');
// Store user credentials
await ctx.api.secrets.set('auth-token', userAuthToken);
get(key: string): Promise<string | null>
Retrieves a secret value (returns null if not found).
const apiKey = await ctx.api.secrets.get('api-key');
if (apiKey) {
// Use the API key
const data = await fetch(`https://api.example.com/data?key=${apiKey}`);
}
delete(key: string): Promise<void>
Permanently deletes a secret.
await ctx.api.secrets.delete('old-api-key');
Security Note: Secrets are encrypted at rest and scoped to your addon. Other addons cannot access your secrets, and you cannot access theirs.
Logger API
Provides logging functionality with automatic addon prefix.
Methods
error(message: string): void
Logs an error message.
ctx.api.logger.error('Failed to fetch data from API');
info(message: string): void
Logs an informational message.
ctx.api.logger.info('Data sync completed successfully');
warn(message: string): void
Logs a warning message.
ctx.api.logger.warn('API rate limit approaching');
debug(message: string): void
Logs a debug message.
ctx.api.logger.debug('Processing 100 activities');
trace(message: string): void
Logs a trace message for detailed debugging.
ctx.api.logger.trace('Entering function processActivity');
Event System
Listen to real-time events for responsive addon behavior.
Portfolio Events
onUpdateStart(callback: EventCallback): Promise<UnlistenFn>
Fires when portfolio update starts.
const unlistenStart = await ctx.api.events.portfolio.onUpdateStart((event) => {
console.log('Portfolio update started');
showLoadingIndicator();
});
onUpdateComplete(callback: EventCallback): Promise<UnlistenFn>
Fires when portfolio calculations are updated.
const unlistenPortfolio = await ctx.api.events.portfolio.onUpdateComplete((event) => {
console.log('Portfolio updated:', event.payload);
// Refresh your addon's data
refreshPortfolioData();
});
// Clean up on disable
ctx.onDisable(() => {
unlistenPortfolio();
});
onUpdateError(callback: EventCallback): Promise<UnlistenFn>
Fires when portfolio update encounters an error.
const unlistenError = await ctx.api.events.portfolio.onUpdateError((event) => {
console.error('Portfolio update failed:', event.payload);
showErrorMessage();
});
Market Events
onSyncStart(callback: EventCallback): Promise<UnlistenFn>
Fires when market data sync starts.
const unlistenSyncStart = await ctx.api.events.market.onSyncStart(() => {
console.log('Market sync started');
showSyncIndicator();
});
onSyncComplete(callback: EventCallback): Promise<UnlistenFn>
Fires when market data sync is completed.
const unlistenMarket = await ctx.api.events.market.onSyncComplete(() => {
console.log('Market data updated!');
// Update price displays
updatePriceDisplays();
});
Import Events
onDropHover(callback: EventCallback): Promise<UnlistenFn>
Fires when files are hovered over for import.
const unlistenHover = await ctx.api.events.import.onDropHover((event) => {
console.log('File hover detected');
showDropZone();
});
onDrop(callback: EventCallback): Promise<UnlistenFn>
Fires when files are dropped for import.
const unlistenImport = await ctx.api.events.import.onDrop((event) => {
console.log('File dropped:', event.payload);
// Trigger import workflow
handleFileImport(event.payload.files);
});
onDropCancelled(callback: EventCallback): Promise<UnlistenFn>
Fires when file drop is cancelled.
const unlistenCancel = await ctx.api.events.import.onDropCancelled(() => {
console.log('File drop cancelled');
hideDropZone();
});
Navigation API
Navigate programmatically within the Wealthfolio application.
Methods
navigate(route: string): Promise<void>
Navigate to a specific route in the application.
// Navigate to a specific account
await ctx.api.navigation.navigate('/accounts/account-123');
// Navigate to portfolio overview
await ctx.api.navigation.navigate('/portfolio');
// Navigate to activities page
await ctx.api.navigation.navigate('/activities');
// Navigate to settings
await ctx.api.navigation.navigate('/settings');
Navigation Routes: The navigation API uses the same route structure as the main application. Common routes include /accounts
, /portfolio
, /activities
, /goals
, and /settings
.
Query API
Access and manipulate the shared React Query client for efficient data management.
Methods
getClient(): QueryClient
Gets the shared QueryClient instance from the main application.
const queryClient = ctx.api.query.getClient();
// Use standard React Query methods
const accounts = await queryClient.fetchQuery({
queryKey: ['accounts'],
queryFn: () => ctx.api.accounts.getAll()
});
invalidateQueries(queryKey: string | string[]): void
Invalidates queries to trigger refetch.
// Invalidate specific query
ctx.api.query.invalidateQueries(['accounts']);
// Invalidate multiple related queries
ctx.api.query.invalidateQueries(['portfolio', 'holdings']);
// Invalidate all account-related queries
ctx.api.query.invalidateQueries(['accounts']);
refetchQueries(queryKey: string | string[]): void
Triggers immediate refetch of queries.
// Refetch portfolio data
ctx.api.query.refetchQueries(['portfolio']);
// Refetch multiple queries
ctx.api.query.refetchQueries(['accounts', 'holdings']);
Integration with Events
Combine Query API with event listeners for reactive data updates:
export default function enable(ctx: AddonContext) {
// Invalidate relevant queries when portfolio updates
const unlistenPortfolio = await ctx.api.events.portfolio.onUpdateComplete(() => {
ctx.api.query.invalidateQueries(['portfolio', 'holdings', 'performance']);
});
// Invalidate market data queries when sync completes
const unlistenMarket = await ctx.api.events.market.onSyncComplete(() => {
ctx.api.query.invalidateQueries(['quotes', 'assets']);
});
ctx.onDisable(() => {
unlistenPortfolio();
unlistenMarket();
});
}
UI Integration APIs
Sidebar API
Add navigation items to the main application sidebar.
addItem(item: SidebarItem): SidebarItemHandle
const sidebarItem = ctx.sidebar.addItem({
id: 'my-addon',
label: 'My Addon',
route: '/addon/my-addon',
icon: MyAddonIcon, // Optional React component
order: 100 // Lower numbers appear first
});
// Remove when addon is disabled
ctx.onDisable(() => {
sidebarItem.remove();
});
Router API
Register routes for your addon’s pages.
add(route: RouteConfig): void
ctx.router.add({
path: '/addon/my-addon',
component: React.lazy(() => Promise.resolve({ default: MyAddonComponent }))
});
// Multiple routes
ctx.router.add({
path: '/addon/my-addon/settings',
component: React.lazy(() => Promise.resolve({ default: MyAddonSettings }))
});
Error Handling
API Error Types
interface APIError {
code: string;
message: string;
details?: any;
}
Common error codes:
PERMISSION_DENIED
- Insufficient permissionsNOT_FOUND
- Resource not foundVALIDATION_ERROR
- Invalid data providedNETWORK_ERROR
- Connection issuesRATE_LIMITED
- Too many requests
Best Practices
try {
const accounts = await ctx.api.accounts.getAll();
} catch (error) {
if (error.code === 'PERMISSION_DENIED') {
ctx.api.logger.error('Missing account permissions');
// Show user-friendly message
} else if (error.code === 'NETWORK_ERROR') {
ctx.api.logger.warn('Network issue, retrying...');
// Implement retry logic
} else {
ctx.api.logger.error('Unexpected error:', error);
// General error handling
}
}
Advanced Usage
Batch Operations
// Efficient batch processing
const activities = await Promise.all([
ctx.api.activities.getAll('account-1'),
ctx.api.activities.getAll('account-2'),
ctx.api.activities.getAll('account-3')
]);
// Batch create
const newActivities = await ctx.api.activities.saveMany([
{ /* activity 1 */ },
{ /* activity 2 */ },
{ /* activity 3 */ }
]);
Real-time Updates
export default function enable(ctx: AddonContext) {
// Listen for multiple events
const unsubscribers = [
await ctx.api.events.portfolio.onUpdateComplete(() => refreshData()),
await ctx.api.events.market.onSyncComplete(() => updatePrices()),
await ctx.api.events.import.onDrop((event) => handleImport(event))
];
// Clean up all listeners
ctx.onDisable(() => {
unsubscribers.forEach(unsub => unsub());
});
}
Caching Strategies
// Simple in-memory cache
const cache = new Map();
async function getCachedAccounts() {
if (cache.has('accounts')) {
return cache.get('accounts');
}
const accounts = await ctx.api.accounts.getAll();
cache.set('accounts', accounts);
// Invalidate cache on updates
const unlisten = await ctx.api.events.portfolio.onUpdateComplete(() => {
cache.delete('accounts');
});
return accounts;
}
TypeScript Support
Full TypeScript definitions are provided for all APIs:
import type {
AddonContext,
Account,
Activity,
Holding,
PerformanceHistory,
PerformanceSummary,
// ... and many more
} from '@wealthfolio/addon-sdk';
// Type-safe API usage
const accounts: Account[] = await ctx.api.accounts.getAll();
const holdings: Holding[] = await ctx.api.portfolio.getHoldings(accounts[0].id);
Performance Tips
- Use batch operations when possible
- Implement caching for expensive operations
- Listen to relevant events only
- Clean up resources in disable function
- Use React.memo for expensive components
- Debounce user inputs for search/filter
Ready to build? Check out our examples to see these APIs in action!
On This Page
- API Reference
- Context Overview
- API Domains
- Accounts API
- Portfolio API
- Activities API
- Market Data API
- Assets API
- Quotes API
- Performance API
- Exchange Rates API
- Contribution Limits API
- Goals API
- Settings API
- Files API
- Secrets API
- Logger API
- Event System
- Navigation API
- Query API
- UI Integration APIs
- Error Handling
- Advanced Usage
- TypeScript Support
- Performance Tips