API Key Authentication Setup β
π Overview β
Luna Agents uses API keys to gate access to premium features like Luna Vision RAGβ’. This system ensures only paying customers can access Pro features.
ποΈ Architecture β
User subscribes β LemonSqueezy β Webhook β Generate API Key β Store in KV β Email to user
User makes request β Validate API key β Check limits β Allow/Deny accessComponents β
- API Auth Service (
api-auth/) - Cloudflare Worker for key validation - Webhook Handler (
webhooks/lemonsqueezy.js) - Processes subscription events - KV Store - Stores API keys and usage data
- Luna Vision RAG MCP - Validates keys before processing
π Setup Steps β
Step 1: Create KV Namespace β
bash
# Create KV namespace for API keys
cd api-auth
wrangler kv:namespace create "API_KEYS"
# Copy the ID that's returned
# Example: id = "abc123def456"Update api-auth/wrangler.toml:
toml
[[kv_namespaces]]
binding = "API_KEYS"
id = "YOUR_KV_NAMESPACE_ID_HERE" # Paste the ID from aboveStep 2: Set Webhook Secret β
bash
# Generate a random secret
openssl rand -hex 32
# Set it as a Cloudflare secret
cd api-auth
wrangler secret put WEBHOOK_SECRET
# Paste the generated secret when promptedSave this secret - you'll need it for the webhook handler.
Step 3: Deploy API Auth Service β
bash
cd api-auth
wrangler deployYour auth service will be live at:
https://luna-agents-api-auth.YOUR_SUBDOMAIN.workers.dev- Or custom domain:
https://auth.lunaos.ai
Step 4: Configure Custom Domain (Optional) β
- Go to Cloudflare Dashboard β Workers
- Find
luna-agents-api-auth - Click "Triggers" β "Custom Domains"
- Add:
auth.lunaos.ai - DNS configured automatically
Step 5: Update Webhook Handler β
Edit webhooks/lemonsqueezy.js:
javascript
// Set these environment variables
process.env.AUTH_SERVICE_URL = 'https://auth.lunaos.ai';
process.env.WEBHOOK_SECRET = 'YOUR_WEBHOOK_SECRET_HERE';
process.env.LEMONSQUEEZY_WEBHOOK_SECRET = 'FROM_LEMONSQUEEZY_DASHBOARD';Step 6: Configure LemonSqueezy Webhook β
- Go to LemonSqueezy Dashboard β Settings β Webhooks
- Click "Add endpoint"
- URL:
https://your-api.com/webhooks/lemonsqueezy - Secret: Generate and save (use in webhook handler)
- Events:
subscription_createdsubscription_updatedsubscription_cancelledsubscription_resumedsubscription_expiredsubscription_payment_successsubscription_payment_failed
π API Key Format β
API keys follow this format:
luna_AbCdEfGh1234567890IjKlMnOpQrSt- Prefix:
luna_ - Length: 37 characters total
- Characters: Alphanumeric (A-Z, a-z, 0-9)
π Usage Tracking β
Free Tier Limits β
- Queries: 100/day
- Files indexed: 1,000 total
- Luna Vision RAGβ’: β Not available
Pro Tier Limits β
- Queries: Unlimited
- Files indexed: Unlimited
- Luna Vision RAGβ’: β Full access
Enterprise Tier β
- Everything unlimited
- Custom limits available
π API Endpoints β
Validate API Key β
bash
POST https://auth.lunaos.ai/validate
Content-Type: application/json
{
"apiKey": "luna_AbCdEfGh1234567890IjKlMnOpQrSt"
}Response (Success):
json
{
"valid": true,
"tier": "pro",
"customerId": "123456",
"usage": {
"queries": {
"used": 45,
"limit": -1,
"remaining": -1
},
"filesIndexed": {
"used": 2500,
"limit": -1,
"remaining": -1
}
},
"features": {
"lunaVisionRAG": true,
"unlimitedIndexing": true,
"unlimitedQueries": true,
"prioritySupport": true
}
}Response (Invalid):
json
{
"valid": false,
"error": "Invalid API key"
}Get Usage Statistics β
bash
GET https://auth.lunaos.ai/usage
Authorization: Bearer luna_AbCdEfGh1234567890IjKlMnOpQrStResponse:
json
{
"tier": "pro",
"usage": {
"queries": 45,
"filesIndexed": 2500,
"screenshotsAnalyzed": 12
},
"limits": {
"queries": -1,
"filesIndexed": -1,
"screenshotsAnalyzed": -1
},
"resetDate": "2024-01-02T00:00:00.000Z"
}π§ Integration with Luna Vision RAG MCP β
Update mcp-servers/luna-vision-rag-mcp/src/index.js:
javascript
// Add API key validation
async function validateAPIKey(apiKey) {
const response = await fetch('https://auth.lunaos.ai/validate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ apiKey }),
});
return await response.json();
}
// In your MCP handler
export default {
async fetch(request, env) {
// Get API key from header
const apiKey = request.headers.get('X-API-Key');
if (!apiKey) {
return new Response(JSON.stringify({
error: 'API key required. Get yours at https://agent.lunaos.ai/pricing'
}), {
status: 401,
headers: { 'Content-Type': 'application/json' },
});
}
// Validate API key
const validation = await validateAPIKey(apiKey);
if (!validation.valid) {
return new Response(JSON.stringify({
error: validation.error || 'Invalid API key',
upgrade: 'https://agent.lunaos.ai/pricing'
}), {
status: 403,
headers: { 'Content-Type': 'application/json' },
});
}
// Check if user has access to Luna Vision RAG
if (!validation.features.lunaVisionRAG) {
return new Response(JSON.stringify({
error: 'Luna Vision RAGβ’ requires Pro subscription',
upgrade: 'https://agent.lunaos.ai/pricing'
}), {
status: 403,
headers: { 'Content-Type': 'application/json' },
});
}
// Process request...
}
};π₯ User Configuration β
Users add their API key to their MCP configuration:
Claude Desktop β
json
{
"mcpServers": {
"luna-vision-rag": {
"url": "https://luna-vision-rag-mcp.broad-dew-49ad.workers.dev/mcp",
"headers": {
"X-API-Key": "luna_AbCdEfGh1234567890IjKlMnOpQrSt"
}
}
}
}Zed β
json
{
"context_servers": {
"luna-vision-rag": {
"settings": {
"url": "https://luna-vision-rag-mcp.broad-dew-49ad.workers.dev/mcp",
"headers": {
"X-API-Key": "luna_AbCdEfGh1234567890IjKlMnOpQrSt"
}
}
}
}
}π§ Email Templates β
Welcome Email (After Subscription) β
Subject: Welcome to Luna Agents Pro! π
Hi there,
Thanks for subscribing to Luna Agents Pro!
Your API Key:
luna_AbCdEfGh1234567890IjKlMnOpQrSt
Get Started:
1. Add your API key to your MCP configuration
2. Restart your AI coding assistant
3. Start using Luna Vision RAGβ’!
Documentation: https://agent.lunaos.ai/docs
Dashboard: https://agent.lunaos.ai/dashboard
Questions? Just reply to this email.
Happy coding!
The Luna Agents TeamCancellation Email β
Subject: Your Luna Agents subscription
Hi there,
We're sorry to see you go!
Your subscription will remain active until: [END_DATE]
After that, you'll be downgraded to the Free tier.
Want to stay? You can reactivate anytime at:
https://agent.lunaos.ai/pricing
We'd love to hear your feedback:
[FEEDBACK_LINK]
Thanks for trying Luna Agents!π§ͺ Testing β
Test API Key Generation β
bash
curl -X POST https://auth.lunaos.ai/generate \
-H "Authorization: Bearer YOUR_WEBHOOK_SECRET" \
-H "Content-Type: application/json" \
-d '{
"customerId": "test_123",
"email": "[email protected]",
"tier": "pro",
"subscriptionId": "sub_123"
}'Test API Key Validation β
bash
curl -X POST https://auth.lunaos.ai/validate \
-H "Content-Type: application/json" \
-d '{
"apiKey": "luna_YOUR_TEST_KEY_HERE"
}'Test Usage Tracking β
bash
curl https://auth.lunaos.ai/usage \
-H "Authorization: Bearer luna_YOUR_TEST_KEY_HERE"π Security Best Practices β
- Never expose API keys in client-side code
- Use HTTPS only for all API calls
- Rotate webhook secrets regularly
- Monitor for abuse - track usage patterns
- Rate limit validation endpoint
- Log all access for audit trail
π Monitoring β
Key Metrics to Track β
- API key validations per minute
- Failed validation attempts
- Usage by tier
- Top users by API calls
- Subscription churn rate
Cloudflare Analytics β
View in Cloudflare Dashboard:
- Workers β luna-agents-api-auth β Metrics
- Requests, errors, CPU time
- Set up alerts for errors
π Deployment Checklist β
- [ ] KV namespace created
- [ ] Webhook secret set
- [ ] API auth service deployed
- [ ] Custom domain configured (optional)
- [ ] Webhook handler deployed
- [ ] LemonSqueezy webhook configured
- [ ] Luna Vision RAG MCP updated with validation
- [ ] Email templates configured
- [ ] Test API key generated
- [ ] Test validation working
- [ ] Test webhook flow end-to-end
- [ ] Monitor logs for errors
π‘ Next Steps β
After API key system is live:
- Update Documentation - Add API key setup instructions
- Create Dashboard - Let users view usage and manage keys
- Add Analytics - Track feature usage
- Set Up Alerts - Monitor for issues
- Plan Features - What else can you gate?
π Your API key system is production-ready!