Overview

PrivyGate is an enterprise-grade PII anonymization gateway for LLM applications. It provides a transparent proxy that automatically detects and anonymizes sensitive data before sending to LLM providers, then restores original data in responses.

Key Features

  • OpenAI SDK compatible - zero code changes required
  • Passthrough mode - use your own API keys
  • Southeast Asia localized - Singapore NRIC, Indonesia NIK, etc.
  • Reversible anonymization - real data restored in responses

Authentication

PrivyGate supports passthrough authentication. Your API key is passed through to the upstream LLM provider (OpenAI, DeepSeek, etc.) via the standard Authorization header.

HTTP Header
Authorization: Bearer sk-your-openai-api-key

PrivyGate does not store your API key. It is only used to forward requests to the upstream provider.

Quick Start

Replace your OpenAI base_url with PrivyGate's URL. That's it!

Python
from openai import OpenAI

# Point to PrivyGate instead of OpenAI directly
client = OpenAI(
    base_url="https://privygate.your-company.com/v1",
    api_key="sk-your-openai-key"  # Your key, passed through to OpenAI
)

# Use normally - PII is automatically protected
response = client.chat.completions.create(
    model="gpt-4",
    messages=[{
        "role": "user",
        "content": "Customer John Tan (NRIC: S1234567D) is asking about their balance."
    }]
)

print(response.choices[0].message.content)
# PII is anonymized before reaching OpenAI, restored in response
cURL
curl -X POST https://privygate.your-company.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-your-openai-key" \
  -d '{
    "model": "gpt-4",
    "messages": [
      {"role": "user", "content": "Customer John Tan (NRIC: S1234567D) needs help."}
    ]
  }'

Chat Completions

POST /v1/chat/completions

OpenAI-compatible chat completions endpoint with automatic PII anonymization.

Request Body

Parameter Type Description
model string Model ID (e.g., "gpt-4", "gpt-3.5-turbo")
messages array Array of message objects
stream boolean Enable streaming (optional)
temperature number Sampling temperature 0-2 (optional)

Example

# Request
POST /v1/chat/completions
Authorization: Bearer sk-xxx

{
  "model": "gpt-4",
  "messages": [
    {"role": "user", "content": "John Tan (S1234567D) needs account info."}
  ]
}

# What OpenAI receives (anonymized)
{
  "model": "gpt-4",
  "messages": [
    {"role": "user", "content": "David Lee (S9876543A) needs account info."}
  ]
}

# Response you receive (restored)
{
  "choices": [{
    "message": {
      "content": "I'll help John Tan (S1234567D) with their account..."
    }
  }]
}

PII Scan

POST /v1/pii/scan

Detect PII entities in text without anonymization. Useful for validation and testing.

Request

{
  "text": "Customer John Tan (NRIC: S1234567D, Email: john@example.com)",
  "language": "auto"
}

Response

{
  "entities": [
    {
      "text": "John Tan",
      "type": "PERSON",
      "start": 9,
      "end": 17,
      "score": 0.95
    },
    {
      "text": "S1234567D",
      "type": "SG_NRIC",
      "start": 25,
      "end": 34,
      "score": 1.0
    },
    {
      "text": "john@example.com",
      "type": "EMAIL",
      "start": 43,
      "end": 59,
      "score": 1.0
    }
  ],
  "entity_count": 3,
  "processing_time_ms": 45.2
}

PII Anonymize

POST /v1/pii/anonymize

Anonymize PII in text and get a mapping ID for later de-anonymization.

Request

{
  "text": "Customer John Tan (NRIC: S1234567D) needs help.",
  "return_mapping": true
}

Response

{
  "anonymized_text": "Customer David Lee (NRIC: S9876543A) needs help.",
  "mapping_id": "req_abc123def456",
  "mappings": [
    {
      "original": "John Tan",
      "replacement": "David Lee",
      "type": "PERSON"
    },
    {
      "original": "S1234567D",
      "replacement": "S9876543A",
      "type": "SG_NRIC"
    }
  ]
}

PII De-anonymize

POST /v1/pii/deanonymize

Restore original PII using a mapping ID from a previous anonymize call.

Request

{
  "text": "David Lee's account balance is $1,234.56",
  "mapping_id": "req_abc123def456"
}

Response

{
  "original_text": "John Tan's account balance is $1,234.56"
}

Supported LLM Providers

PrivyGate supports multiple LLM providers in passthrough mode. Use your own API key with any supported provider - PrivyGate automatically handles API format conversion and PII protection.

OpenAI

Native support

Models: gpt-4 gpt-4-turbo gpt-3.5-turbo

Key format: sk-xxx

DeepSeek

OpenAI-compatible

Models: deepseek-chat deepseek-reasoner

Key format: sk-xxx

Anthropic Claude

Auto format conversion

Models: claude-3-5-sonnet claude-3-opus claude-3-haiku

Key format: sk-ant-xxx

Google Gemini

Auto format conversion

Models: gemini-2.5-pro gemini-2.5-flash gemini-2.0-flash

Key format: AIzaSy...

Unified API Interface

Use the same OpenAI-style API format for all providers. PrivyGate automatically converts requests/responses between formats. Just change the model parameter and provide the corresponding API key.

Example: Using Claude

curl -X POST https://privygate.your-company.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-ant-your-anthropic-key" \
  -d '{
    "model": "claude-3-5-sonnet-20241022",
    "messages": [{"role": "user", "content": "Customer John Tan (NRIC: S1234567D) needs help."}],
    "max_tokens": 1024
  }'

# PrivyGate automatically:
# 1. Anonymizes PII in the request
# 2. Converts OpenAI format → Anthropic format
# 3. Forwards to Anthropic API
# 4. Converts response back to OpenAI format
# 5. Restores original PII in response

Supported PII Types

Type Region Example
PERSON Universal John Tan, 张三
EMAIL Universal user@example.com
PHONE Universal +65 9123 4567
CREDIT_CARD Universal 4111-1111-1111-1111
SG_NRIC 🇸🇬 Singapore S1234567D
SG_FIN 🇸🇬 Singapore G1234567N
ID_NIK 🇮🇩 Indonesia 3201234567890001
CN_ID 🇨🇳 China 110101199001011234
TH_ID 🇹🇭 Thailand 1234567890123
MY_NRIC 🇲🇾 Malaysia 880101-14-1234