FastPII Docs
Protection API

Protection API

Production REST API for protecting PII in text with replace, mask, hash, tokenize, and policy modes.

Protection API

The Protection API detects PII in text and applies a protection transformation in a single call. It runs at https://api.fastpii.com/api/v1/ and offers five protection modes for different privacy requirements.

If you are using the open-source SDK locally, see the anonymization, redaction, masking, and removing-data guides instead. If you want a Python client, see FastPII Connect.

Authentication

All Protection API endpoints require an API key:

Authorization: Bearer fpk_your_api_key

See the Detection API authentication section for details on managing API keys.

Protection modes

The Protection API offers five modes for handling detected PII:

ModeDescriptionReversible?Use case
replaceReplace PII with a placeholder like [REDACTED]NoLogs, reports, LLM prompts
maskReplace PII with asterisks preserving original lengthNoVisual preservation, formatting
hashReplace PII with a consistent hash (same input produces same output)NoAnalytics, deduplication
tokenizeReplace PII with a reversible token that can be restored laterYesData processing, later restoration
policyUse gateway policy rules to determine the actionVariesEnterprise, dynamic enforcement

Choose a mode based on whether you need to preserve format, enable analytics, or restore the original data later.

POST /api/v1/protect

Protect PII in text using the specified mode.

Request body

FieldTypeRequiredDefaultDescription
textstringYes-Text to protect (1-50,000 characters)
modestringNo"replace"Protection mode: replace, mask, hash, tokenize, policy
countrystringNonullISO 3166-1 alpha-2 country code. Auto-detected if null.
languagestringNonullLanguage hint for detection
privacy_presetstringNonull"conservative", "balanced", or "aggressive"

The policy mode requires an Enterprise plan. If you use policy mode on a non-Enterprise plan, the API returns a 400 error.

Response fields

FieldTypeDescription
original_textstringOriginal text before protection
protected_textstringText after PII protection was applied
entitieslistProtected PII entities
countries_detectedlistCountries detected by Intelligence Engine
protection_modestringProtection mode used
processing_time_msfloatProcessing time in milliseconds
api_versionstringAPI version (default "v1")

ProtectedEntity

FieldTypeDescription
typestringEntity type (e.g., rodne_cislo, email, phone)
originalstringThe original text that was detected
protectedstringThe protected or replaced text
countrystring or nullCountry code if entity is country-specific
confidencefloatDetection confidence (0-1)
validatedbooleanWhether the entity passed checksum validation
startintegerStart position in original text
endintegerEnd position in original text
metadataobject or nullAdditional entity metadata

Replace mode (default)

Replaces each PII entity with [REDACTED]:

curl -X POST https://api.fastpii.com/api/v1/protect \
  -H "Authorization: Bearer fpk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Email: jan.novak@example.cz, RČ: 8001011238",
    "mode": "replace"
  }'
import requests

response = requests.post(
    "https://api.fastpii.com/api/v1/protect",
    headers={"Authorization": "Bearer fpk_your_api_key"},
    json={
        "text": "Email: jan.novak@example.cz, RČ: 8001011238",
        "mode": "replace",
    },
)
result = response.json()
print(result["protected_text"])
# Email: [REDACTED], RČ: [REDACTED]

Response:

{
  "original_text": "Email: jan.novak@example.cz, RČ: 8001011238",
  "protected_text": "Email: [REDACTED], RČ: [REDACTED]",
  "entities": [
    {
      "type": "email",
      "original": "jan.novak@example.cz",
      "protected": "[REDACTED]",
      "country": "cz",
      "confidence": 0.95,
      "validated": false,
      "start": 7,
      "end": 27,
      "metadata": {}
    },
    {
      "type": "rodne_cislo",
      "original": "8001011238",
      "protected": "[REDACTED]",
      "country": "cz",
      "confidence": 1.0,
      "validated": true,
      "start": 33,
      "end": 43,
      "metadata": {"checksum_valid": true, "birth_date": "1980-01-01", "gender": "male"}
    }
  ],
  "countries_detected": [{"code": "cz", "confidence": 0.98}],
  "protection_mode": "replace",
  "processing_time_ms": 4.1,
  "api_version": "v1"
}

