v1.4.0
API Reference
VixFlow is a local-first application. There is no external REST API — all data operations are performed directly in the browser using JavaScript functions that read and write to localStorage. This page documents those internal functions for developers who want to extend or integrate with VixFlow.
Local-first architecture: All functions listed here operate on
localStorage. Data never leaves your browser. The only external API calls are to api.anthropic.com for AI features, using your personal API key.Architecture Overview
VixFlow's data layer is built around a simple pattern: each entity type (clients, proposals, invoices, etc.) has its own localStorage key that stores a JSON array. CRUD operations are performed by reading the array, modifying it, and writing it back.
javascript — core pattern
// Generic read pattern function getEntity(key) { try { return JSON.parse(localStorage.getItem(key) || '[]'); } catch { return []; } } // Generic write pattern function saveEntity(key, item) { const items = getEntity(key); const idx = items.findIndex(i => i.id === item.id); if (idx >= 0) items[idx] = item; // update else items.push(item); // insert localStorage.setItem(key, JSON.stringify(items)); }
Clients API
GET
getClients()
Returns all clients as an array
Returns all stored clients sorted by creation date (newest first).
javascript
function getClients() { const data = JSON.parse( localStorage.getItem('vixflow_clients') || '[]' ); return data.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt) ); } // Example usage const clients = getClients(); console.log(clients); // [{id, name, email, ...}, ...]
Returns: Client[]
SET
saveClient(client)
Create or update a client record
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Required | UUID. If matching ID exists, updates. Otherwise inserts. |
| name | string | Required | Client full name |
| string | Required | Email address | |
| company | string | Optional | Company name |
| currency | string | Optional | ISO 4217 currency code (default: "USD") |
| createdAt | string | Required | ISO 8601 date string |
javascript
saveClient({ id: crypto.randomUUID(), name: 'Rahim Ahmed', email: 'rahim@example.com', company: 'TechBD Ltd', currency: 'USD', createdAt: new Date().toISOString() });
DEL
deleteClient(id)
Permanently delete a client by ID
Warning: Deletion is permanent. The client record is removed from localStorage immediately with no undo.
javascript
function deleteClient(id) { const clients = getClients().filter(c => c.id !== id); localStorage.setItem('vixflow_clients', JSON.stringify(clients)); }
Proposals API
GETgetProposals()
Returns all proposals sorted by date
javascript
function getProposals() { return JSON.parse( localStorage.getItem('vixflow_proposals') || '[]' ).sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)); }
| Field | Type | Description |
|---|---|---|
| id | string | UUID |
| clientId | string | Linked client ID |
| title | string | Proposal title |
| status | string | "draft" | "sent" | "accepted" | "rejected" |
| value | number | Proposed project value |
SETsaveProposal(proposal)
Create or update a proposal
javascript
saveProposal({ id: crypto.randomUUID(), clientId: '...', title: 'Website Redesign', content: '## Summary...', status: 'draft', value: 1500, currency: 'USD', createdAt: new Date().toISOString() });
Invoices API
GETgetInvoices()
Returns all invoices sorted by date
javascript
function getInvoices() { return JSON.parse(localStorage.getItem('vixflow_invoices') || '[]') .sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)); } // Filter by status const overdue = getInvoices().filter(i => i.status === 'overdue');
| Field | Type | Description |
|---|---|---|
| invoiceNumber | string | e.g. "INV-0042" |
| items | LineItem[] | {description, qty, unitPrice, total} |
| total | number | Final amount due |
| status | string | "draft" | "sent" | "paid" | "overdue" |
| dueDate | string | ISO 8601 date |
SETsaveInvoice(invoice)
Create or update an invoice
javascript
saveInvoice({ id: crypto.randomUUID(), invoiceNumber: 'INV-0042', clientId: '...', items: [{ description: 'Design work', qty: 1, unitPrice: 800, total: 800 }], subtotal: 800, taxRate: 0, total: 800, currency: 'USD', status: 'draft', dueDate: '2026-04-15', createdAt: new Date().toISOString() });
Settings API
GETgetSettings()
Returns user settings object
javascript
function getSettings() { return JSON.parse(localStorage.getItem('vixflow_settings') || '{}'); } // { claudeApiKey, businessName, email, currency, theme, language, ... }
AI API
AI
generateAIContent(prompt, options)
Call Claude API with user's key
Core AI generation function. Uses the user's stored Claude API key. Throws an error if no key is set.
javascript
async function generateAIContent(prompt, options = {}) { const apiKey = getStoredAPIKey(); if (!apiKey) throw new Error('No API key configured'); const { model = 'claude-haiku-20240307', maxTokens = 1024, system = '' } = options; const res = await fetch('https://api.anthropic.com/v1/messages', { method: 'POST', headers: { 'x-api-key': apiKey, 'anthropic-version': '2023-06-01', 'content-type': 'application/json' }, body: JSON.stringify({ model, max_tokens: maxTokens, system, messages: [{ role: 'user', content: prompt }] }) }); if (!res.ok) throw new Error(`API error: ${res.status}`); const data = await res.json(); return data.content[0].text; } // Usage example const proposal = await generateAIContent( `Write a proposal for web design project for TechBD Ltd`, { maxTokens: 2048 } );
Options
| Option | Type | Default | Description |
|---|---|---|---|
| model | string | claude-haiku-20240307 | Claude model to use |
| maxTokens | number | 1024 | Maximum tokens to generate |
| system | string | "" | System prompt for context |
GET
getStoredAPIKey()
Retrieve the user's Claude API key
javascript
function getStoredAPIKey() { const settings = JSON.parse( localStorage.getItem('vixflow_settings') || '{}' ); return settings.claudeApiKey || null; } // Returns: string (the API key) or null
Export API
GET
exportAllData()
Export all data as a JSON file download
javascript
function exportAllData() { const exportData = { version: '1.4.0', exportedAt: new Date().toISOString(), clients: getClients(), proposals: getProposals(), invoices: getInvoices(), projects: getProjects(), expenses: getExpenses() }; const blob = new Blob( [JSON.stringify(exportData, null, 2)], { type: 'application/json' } ); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `vixflow-backup-${Date.now()}.json`; a.click(); }