AI
Docs

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); }}
    />
  );
}