Examples
Code Examples
Copy-paste working examples for the most common use cases.
Basic usage
Fetch accounts, balance, and transactions.
import { InvestecAI } from 'investec-ai';
const sdk = new InvestecAI({
clientId: process.env.INVESTEC_CLIENT_ID!,
clientSecret: process.env.INVESTEC_CLIENT_SECRET!,
apiKey: process.env.INVESTEC_API_KEY!,
openaiApiKey: process.env.OPENAI_API_KEY!,
});
// Get all accounts
const accounts = await sdk.getAccounts();
const accountId = accounts[0].accountId;
// Get balance
const { currentBalance, availableBalance } = await sdk.getBalance(accountId);
console.log(`Balance: R${currentBalance}`);
// Get last 30 transactions
const transactions = await sdk.getTransactions(accountId, { limit: 30 });
console.log(`${transactions.length} transactions loaded`);AI spending analysis
Categorise spending and get actionable insights.
const analysis = await sdk.analyzeSpending(accountId, { period: '30d' });
// Spending by category
Object.entries(analysis.categories).forEach(([category, amount]) => {
console.log(`${category}: R${amount}`);
});
// Groceries: R2400
// Transport: R850
// Food & Dining: R1200
// AI insights
analysis.insights.forEach(insight => console.log('•', insight));
// • You spent 23% more on groceries compared to last month
// • Transport costs are within a healthy range for your income
// Predicted next 30 days spend
console.log(`Predicted: R${analysis.predictions.next30Days}`);AI chat
Full AI chat handler with a React frontend.
app/api/chat/route.ts
import { createChatHandler } from 'investec-ai';
import { sdk } from '@/lib/sdk';
export const POST = createChatHandler(sdk, {
maxSteps: 10,
system: (d) => `${d}\n\nAlways greet the user warmly and be concise.`,
});app/chat/page.tsx
'use client';
import { useChat } from 'ai/react';
import { useState } from 'react';
export default function ChatPage() {
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
api: '/api/chat',
body: { accountId: 'your-account-id' },
});
return (
<div className="flex flex-col h-screen">
<div className="flex-1 overflow-y-auto p-4 space-y-4">
{messages.map(m => (
<div key={m.id} className={m.role === 'user' ? 'text-right' : 'text-left'}>
<span className="inline-block bg-gray-100 rounded-xl px-4 py-2 text-sm">
{m.content}
</span>
</div>
))}
</div>
<form onSubmit={handleSubmit} className="p-4 flex gap-2">
<input
value={input}
onChange={handleInputChange}
placeholder="Ask about your finances..."
className="flex-1 border rounded-xl px-4 py-2"
/>
<button type="submit" disabled={isLoading}>Send</button>
</form>
</div>
);
}Fraud detection
Risk-score a transaction and flag suspicious activity.
const transactions = await sdk.getTransactions(accountId, { limit: 20 });
for (const transaction of transactions) {
const alert = await sdk.detectFraud(transaction);
if (alert.riskScore > 70) {
console.log(`⚠️ HIGH RISK: ${transaction.description}`);
console.log(`Risk score: ${alert.riskScore}/100`);
alert.reasons.forEach(r => console.log(` - ${r}`));
if (alert.requiresConfirmation) {
console.log('Action required: user must confirm this transaction');
}
}
}Voice banking
Record audio in the browser, transcribe with Whisper, respond with AI.
app/voice/page.tsx
'use client';
import { useState, useRef } from 'react';
export default function VoicePage() {
const [transcript, setTranscript] = useState('');
const [response, setResponse] = useState('');
const recorderRef = useRef<MediaRecorder | null>(null);
const chunksRef = useRef<Blob[]>([]);
async function startRecording() {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const recorder = new MediaRecorder(stream);
chunksRef.current = [];
recorder.ondataavailable = e => chunksRef.current.push(e.data);
recorder.onstop = async () => {
stream.getTracks().forEach(t => t.stop());
const blob = new Blob(chunksRef.current, { type: 'audio/webm' });
// 1. Transcribe with Whisper via your API route
const form = new FormData();
form.append('audio', blob, 'audio.webm');
const { transcript: text } = await fetch('/api/transcribe', {
method: 'POST',
body: form,
}).then(r => r.json());
setTranscript(text);
// 2. Send transcript to AI chat
const res = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ messages: [{ role: 'user', content: text }] }),
});
const reader = res.body?.getReader();
// ... stream the response
};
recorder.start();
recorderRef.current = recorder;
}
return (
<div>
<button onClick={startRecording}>Start recording</button>
<button onClick={() => recorderRef.current?.stop()}>Stop</button>
{transcript && <p>You said: {transcript}</p>}
{response && <p>AI: {response}</p>}
</div>
);
}Transcribe API route:
app/api/transcribe/route.ts
import { NextResponse } from 'next/server';
import { sdk } from '@/lib/sdk';
export async function POST(req: Request) {
const formData = await req.formData();
const audio = formData.get('audio') as Blob;
const transcript = await sdk.transcribeAudio(audio, 'audio.webm');
return NextResponse.json({ transcript });
}Receipt scanning
Upload an image and extract receipt data with GPT-4o Vision.
app/api/scan-receipt/route.ts
import { NextResponse } from 'next/server';
import { sdk } from '@/lib/sdk';
export async function POST(req: Request) {
const { imageBase64 } = await req.json();
const receipt = await sdk.scanReceipt(imageBase64);
return NextResponse.json(receipt);
}app/receipt/page.tsx
'use client';
export default function ReceiptPage() {
async function handleFile(file: File) {
const reader = new FileReader();
reader.onload = async (e) => {
const base64 = (e.target?.result as string).split(',')[1]!;
const receipt = await fetch('/api/scan-receipt', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ imageBase64: base64 }),
}).then(r => r.json());
console.log(receipt.merchant); // "Woolworths Food"
console.log(receipt.amount); // 342.50
console.log(receipt.items); // [{ name: "Milk", price: 28, quantity: 2 }]
};
reader.readAsDataURL(file);
}
return (
<input
type="file"
accept="image/*"
onChange={e => { const f = e.target.files?.[0]; if (f) handleFile(f); }}
/>
);
}