Two RAG pipelines for Paystack: 1) Documentation RAG — embed Paystack API docs, your integration notes, error code reference, webhook event catalogue. Query when someone asks "what does this error mean" or "how should I handle X". 2) Transaction history RAG — store transaction records in a database queryable by the LLM via tools. Query when someone asks "find transactions matching this pattern" or "what happened to this customer". Keep transaction data in your own infrastructure — never send raw PII-containing transaction records to third-party embedding services.
// Build a documentation RAG index for Paystack error codes and API reference
// Using a simple embedding + cosine similarity approach
// Step 1: Create documentation chunks
var docChunks = [
{
id: 'error-insufficient-funds',
text: 'Error: "Insufficient Funds". The customer's bank declined the transaction because the account balance was too low. This is a card_decline error from the bank. Customer action: ask the customer to use a different card or top up the account. Do not retry the same card immediately.',
tags: ['error', 'card', 'decline'],
},
{
id: 'error-do-not-honor',
text: 'Error: "Do Not Honor" (gateway_response: "Do Not Honour"). The issuing bank declined without giving a specific reason. Common causes: fraud suspicion, card flagged, transaction type restriction. Customer action: ask the customer to contact their bank or use a different card.',
tags: ['error', 'card', 'decline'],
},
{
id: 'webhook-charge-success',
text: 'Webhook event: charge.success. Fired when a transaction is successfully completed. Always verify the payment status by calling GET /transaction/verify/:reference before fulfilling the order. The webhook payload contains data.reference, data.amount (in kobo), data.customer.email, and data.status which should be "success".',
tags: ['webhook', 'charge'],
},
// Add more chunks for each error code, each endpoint, each webhook event...
];
// Step 2: Embed chunks (using any embedding model)
async function buildDocIndex(chunks) {
var indexed = [];
for (var chunk of chunks) {
var embedding = await embedText(chunk.text); // your embedding function
indexed.push({ ...chunk, embedding });
}
return indexed;
}
// Step 3: Retrieve relevant chunks for a query
async function retrieveRelevantDocs(query, docIndex, topK = 3) {
var queryEmbedding = await embedText(query);
return docIndex
.map(doc => ({ ...doc, score: cosineSimilarity(queryEmbedding, doc.embedding) }))
.sort((a, b) => b.score - a.score)
.slice(0, topK);
}
// Step 4: Augment prompt with retrieved docs
async function answerPaymentQuestion(question, docIndex) {
var relevantDocs = await retrieveRelevantDocs(question, docIndex);
var context = relevantDocs.map(d => d.text).join('
');
var response = await anthropic.messages.create({
model: 'claude-opus-4-6',
max_tokens: 512,
messages: [{
role: 'user',
content: 'Payment documentation:
' + context + '
Question: ' + question,
}],
system: 'Answer the payment question using only the documentation provided. If the answer is not in the documentation, say so.',
});
return response.content[0].text;
}
For transaction history, use tool calling rather than vector embeddings. Transaction records contain PII and financial data — query them from your own database via tools, not by embedding them in an external vector store:
// Tool calling for transaction retrieval (safer than embedding PII data)
var transactionTools = [
{
name: 'search_transactions',
description: 'Search transaction history by various filters.',
input_schema: {
type: 'object',
properties: {
reference: { type: 'string' },
customer_email: { type: 'string' },
date_from: { type: 'string' },
date_to: { type: 'string' },
status: { type: 'string' },
amount_min: { type: 'number' },
amount_max: { type: 'number' },
},
},
},
];
// Executed against your own DB — not an external service
async function executeSearchTransactions(input) {
return db.transactions.search(input); // your own DB, you control the data
}
This way, the LLM gets transaction data it needs without the raw records ever leaving your infrastructure.
Get weekly developer tips
Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.
No spam. Unsubscribe anytime.
See building an AI agent that queries Paystack transactions for the full tool calling pattern.
KES 2,999
The definitive guide to building payment systems with Paystack — from your first transaction to production-grade payment infrastructure across Africa. 9 modules, 47 lessons. Free preview available.
Start Paystack Course