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_keySee the Detection API authentication section for details on managing API keys.
Protection modes
The Protection API offers five modes for handling detected PII:
| Mode | Description | Reversible? | Use case |
|---|---|---|---|
replace | Replace PII with a placeholder like [REDACTED] | No | Logs, reports, LLM prompts |
mask | Replace PII with asterisks preserving original length | No | Visual preservation, formatting |
hash | Replace PII with a consistent hash (same input produces same output) | No | Analytics, deduplication |
tokenize | Replace PII with a reversible token that can be restored later | Yes | Data processing, later restoration |
policy | Use gateway policy rules to determine the action | Varies | Enterprise, 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
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| text | string | Yes | - | Text to protect (1-50,000 characters) |
| mode | string | No | "replace" | Protection mode: replace, mask, hash, tokenize, policy |
| country | string | No | null | ISO 3166-1 alpha-2 country code. Auto-detected if null. |
| language | string | No | null | Language hint for detection |
| privacy_preset | string | No | null | "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
| Field | Type | Description |
|---|---|---|
| original_text | string | Original text before protection |
| protected_text | string | Text after PII protection was applied |
| entities | list | Protected PII entities |
| countries_detected | list | Countries detected by Intelligence Engine |
| protection_mode | string | Protection mode used |
| processing_time_ms | float | Processing time in milliseconds |
| api_version | string | API version (default "v1") |
ProtectedEntity
| Field | Type | Description |
|---|---|---|
| type | string | Entity type (e.g., rodne_cislo, email, phone) |
| original | string | The original text that was detected |
| protected | string | The protected or replaced text |
| country | string or null | Country code if entity is country-specific |
| confidence | float | Detection confidence (0-1) |
| validated | boolean | Whether the entity passed checksum validation |
| start | integer | Start position in original text |
| end | integer | End position in original text |
| metadata | object or null | Additional 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Č: 7e9d4f2aTokenize 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_7e9d4f2aProtection 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
| Scenario | Recommended mode | Why |
|---|---|---|
| Sending text to an LLM | replace or mask | Removes PII before it reaches the model |
| Logging user inputs | mask | Preserves text structure and length for log analysis |
| Analytics on PII fields | hash | Same input produces same hash, enabling grouping and counting |
| Temporary data processing | tokenize | Can restore the original value when processing is complete |
| Enterprise policy enforcement | policy | Uses your configured gateway policies to decide the action |
Error responses
| Status | Meaning | When |
|---|---|---|
| 400 | Bad Request | Invalid mode, text too long, or policy mode on non-Enterprise plan |
| 401 | Unauthorized | Invalid or missing API key |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server-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.