
This is a wrapper API for the LemonFox AI speech generation service with usage tracking, rate limiting, and document text extraction capabilities. It simplifies the interface by only exposing the essential parameters while handling authentication, usage tracking, and configuration internally.
- Authentication: RevenueCat subscription verification + admin bypass
- Usage Tracking: Monthly character limits with SQLite storage
- Rate Limiting: 4 million characters per calendar month per customer
- Document Text Extraction: Extract clean text from .txt, .rtf, and .docx files for TTS
- Modular Architecture: Separated middleware and database modules
├── backend/
│ ├── index.ts # Main Hono app
│ ├── middleware/
│ │ ├── auth.ts # Authentication middleware
│ │ └── usage.ts # Usage tracking middleware
│ ├── database/
│ │ └── usage.ts # Database operations
│ └── README.md
├── main.tsx # Frontend (if applicable)
└── README.md
LEMONFOX_API_KEY- Your LemonFox API keyREVENUECAT_API_KEY- Your RevenueCat API key for subscription verificationADMIN_ACCESS_KEY- Admin bypass key for development/testing
Update the REVENUECAT_PROJECT_ID constant in /backend/middleware/auth.ts with your actual RevenueCat project ID.
All API endpoints (except /health) require authentication via the Authorization header:
Authorization: Bearer YOUR_ADMIN_ACCESS_KEY
Authorization: Bearer CUSTOMER_ID
or
Authorization: Customer CUSTOMER_ID
The API will verify the customer has active entitlements via RevenueCat before allowing access.
- Monthly Limit: 4,000,000 characters per customer
- Reset Period: Calendar month (1st to last day of month)
- Admin Users: Unlimited usage
- Tracking: Automatic usage recording after successful requests
Generates speech from text using the LemonFox AI service.
Request Body:
{ "voice": "sarah", "input": "Text to convert to speech" }
Response:
{ "audio": "_base_64_encoded_audio_here", "word_timestamps": [ { "word": "Hello!", "start": 0.275, "end": 0.7 } ] }
Error Response (Rate Limited):
{ "error": "Monthly character limit exceeded", "details": { "monthly_limit": 4000000, "current_usage": 3950000, "requested_characters": 100000, "remaining_characters": 50000 } }
Extracts clean text content from uploaded documents (.txt, .rtf, .docx) for TTS processing.
Request:
- Method: POST
- Content-Type: multipart/form-data
- Body: Form data with 'file' field containing the document
Supported File Types:
.txt- Plain text files.rtf- Rich Text Format files.docx- Microsoft Word documents
File Size Limit: 10MB
Response:
{ "text": "Extracted clean text content suitable for TTS processing...", "filename": "document.docx", "fileType": "docx", "wordCount": 1250, "characterCount": 6890 }
Error Responses:
{ "error": "Unsupported file type. Supported types: txt, rtf, docx" }
{ "error": "File too large. Maximum size is 10MB." }
{ "error": "No readable text content found in the document" }
Text Processing:
- Removes excessive whitespace and formatting artifacts
- Strips common header/footer patterns and page numbers
- Optimizes text flow for natural TTS reading
- Handles complex document structures (tables, lists, etc.)
Get current month's usage statistics for the authenticated customer.
Response:
{ "monthly_limit": 4000000, "current_usage": 150000, "remaining_characters": 3850000, "usage_percentage": 4 }
Admin Query Parameter:
GET /api/usage?customer_id=specific_customer_id
Health check endpoint that returns the service status.
Response:
{ "status": "ok", "timestamp": "2024-01-01T00:00:00.000Z" }
The system uses SQLite to track usage with the following schema:
Table: customer_usage_v1
id- Auto-incrementing primary keycustomer_id- Customer identifier from RevenueCatcharacter_count- Number of characters in the requestrequest_timestamp- ISO timestamp of the requestcreated_at- Database insertion timestamp
The API automatically configures:
response_format: Always set to "mp3"word_timestamps: Always set to true
Only voice and input parameters need to be provided by the client.
400- Bad Request (missing required fields)401- Unauthorized (missing/invalid auth header)403- Forbidden (no active subscription)429- Too Many Requests (monthly limit exceeded)500- Internal Server Error