managarten/services/mana-api-gateway/CLAUDE.md
Till-JS fc0ed636fc feat(api-gateway): add Swagger, admin endpoints, and scheduler
- Add Swagger/OpenAPI documentation at /docs endpoint
- Add admin module for system-wide API key management
- Add scheduler for monthly credit reset and usage cleanup
- Add Docker Compose entry for Mac Mini deployment
- Document all endpoints with descriptions and examples
2026-01-29 18:03:16 +01:00

9.1 KiB

Mana API Gateway

Custom NestJS API Gateway for monetizing ManaCore services (mana-search, mana-stt, mana-tts).

Overview

  • Port: 3030
  • Technology: NestJS 10 + Drizzle ORM + Redis
  • Purpose: API Key Management, Usage Tracking, Rate Limiting, Credit-based Billing

Architecture

                        ┌─────────────────────────┐
                        │     API Gateway         │
                        │      (Port 3030)        │
                        │                         │
    Clients ───────────>│  • API Key Validation   │
    (X-API-Key Header)  │  • Rate Limiting        │
                        │  • Usage Tracking       │
                        │  • Credit Deduction     │
                        └───────────┬─────────────┘
                                    │
              ┌─────────────────────┼─────────────────────┐
              │                     │                     │
              ▼                     ▼                     ▼
      ┌───────────────┐     ┌───────────────┐     ┌───────────────┐
      │  mana-search  │     │   mana-stt    │     │   mana-tts    │
      │  (Port 3021)  │     │  (Port 3020)  │     │  (Port 3022)  │
      └───────────────┘     └───────────────┘     └───────────────┘

Quick Start

Development

# Install dependencies
pnpm install

# Push database schema
pnpm db:push

# Start in development mode
pnpm dev

Production

# Build
pnpm build

# Start
pnpm start

API Endpoints

Public API (with API Key)

Method Endpoint Description Credits
POST /v1/search Web search 1
POST /v1/extract Content extraction 1
POST /v1/extract/bulk Bulk extraction 1 per URL
GET /v1/search/engines Available search engines 0
POST /v1/stt/transcribe Audio → Text 10/min
GET /v1/stt/models Available STT models 0
GET /v1/stt/languages Supported languages 0
POST /v1/tts/synthesize Text → Audio 1/1000 chars
GET /v1/tts/voices Available voices 0
GET /v1/tts/languages Supported languages 0

Management API (with JWT)

Method Endpoint Description
POST /api-keys Create new API key
GET /api-keys List all API keys
GET /api-keys/:id Get API key details
PATCH /api-keys/:id Update API key
DELETE /api-keys/:id Delete API key
POST /api-keys/:id/regenerate Regenerate API key
GET /api-keys/:id/usage Get usage statistics
GET /api-keys/:id/usage/summary Get usage summary

Admin API (with JWT + Admin Role)

Method Endpoint Description
GET /admin/api-keys List all API keys (paginated)
GET /admin/api-keys/:id Get any API key details
PATCH /admin/api-keys/:id Update any key (tier, credits, limits)
DELETE /admin/api-keys/:id Delete any API key
GET /admin/usage/summary System-wide usage stats
GET /admin/usage/top-users Top users by usage

System

Method Endpoint Description
GET /health Health check
GET /metrics Prometheus metrics
GET /docs Swagger/OpenAPI documentation

Pricing Tiers

Tier Rate Limit Monthly Credits Endpoints Price
Free 10 req/min 100 Search only Free
Pro 100 req/min 5,000 All €19/month
Enterprise 1,000 req/min 50,000 All €99/month

Credit Costs

Operation Cost
Search 1 credit
Extract 1 credit
STT 10 credits/minute
TTS 1 credit/1000 chars

Usage Examples

Create an API Key

# First, get a JWT token from mana-core-auth
TOKEN=$(curl -s -X POST http://localhost:3001/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com", "password": "password"}' | jq -r '.accessToken')

# Create an API key
curl -X POST http://localhost:3030/api-keys \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "My API Key", "tier": "free"}'

Use the API

# Search
curl -X POST http://localhost:3030/v1/search \
  -H "X-API-Key: sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"query": "quantum computing"}'

# Extract content
curl -X POST http://localhost:3030/v1/extract \
  -H "X-API-Key: sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/article"}'

