OpenAI Content Moderator API

July 19, 2026 · View on GitHub

A production-ready REST API for content moderation using OpenAI's moderation API. This service provides a secure, scalable interface for moderating text content with comprehensive validation, error handling, and deployment options for both traditional servers and AWS Lambda.

⚠️ Important: Google Perspective API integration is currently incomplete and under development. The API currently uses OpenAI moderation only. Perspective API functionality will be added in a future release.

Features

  • Request Validation: Comprehensive input validation with detailed error messages
  • OpenAI Integration: Direct integration with OpenAI's moderation API
  • Google Perspective API: Integration with Google's Perspective API (⚠️ Not yet complete - Coming soon)
  • RESTful Design: Clean, intuitive API endpoints following REST principles
  • Metadata Enrichment: Response metadata including timestamps, text length, and model info
  • Error Handling: Robust error handling with consistent response formats
  • Environment Configuration: Flexible configuration for different deployment environments
  • AWS Lambda Ready: Serverless deployment support with AWS Lambda
  • Comprehensive Testing: Full test coverage with unit and integration tests
  • CORS Support: Configurable CORS for browser-based applications

Quick Start

# Clone the repository
git clone https://github.com/karlgroves/openai-content-moderator.git
cd openai-content-moderator

# Install dependencies
npm install

# Configure environment
cp .env.example .env
# Edit .env and add your OPENAI_API_KEY

# Run the API
npm start

The API will be available at http://localhost:8000

API Endpoints

POST /api/moderation/text

Moderate text content using OpenAI's moderation API.

Analyzes text content for potentially harmful content using OpenAI's moderation API.

Request:

{
  "text": "Text content to moderate"
}

Headers:

Content-Type: application/json

Response (200 OK):

{
  "flagged": false,
  "services": {
    "openai": {
      "results": {
        "flagged": false,
        "categories": {
          "harassment": false,
          "harassment/threatening": false,
          "sexual": false,
          "hate": false,
          "hate/threatening": false,
          "illicit": false,
          "illicit/violent": false,
          "self-harm/intent": false,
          "self-harm/instructions": false,
          "self-harm": false,
          "sexual/minors": false,
          "violence": false,
          "violence/graphic": false
        },
        "category_scores": {
          "harassment": 0.000024923252458203565,
          "harassment/threatening": 0.000003169325442919291,
          "sexual": 0.00016229670614688406,
          "hate": 0.000005829126566113866,
          "hate/threatening": 2.4061023397180247e-7,
          "illicit": 0.00004173157606777201,
          "illicit/violent": 0.000010889691002655445,
          "self-harm/intent": 0.00000288571183887091,
          "self-harm/instructions": 0.0000016964426510543331,
          "self-harm": 0.000006605214485464791,
          "sexual/minors": 0.000010554685795431098,
          "violence": 0.00048644850322948033,
          "violence/graphic": 0.000006605214485464791
        },
        "category_applied_input_types": {
          "harassment": ["text"],
          "harassment/threatening": ["text"],
          "sexual": ["text"],
          "hate": ["text"],
          "hate/threatening": ["text"],
          "illicit": ["text"],
          "illicit/violent": ["text"],
          "self-harm/intent": ["text"],
          "self-harm/instructions": ["text"],
          "self-harm": ["text"],
          "sexual/minors": ["text"],
          "violence": ["text"],
          "violence/graphic": ["text"]
        }
      },
      "metadata": {
        "timestamp": "2025-08-26T19:49:29.449Z",
        "textLength": 12,
        "model": "omni-moderation-latest"
      }
    }
  },
  "metadata": {
    "timestamp": "2025-08-26T19:49:29.449Z",
    "textLength": 12,
    "servicesUsed": ["openai"]
  }
}

Error Response (400 Bad Request):

{
  "error": "Text content is required for moderation.",
  "field": "text"
}

GET /api/moderation/models

Returns a list of available moderation models.

Response (200 OK):

{
  "models": [
    {
      "id": "omni-moderation-latest",
      "name": "Omni Moderation Latest",
      "description": "Latest OpenAI moderation model"
    }
  ]
}

GET /health

Health check endpoint for monitoring and load balancers.

Response (200 OK):

{
  "status": "healthy",
  "timestamp": "2025-08-26T19:49:31.302Z",
  "service": "openai-content-moderator"
}

POST /moderate (Legacy)

Legacy endpoint maintained for backward compatibility. Automatically redirects to /api/moderation/text.

Note: This endpoint is deprecated and will be removed in a future version. Please update your integration to use /api/moderation/text.

