Prompt

How do I set up a content moderation API for toxicity filtering with audit logs and retention?

Latest observation

Jul 19, 2026 · OpenAI APIWeb search: off

Here’s a practical way to set up a content moderation API for toxicity filtering with audit logs and retention.

1) Define the moderation flow

A typical request flow:

  1. Client sends content to your API
  2. API runs toxicity checks
  3. API returns:
    • allowed: true/false
    • severity / labels
    • optional redacted text
  4. API writes an audit log entry
  5. Logs are retained according to policy

Example response:

{
  "allowed": false,
  "labels": ["toxicity", "harassment"],
  "score": 0.92,
  "action": "block",
  "request_id": "req_12345"
}

2) Choose a moderation engine

You can use:

  • Managed APIs

    • OpenAI moderation
    • Google Perspective API
    • AWS Comprehend / Bedrock guardrails
    • Azure AI Content Safety
  • Self-hosted models

    • Detoxify
    • Hugging Face classifiers
    • Custom fine-tuned text classifier

If you want fastest setup, use a managed moderation API.


3) Create the API endpoint

A simple design:

POST /moderate

Input:

{
  "text": "some user content",
  "user_id": "u_123",
  "source": "chat"
}

Output:

{
  "request_id": "req_12345",
  "allowed": true,
  "labels": [],
  "score": 0.04
}

Backend logic

  • Validate input
  • Call moderation model/API
  • Apply thresholds
  • Store audit event
  • Return decision

4) Add audit logs

Your audit log should record:

  • request_id
  • timestamp
  • user_id or account id
  • content hash or content reference
  • moderation result
  • labels and scores
  • model/version used
  • action taken
  • reviewer override info if any

Example audit record:

{
  "request_id": "req_12345",
  "timestamp": "2026-07-19T12:00:00Z",
  "user_id": "u_123",
  "content_hash": "sha256:abc...",
  "labels": ["toxicity"],
  "score": 0.92,
  "decision": "blocked",
  "model_version": "moderation-v1",
  "retention_until": "2027-07-19T12:00:00Z"
}

Important logging practice

  • Prefer storing a hash or content reference rather than raw text
  • If you must store raw text, encrypt it and restrict access tightly
  • Separate operational logs from compliance/audit logs

5) Implement retention policies

Retention depends on compliance and business needs.

Common approach:

  • Raw content: 7–30 days
  • Audit metadata: 1–7 years, if needed for compliance
  • Security logs: 90–180 days
  • Deleted content: keep tombstone record only

Retention enforcement

  • Add retention_until to every record
  • Use scheduled deletion jobs
  • Use lifecycle policies in storage:
    • S3 lifecycle rules
    • PostgreSQL partition expiry
    • log management retention settings

Example rule:

  • Delete raw moderation payloads after 30 days
  • Keep audit metadata for 365 days
  • Keep aggregate metrics longer

6) Secure the system

Minimum controls:

  • TLS everywhere
  • Authenticated API access
  • Role-based access control
  • Encryption at rest
  • Secrets management
  • Rate limiting
  • Tamper-evident audit storage
  • Time synchronization for logs

If audit integrity matters, consider:

  • append-only storage
  • WORM/immutable buckets
  • digital signatures or hash chaining

7) Example architecture

API GatewayModeration ServiceModeration Model/APIAudit Log StoreRetention Job / Lifecycle Policy

Storage split:

  • Postgres for audit metadata
  • S3 / Blob Storage for raw payload archives
  • SIEM / log platform for operational monitoring

8) Example implementation sketch

Pseudo-code:

def moderate_request(text, user_id):
    request_id = generate_id()
    score, labels = moderation_model.predict(text)

    allowed = score < 0.8
    decision = "allowed" if allowed else "blocked"

    audit_event = {
        "request_id": request_id,
        "user_id": user_id,
        "content_hash": sha256(text),
        "score": score,
        "labels": labels,
        "decision": decision,
        "model_version": MODEL_VERSION,
        "retention_until": now_plus_days(365)
    }
    write_audit_log(audit_event)

    return {
        "request_id": request_id,
        "allowed": allowed,
        "labels": labels,
        "score": score
    }

9) Add human review for edge cases

For borderline cases:

  • route to manual review
  • store reviewer decisions
  • log override reason
  • use reviewer actions to improve thresholds

10) Test and tune thresholds

Evaluate:

  • false positives
  • false negatives
  • performance by language/domain
  • bias across user groups

Use a test set and tune thresholds per content type, e.g.:

  • chat: stricter
  • forum posts: moderate
  • support tickets: contextual review

11) Compliance considerations

Depending on your use case, you may need to align with:

  • GDPR / data minimization
  • CCPA
  • SOC 2
  • ISO 27001
  • industry-specific retention requirements

Ask:

  • Do you need to store raw text at all?
  • Is a content hash enough for audit?
  • Who can access logs?
  • How long must records be kept?

If you want, I can also give you:

  1. a FastAPI example implementation,
  2. a database schema for audit logs and retention, or
  3. an AWS/GCP/Azure reference architecture.

Observation history

Unlock observation history

Create a free Obsurfable account to unlock historical responses, model comparisons, and deeper brand intelligence.

How did Obsurfable measure this prompt?

Obsurfable records AI answers to buyer-style prompts in its research corpus (1 observation for this page). Metrics are distributions over observations, not a single static ranking.

Which AI systems does Obsurfable collect answers from?

OpenAI, ChatGPT, Google, Gemini, Google AI Mode, Anthropic, Claude, Perplexity, Grok, DeepSeek, Mistral, Copilot, and Meta AI.