Mask mode

Replaces PII with asterisks while preserving the original text length:

curl -X POST https://api.fastpii.com/api/v1/protect \
  -H "Authorization: Bearer fpk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Email: jan.novak@example.cz, RČ: 8001011238",
    "mode": "mask"
  }'
result = requests.post(
    "https://api.fastpii.com/api/v1/protect",
    headers={"Authorization": "Bearer fpk_your_api_key"},
    json={"text": "Email: jan.novak@example.cz, RČ: 8001011238", "mode": "mask"},
).json()
print(result["protected_text"])
# Email: *******************, RČ: **********

Hash mode

Replaces PII with a consistent hash. The same input always produces the same output, which enables analytics and deduplication without revealing the original value:

curl -X POST https://api.fastpii.com/api/v1/protect \
  -H "Authorization: Bearer fpk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Email: jan.novak@example.cz, RČ: 8001011238",
    "mode": "hash"
  }'
result = requests.post(
    "https://api.fastpii.com/api/v1/protect",
    headers={"Authorization": "Bearer fpk_your_api_key"},
    json={"text": "Email: jan.novak@example.cz, RČ: 8001011238", "mode": "hash"},
).json()
print(result["protected_text"])
# Email: a3f2b8c1, RČ: 7e9d4f2a

Tokenize mode

Replaces PII with a reversible token. The original value can be restored later using the token:

curl -X POST https://api.fastpii.com/api/v1/protect \
  -H "Authorization: Bearer fpk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Email: jan.novak@example.cz, RČ: 8001011238",
    "mode": "tokenize"
  }'
result = requests.post(
    "https://api.fastpii.com/api/v1/protect",
    headers={"Authorization": "Bearer fpk_your_api_key"},
    json={"text": "Email: jan.novak@example.cz, RČ: 8001011238", "mode": "tokenize"},
).json()
print(result["protected_text"])
# Email: tok_cz_email_a3f2b8c1, RČ: tok_cz_rc_7e9d4f2a

Protection with privacy preset

curl -X POST https://api.fastpii.com/api/v1/protect \
  -H "Authorization: Bearer fpk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Contact john@example.com or call +420 777 123 456",
    "mode": "replace",
    "privacy_preset": "aggressive"
  }'

Protection with country detection

curl -X POST https://api.fastpii.com/api/v1/protect \
  -H "Authorization: Bearer fpk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "RČ: 8001011238, PESEL: 44051401458",
    "mode": "mask",
    "country": "cz"
  }'

When to use each mode

ScenarioRecommended modeWhy
Sending text to an LLMreplace or maskRemoves PII before it reaches the model
Logging user inputsmaskPreserves text structure and length for log analysis
Analytics on PII fieldshashSame input produces same hash, enabling grouping and counting
Temporary data processingtokenizeCan restore the original value when processing is complete
Enterprise policy enforcementpolicyUses your configured gateway policies to decide the action

Error responses

StatusMeaningWhen
400Bad RequestInvalid mode, text too long, or policy mode on non-Enterprise plan
401UnauthorizedInvalid or missing API key
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer-side failure

policy mode on non-Enterprise:

{"detail": "Policy mode requires Enterprise plan. Use replace, mask, hash, or tokenize."}

Using with FastPII Connect

from fastpii_connect import FastPIIClient

client = FastPIIClient(api_key="fpk_your_api_key")

result = client.protect("My rodné číslo is 900101/1234", mode="replace")
print(result.protected_text)

result = client.protect("My rodné číslo is 900101/1234", mode="mask")
print(result.protected_text)

result = client.protect("My rodné číslo is 900101/1234", mode="hash")
print(result.protected_text)

See the client reference for full method signatures.

On this page