Installation

Prerequisites

  • Node.js 20.x or higher (see .nvmrc — run nvm use)
  • npm or yarn
  • OpenAI API key (Get one here)
  • nodemon (for development mode) - npm install -g nodemon

Optional security CLIs

The security:* npm scripts below use external binaries. If a binary is missing, the corresponding script prints an install hint and exits 0.

ToolPurposeInstall
osv-scannerCVEs in dependenciesbrew install osv-scanner
semgrepStatic analysis (OWASP Top 10, Node.js rules)brew install semgrep or pip install semgrep
trufflehogSecret scanning (verifies credentials against live services)brew install trufflehog

Step-by-Step Installation

  1. Clone the repository:

    git clone https://github.com/karlgroves/openai-content-moderator.git
    cd openai-content-moderator
    
  2. Install dependencies:

    npm install
    
  3. Configure environment variables:

    cp .env.example .env
    
  4. Add your OpenAI API key to .env:

    OPENAI_API_KEY=sk-your-api-key-here
    
  5. Verify installation:

    npm test
    

    All tests should pass before proceeding.

Usage

Development Mode

Run with auto-reload for development (requires nodemon):

npm run dev

Note: If you don't have nodemon installed, install it globally first:

npm install -g nodemon

Production Mode

Run in production mode:

npm start

Testing the API

Once running, you can test the API using curl:

# Moderate text
curl -X POST http://localhost:8000/api/moderation/text \
  -H "Content-Type: application/json" \
  -d '{"text": "This is a test message"}'

# Check health
curl http://localhost:8000/health

# Get available models
curl http://localhost:8000/api/moderation/models

Using with JavaScript/Node.js

const response = await fetch('http://localhost:8000/api/moderation/text', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    text: 'Content to moderate',
  }),
});

const result = await response.json();
console.log('Flagged:', result.flagged);
console.log('OpenAI Results:', result.services.openai.results);

Testing

The project includes comprehensive unit and integration tests using Jest and Supertest.

# Run all tests
npm test

# Run tests with coverage
npm run test:coverage

# Run tests in watch mode (for development)
npm run test:watch


# Run only unit tests
npm run test:unit

# Run only integration tests
npm run test:integration

Note: The test:unit and test:integration scripts are not currently defined in package.json. To run specific test suites:

# Unit tests only
jest tests/unit

# Integration tests only
jest tests/integration

Test Coverage:

  • Unit tests for all middleware components
  • Integration tests for API endpoints
  • Validation testing for all input scenarios
  • Error handling verification
  • Mock OpenAI API interactions

Test Structure:

  • tests/unit/ - Unit tests for individual components
  • tests/integration/ - Full API endpoint testing
  • tests/fixtures/ - Test data and mock responses
  • tests/helpers/ - Test utilities and helper functions

Configuration

Environment Variables

Configure the application using environment variables in your .env file:

VariableRequiredDefaultDescription
OPENAI_API_KEYYes-Your OpenAI API key
OPENAI_MODELNoomni-moderation-latestOpenAI moderation model to use
GOOGLE_PERSPECTIVE_API_KEYNo-Google Perspective API key (optional)
PERSPECTIVE_API_ENABLEDNofalseEnable Google Perspective API integration
PORTNo8000Port number for the API server
NODE_ENVNodevelopmentEnvironment (development/production)
CORS_ORIGINNo*CORS allowed origins

Example .env file

# Required
OPENAI_API_KEY=sk-your-api-key-here

# Optional - OpenAI Configuration
OPENAI_MODEL=omni-moderation-latest

# Optional - Google Perspective API (⚠️ integration in development)
GOOGLE_PERSPECTIVE_API_KEY=your-google-perspective-api-key-here
PERSPECTIVE_API_ENABLED=true

# Optional - Server Configuration
PORT=3000
NODE_ENV=production
CORS_ORIGIN=https://yourdomain.com

⚠️ Important: The Google Perspective API integration is not yet functional. The perspective.js middleware exists but is not fully implemented. Setting PERSPECTIVE_API_ENABLED=true will not enable this feature until development is complete.

Architecture

Middleware Chain

  1. Validation Middleware (middleware/validation.js)

    • Validates request body
    • Checks text presence, type, and length (max 32,768 characters)
    • Returns 400 errors for invalid requests
  2. Moderation Middleware (middleware/moderation.js)

    • Calls OpenAI Moderation API
    • Handles API-specific errors
    • Adds metadata to responses
  3. Perspective Middleware (middleware/perspective.js)

    • ⚠️ Not yet complete - Placeholder for Google Perspective API integration
    • Will provide toxicity analysis when implemented
  4. Error Handler (middleware/errorHandler.js)

    • Global error handling
    • Consistent error response format
    • Handles OpenAI API errors gracefully

