Building an AI-Powered Receipt Capture Bot for Discord
I've been running multiple small businesses and the most tedious part has always been expense tracking. Taking photos of receipts, manually entering data, categorizing transactions — it's death by a thousand paper cuts.
So I built a system where I can just snap a photo, send it to my Discord bot, and have it automatically extract the data and save it to my finance dashboard. Here's exactly how I did it.
The End Result
Before diving into the technical details, here's what the finished system looks like:
The whole process takes about 10 seconds from photo to saved transaction.
Architecture Overview
Part 1: Bot Framework Setup
1 Choose Your Framework
I'm using Clawdbot, an open-source bot framework that supports Discord, Slack, and other platforms. The key feature I needed was the skill system that lets you define custom behaviors.
# Clone and install
git clone https://github.com/clawdbot/clawdbot.git
cd clawdbot
pnpm install
# Run the setup wizard
pnpm clawdbot onboard
2 Configure Discord
Create a Discord application at discord.com/developers:
- Create New Application
- Go to Bot → Add Bot
- Enable "Message Content Intent" (required to read message text)
- Copy the bot token
Add the bot to your server using OAuth2 URL Generator with bot scope and appropriate permissions (Send Messages, Read Message History, Add Reactions).
3 Use OpenRouter for Better Rate Limits
Sign up at openrouter.ai, create an API key, and configure your bot:
{
"agents": {
"defaults": {
"model": {
"primary": "openrouter/anthropic/claude-sonnet-4",
"fallbacks": ["openrouter/anthropic/claude-3.5-haiku"]
}
}
}
}
Part 2: The Receipt Capture Skill
The skill system lets you define custom behaviors with trigger phrases and instructions. Here's the core of the receipt capture skill:
Skill Definition (SKILL.md)
---
name: receipt-capture
description: "Capture receipts and screenshots to add transactions."
metadata: {
"triggers": ["add receipt", "log receipt", "log this expense"]
}
---
# Receipt Capture
## When to Use
- User sends an image attachment with a receipt
- User says "add this receipt" or "log this expense"
## Workflow
1. Analyze the image using vision capabilities
2. Extract: merchant, date, amount, description
3. Suggest category based on keywords
4. Ask user to confirm
5. Save to database
Category Matching Logic
The bot uses keyword matching to suggest categories:
const CATEGORY_KEYWORDS = {
software: ['software', 'subscription', 'api', 'saas', 'cloud'],
supplies: ['supplies', 'materials', 'equipment', 'tools'],
meals: ['food', 'restaurant', 'coffee', 'lunch', 'dinner'],
travel: ['uber', 'lyft', 'flight', 'hotel', 'airbnb'],
advertising: ['ads', 'marketing', 'meta', 'google', 'facebook']
};
function suggestCategory(merchant, description) {
const text = `${merchant} ${description}`.toLowerCase();
for (const [category, keywords] of Object.entries(CATEGORY_KEYWORDS)) {
if (keywords.some(kw => text.includes(kw))) {
return category;
}
}
return 'general';
}
Handling Edge Cases
Real-world receipts are messy. The skill handles common issues:
- Blurry photos: Ask user to retake or enter manually
- Missing date: Default to today, note as "estimated"
- Ambiguous amount: Ask user to confirm the total
- Foreign currency: Store as-is with currency noted
Part 3: Firebase/Firestore Setup
Database Schema
// transactions collection
{
id: string,
date: string, // "2026-02-04"
description: string, // "Google LLC - Services"
amount: number, // 93.60
type: "expense",
category: string, // "software"
entity: string, // "business-name"
source: "receipt-capture",
metadata: {
merchant: string,
capturedAt: timestamp,
originalCurrency: string
}
}
Security Rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /transactions/{transactionId} {
allow read, write: if request.auth != null;
}
}
}
Part 4: The Confirmation Flow
Never auto-save without confirmation. The bot always shows extracted data and waits for user approval:
🎯 Analyzing receipt...
**Extracted Data:**
- Merchant: Google LLC
- Date: April 1, 2024
- Amount: CA$93.60
- Description: Google services payment
**Suggested:**
- Category: software
- Entity: business-name
Does this look correct? Reply **confirm** to save,
or tell me what to change! 🏕️
Users can then:
confirm→ Save as-ischange category to advertising→ Update and re-confirmamount is 89.99→ Correct and re-confirmsplit 50/50 between X and Y→ Create two transactions
Part 5: The Web Dashboard
Transactions appear instantly on a simple web dashboard using Firebase's real-time listeners:
import { onSnapshot, query, orderBy } from 'firebase/firestore';
const q = query(
collection(db, 'transactions'),
orderBy('date', 'desc')
);
onSnapshot(q, (snapshot) => {
const transactions = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data()
}));
renderTransactions(transactions);
});
Cost Breakdown
| Component | Cost |
|---|---|
| OpenRouter (Claude Sonnet) | ~$3/million input tokens |
| OpenRouter (Claude Haiku) | ~$0.25/million input tokens |
| Firebase Firestore | Free tier: 50K reads, 20K writes/day |
| Firebase Hosting | Free tier: 10GB storage |
| Estimated Monthly (light use) | $5-15/month |
Lessons Learned
1. Rate Limits Are Real
I hit Anthropic's rate limits immediately with the direct API. OpenRouter solved this completely. Don't assume you'll stay under limits.
2. Always Confirm Before Saving
OCR isn't perfect. Even Claude Vision occasionally misreads amounts or dates. The confirmation step has saved me from many bad entries.
3. Keep Categories Simple
Started with 20+ categories. Now I use 8. Fewer categories = faster categorization = actually using the system.
4. Mobile-First Matters
90% of my receipts come from my phone. The Discord mobile app works great for this - snap, send, confirm, done.
What's Next
Currently exploring:
- Automatic receipt image storage in Firebase Storage
- Monthly expense reports generated automatically
- Multi-currency support with live conversion rates
- Team access with role-based permissions
Resources
- Clawdbot Framework
- OpenRouter - Unified API for AI models
- Firebase Firestore Docs
- Claude Vision Guide
Have questions or built something similar? Reach out on Twitter or get in touch.