# Text-to-Speech
curl -X POST http://localhost:3030/v1/tts/synthesize \
  -H "X-API-Key: sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"text": "Hello, world!", "voice": "en-US-1"}' \
  --output audio.mp3

# Speech-to-Text
curl -X POST http://localhost:3030/v1/stt/transcribe \
  -H "X-API-Key: sk_live_xxx" \
  -F "file=@audio.wav"

Check Usage

curl http://localhost:3030/api-keys/{id}/usage \
  -H "Authorization: Bearer $TOKEN"

Environment Variables

Variable Default Description
PORT 3030 API port
DATABASE_URL - PostgreSQL connection URL
REDIS_HOST localhost Redis host
REDIS_PORT 6379 Redis port
SEARCH_SERVICE_URL http://localhost:3021 mana-search URL
STT_SERVICE_URL http://localhost:3020 mana-stt URL
TTS_SERVICE_URL http://localhost:3022 mana-tts URL
MANA_CORE_AUTH_URL http://localhost:3001 Auth service URL
ADMIN_USER_IDS - Comma-separated admin user IDs

Development Commands

# Install dependencies
pnpm install

# Start development server
pnpm dev

# Build for production
pnpm build

# Start production server
pnpm start

# Type checking
pnpm type-check

# Linting
pnpm lint

# Database commands
pnpm db:push       # Push schema to database
pnpm db:generate   # Generate migrations
pnpm db:migrate    # Run migrations
pnpm db:studio     # Open Drizzle Studio

Database Schema

The gateway uses its own schema (api_gateway) in the shared ManaCore database:

  • api_gateway.api_keys - API key storage and configuration
  • api_gateway.api_usage - Detailed usage logs
  • api_gateway.api_usage_daily - Aggregated daily usage for billing

Rate Limiting

Rate limiting uses Redis with a sliding window algorithm:

  • Each API key has a configurable rate limit (requests per minute)
  • Rate limit headers are included in responses:
    • X-RateLimit-Limit - Maximum requests per minute
    • X-RateLimit-Remaining - Remaining requests
    • X-RateLimit-Reset - Unix timestamp when limit resets

Authentication

Two types of authentication:

  1. X-API-Key header - For public API endpoints (/v1/*)
  2. Bearer JWT token - For management endpoints (/api-keys/*)

The JWT token is validated against mana-core-auth service.

Project Structure

services/mana-api-gateway/
├── src/
│   ├── main.ts                 # Application entry point
│   ├── app.module.ts           # Root module
│   ├── config/
│   │   ├── configuration.ts    # App configuration
│   │   └── pricing.ts          # Pricing tiers and credit costs
│   ├── db/
│   │   ├── schema/             # Drizzle schemas
│   │   ├── database.module.ts  # Database provider
│   │   ├── connection.ts       # DB connection
│   │   └── migrate.ts          # Migration script
│   ├── api-keys/               # API key management
│   ├── usage/                  # Usage tracking
│   ├── proxy/                  # Proxy services to backends
│   ├── guards/                 # Auth, rate limit, credits guards
│   ├── common/                 # Decorators, filters, interceptors
│   ├── credits/                # Credits service (mana-core-auth client)
│   ├── metrics/                # Prometheus metrics
│   └── health/                 # Health check endpoint
├── drizzle.config.ts           # Drizzle Kit configuration
├── package.json
├── tsconfig.json
└── Dockerfile

Troubleshooting

API Key not working

  1. Check the key is valid: curl -H "X-API-Key: $KEY" http://localhost:3030/health
  2. Check the key is active in the database
  3. Check the key hasn't expired
  4. Check the endpoint is allowed for the key's tier

Rate limit exceeded

Wait for the X-RateLimit-Reset timestamp, or upgrade to a higher tier.

Credits exhausted

Check usage with the management API, or wait for monthly reset.