Error Handling

The API provides consistent error responses with detailed information:

Error Response Format

{
  "error": "ErrorType",
  "message": "Human-readable error description",
  "field": "field_name" // Only for validation errors
}

HTTP Status Codes

Status CodeDescriptionExample
200SuccessRequest processed successfully
400Bad RequestMissing or invalid text field
401UnauthorizedInvalid or missing OpenAI API key
413Payload Too LargeText exceeds 32,768 characters
429Rate LimitedOpenAI API rate limit exceeded
500Server ErrorUnexpected server error
503Service UnavailableOpenAI API temporarily unavailable

Common Error Scenarios

Missing Text:

{
  "error": "Text content is required for moderation.",
  "field": "text"
}

Invalid API Key:

{
  "error": "AuthenticationError",
  "message": "Invalid API key provided"
}

Rate Limit:

{
  "error": "RateLimitError",
  "message": "Rate limit exceeded. Please try again later."
}

Deployment

Traditional Server Deployment

  1. Using PM2:

    npm install -g pm2
    pm2 start index.js --name content-moderator
    pm2 save
    pm2 startup
    
  2. Using systemd (Linux):

    Create a service file and configure it to run the Node.js application.

  3. Docker Support:

    Docker configuration is not currently included but can be easily added. Create a Dockerfile with:

    FROM node:18-alpine
    WORKDIR /app
    COPY package*.json ./
    RUN npm ci --only=production
    COPY . .
    EXPOSE 8000
    CMD ["node", "index.js"]
    

AWS Lambda Deployment

This project includes AWS Lambda support through the Serverless Framework. See DEPLOYMENT.md for detailed instructions.

Prerequisites:

  • AWS CLI configured with appropriate credentials
  • Serverless Framework installed (npm install -g serverless)

Quick deployment:

npm install
serverless deploy

Note: There is no npm run deploy script defined. Use the Serverless Framework directly.

Security Best Practices

  1. API Key Security:

    • Never commit .env files to version control
    • Use environment-specific API keys
    • Rotate API keys regularly
    • Consider using AWS Secrets Manager or similar for production
  2. Rate Limiting:

    • Implement application-level rate limiting
    • Use API Gateway throttling for AWS deployments
    • Monitor usage patterns
  3. Input Validation:

    • Maximum text length enforced (32,768 characters)
    • Content-Type validation
    • Request body size limits
  4. CORS Configuration:

    • Set specific origins in production
    • Avoid using wildcard (*) in production environments

Monitoring and Logging

  • Health Checks: Use /health endpoint for monitoring
  • Logging: Console logging (structured JSON logging can be added for production)
  • Metrics: Track API usage, response times, and error rates (implementation needed)
  • Alerts: Set up alerts for high error rates or API failures (requires external monitoring)
  • Use AWS CloudWatch for Lambda deployments
  • Consider New Relic, Datadog, or Prometheus for traditional deployments
  • Implement structured logging with Winston or Bunyan for production

Project Structure

openai-content-moderator/
├── config/              # Configuration files
│   └── index.js        # Main configuration module
├── middleware/         # Express middleware
│   ├── errorHandler.js # Global error handling
│   ├── moderation.js   # OpenAI API integration
│   ├── perspective.js  # Google Perspective API (incomplete)
│   └── validation.js   # Request validation
├── routes/             # API route definitions
│   └── moderation.js   # Moderation endpoints
├── tests/              # Test suites
│   ├── fixtures/       # Mock data
│   ├── helpers/        # Test utilities
│   ├── integration/    # API endpoint tests
│   └── unit/          # Component tests
├── docs/               # Documentation
├── index.js           # Main application entry
├── lambda.js          # AWS Lambda handler
└── serverless.yml     # Serverless Framework config

Support and Contributing

Getting Help

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Run tests to ensure everything passes (npm test)
  4. Make your changes
  5. Add tests for new functionality
  6. Ensure all tests pass (npm test)
  7. Commit your changes (git commit -m 'Add amazing feature')
  8. Push to the branch (git push origin feature/amazing-feature)
  9. Open a Pull Request

Important: All tests must pass before any PR can be merged. See CLAUDE.md for development guidelines.

License

MIT License - see LICENSE file for details

Acknowledgments