A Ruby application that processes invoice images/PDFs, extracts data using Google Cloud Vision and Gemini AI, and creates expenses in Holded via their API.
- 📄 Process PDF invoices (converts to images automatically)
- 🤖 AI-powered data extraction using Google Cloud Vision + Gemini
- 💰 Automatic expense creation in Holded
- 📎 File attachment to Holded documents
- 🔍 Preview mode before creating expenses
- 📁 Batch processing of multiple files
bundle installThe application requires ImageMagick for PDF processing:
# macOS
brew install imagemagick
# Ubuntu/Debian
sudo apt-get install imagemagick
# CentOS/RHEL
sudo yum install ImageMagickCreate the following files in the keys/ directory:
- File:
keys/gemini_api_key.txt - Content: Your Gemini API key (just the key, no extra formatting)
- File:
keys/holded_api_key.txt - Content: Your Holded API key (just the key, no extra formatting)
The easiest way to run the processor is using the provided shell script:
# Process a single PDF file
./run_invoice_processor.sh invoice.pdf
# Process all PDF files in a directory
./run_invoice_processor.sh /path/to/invoices/
# Use custom API key paths
./run_invoice_processor.sh --google-credentials /path/to/credentials.json \
--gemini-key /path/to/gemini.txt \
--holded-key /path/to/holded.txt \
invoice.pdf
# Using environment variables
GOOGLE_CREDENTIALS_PATH=/custom/path.json \
GEMINI_API_KEY_PATH=/custom/gemini.txt \
HOLDED_API_KEY_PATH=/custom/holded.txt \
./run_invoice_processor.sh invoice.pdfYou can also run the processor directly with Ruby, but you'll need to set environment variables manually:
export GEMINI_API="$(cat keys/gemini_api_key.txt)"
export HOLDED_API_KEY="$(cat keys/holded_api_key.txt)"
ruby invoice_processor.rb invoice.pdf- PDF Processing: Converts PDF to high-quality image using ImageMagick
- Text Extraction: Uses Google Cloud Vision to extract text from the image
- Data Extraction: Sends image to Gemini AI for structured data extraction
- Preview: Shows extracted data and asks for confirmation
- Holded Integration: Creates expense document in Holded with extracted data
- File Attachment: Attaches the original PDF to the Holded document
The AI extracts the following information from invoices:
invoice_number: Invoice identifierdate: Invoice date (DD/MM/YYYY format)total_amount: Total invoice amountvendor_name: Supplier company namevendor_id: Supplier tax ID (CIF/NIF)tax_amount: Total tax amountline_items: Array of items with description, amount, and tax percentage
- ImageMagick not found: Install ImageMagick using your package manager
- API key errors: Ensure API key files exist and contain valid keys
- Permission denied: Make sure the script is executable:
chmod +x run_invoice_processor.sh - Google Cloud credentials: Ensure the service account has Vision API access
The application includes extensive logging. Check the console output for detailed information about each step.
holded/
├── run_invoice_processor.sh # Main runner script
├── invoice_processor.rb # Main processor
├── lib/ # Service classes
│ ├── vision_service.rb # Google Cloud Vision integration
│ ├── gemini_image_service.rb # Gemini AI integration
│ ├── holded_service.rb # Holded API integration
│ └── invoice_processor.rb # Core processing logic
├── keys/ # API keys and credentials
│ ├── arimidori-7a49f7f94661.json
│ ├── gemini_api_key.txt
│ └── holded_api_key.txt
└── test/ # Test files
└── invoices/ # Sample invoices for testing
Run the test suite:
bundle exec ruby -I test test/test_helper.rb- Never commit API keys to version control
- Use environment variables or secure key management in production
- The
keys/directory should be added to.gitignore - Consider using a secrets management service for production deployments