Detection API
Production REST API for PII detection and validation with Intelligence Engine auto-detection.
Detection API
The Detection API is FastPII's production REST API for detecting and validating PII at https://api.fastpii.com/api/v1/. It is separate from the open-source SDK's built-in FastAPI integration, which you can self-host inside your own application.
If you want the in-process SDK workflow instead of the hosted API, see the SDK Detection guide and the FastAPI integration guide.
Authentication
Send your API key in the Authorization header for every request:
Authorization: Bearer fpk_your_api_keyRequests without a valid API key return 401 Unauthorized.
Base URL
https://api.fastpii.com/api/v1/Rate limits
The Detection API applies per-key rate limiting to protect shared production capacity.
| Limit | Value |
|---|---|
| Default request rate | 60 requests per minute |
| Burst limit | 10 concurrent requests |
| Batch detection | Counts as 1 request toward rate limits |
When you hit the limit, the API returns 429 Too Many Requests. Rate limit headers may include:
| Header | Description |
|---|---|
X-RateLimit-Limit | Requests allowed in the current window |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp for the next reset |
Retry-After | Seconds to wait before retrying |
POST /api/v1/detect
Detect and validate PII entities in a single text payload. If country is omitted or set to null, the Intelligence Engine auto-detects the most likely countries from the content.
Request body
DetectRequest
| Field | Type | Required | Description |
|---|---|---|---|
text | string | Yes | Input text to analyze, 1 to 50000 characters |
country | string | null | No | ISO country code. If null, the API auto-detects the country or countries |
language | string | null | No | Language hint such as "en", "de", or "fr" |
privacy_preset | string | No | Detection sensitivity preset: "conservative", "balanced", or "aggressive" |
{
"text": "Customer email is jana.novakova@example.cz and rodne cislo 8053121234.",
"country": "CZ",
"language": "cs",
"privacy_preset": "balanced"
}Response body
DetectResponse
| Field | Type | Description |
|---|---|---|
text | string | Original input text |
entities | DetectedEntity[] | Detected and validated entities |
countries_detected | CountryDetection[] | Countries inferred from the text |
privacy_preset | string | Effective privacy preset used for detection |
processing_time_ms | integer | End-to-end processing time in milliseconds |
api_version | string | API version that served the request |
DetectedEntity
| Field | Type | Description |
|---|---|---|
type | string | Entity type such as "email", "rodne_cislo", "pesel", or "phone_number" |
original | string | Exact matched text from the input |
country | string | null | Country associated with the detector |
confidence | number | Confidence score from 0 to 1 |
validated | boolean | Whether the value passed checksum or structural validation |
start | integer | Zero-based start offset |
end | integer | Zero-based end offset |
metadata | object | Detector-specific metadata |
CountryDetection
| Field | Type | Description |
|---|---|---|
code | string | ISO country code |
confidence | number | Confidence score from 0 to 1 |
Example: simple single-country detection
curl -X POST "https://api.fastpii.com/api/v1/detect" \
-H "Authorization: Bearer fpk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"text": "Contact Jana Novakova at jana.novakova@example.cz or 775 123 456.",
"country": "CZ",
"language": "cs",
"privacy_preset": "balanced"
}'import requests
response = requests.post(
"https://api.fastpii.com/api/v1/detect",
headers={
"Authorization": "Bearer fpk_your_api_key",
"Content-Type": "application/json",
},
json={
"text": "Contact Jana Novakova at jana.novakova@example.cz or 775 123 456.",
"country": "CZ",
"language": "cs",
"privacy_preset": "balanced",
},
timeout=30,
)
print(response.status_code)
print(response.json())Response:
{
"text": "Contact Jana Novakova at jana.novakova@example.cz or 775 123 456.",
"entities": [
{
"type": "email",
"original": "jana.novakova@example.cz",
"country": "CZ",
"confidence": 0.99,
"validated": true,
"start": 25,
"end": 49,
"metadata": {
"normalized": "jana.novakova@example.cz"
}
},
{
"type": "phone_number",
"original": "775 123 456",
"country": "CZ",
"confidence": 0.95,
"validated": true,
"start": 53,
"end": 64,
"metadata": {
"e164": "+420775123456",
"line_type": "mobile"
}
}
],
"countries_detected": [
{
"code": "CZ",
"confidence": 0.99
}
],
"privacy_preset": "balanced",
"processing_time_ms": 18,
"api_version": "v1"
}Example: multi-country auto-detection
Use country: null when your input may contain identifiers from more than one market.
curl -X POST "https://api.fastpii.com/api/v1/detect" \
-H "Authorization: Bearer fpk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"text": "PESEL 44051401458 belongs to Jan Kowalski. French billing record includes SIREN 552120222 and email compta@exemple.fr.",
"country": null,
"language": "en",
"privacy_preset": "balanced"
}'import requests
response = requests.post(
"https://api.fastpii.com/api/v1/detect",
headers={
"Authorization": "Bearer fpk_your_api_key",
"Content-Type": "application/json",
},
json={
"text": "PESEL 44051401458 belongs to Jan Kowalski. French billing record includes SIREN 552120222 and email compta@exemple.fr.",
"country": None,
"language": "en",
"privacy_preset": "balanced",
},
timeout=30,
)
print(response.json())Response:
{
"text": "PESEL 44051401458 belongs to Jan Kowalski. French billing record includes SIREN 552120222 and email compta@exemple.fr.",
"entities": [
{
"type": "pesel",
"original": "44051401458",
"country": "PL",
"confidence": 1.0,
"validated": true,
"start": 6,
"end": 17,
"metadata": {
"birth_date": "1944-05-14",
"gender": "male",
"checksum_valid": true
}
},
{
"type": "siren",
"original": "552120222",
"country": "FR",
"confidence": 1.0,
"validated": true,
"start": 83,
"end": 92,
"metadata": {
"checksum_valid": true
}
},
{
"type": "email",
"original": "compta@exemple.fr",
"country": "FR",
"confidence": 0.98,
"validated": true,
"start": 103,
"end": 120,
"metadata": {
"normalized": "compta@exemple.fr"
}
}
],
"countries_detected": [
{
"code": "FR",
"confidence": 0.96
},
{
"code": "PL",
"confidence": 0.94
}
],
"privacy_preset": "balanced",
"processing_time_ms": 27,
"api_version": "v1"
}Example: selective detection with privacy_preset
Use a stricter preset when you only want high-confidence matches, or an aggressive preset when you would rather catch more possible PII for review.
curl -X POST "https://api.fastpii.com/api/v1/detect" \
-H "Authorization: Bearer fpk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"text": "Reach me at maria.schmidt@example.de, tax id 86095742719, office line 030 1234567.",
"country": "DE",
"language": "de",
"privacy_preset": "aggressive"
}'import requests
payload = {
"text": "Reach me at maria.schmidt@example.de, tax id 86095742719, office line 030 1234567.",
"country": "DE",
"language": "de",
"privacy_preset": "aggressive",
}
response = requests.post(
"https://api.fastpii.com/api/v1/detect",
headers={
"Authorization": "Bearer fpk_your_api_key",
"Content-Type": "application/json",
},
json=payload,
timeout=30,
)
print(response.json())Response:
{
"text": "Reach me at maria.schmidt@example.de, tax id 86095742719, office line 030 1234567.",
"entities": [
{
"type": "email",
"original": "maria.schmidt@example.de",
"country": "DE",
"confidence": 0.99,
"validated": true,
"start": 12,
"end": 37,
"metadata": {
"normalized": "maria.schmidt@example.de"
}
},
{
"type": "steuer_id",
"original": "86095742719",
"country": "DE",
"confidence": 1.0,
"validated": true,
"start": 46,
"end": 57,
"metadata": {
"checksum_valid": true
}
},
{
"type": "phone_number",
"original": "030 1234567",
"country": "DE",
"confidence": 0.88,
"validated": true,
"start": 71,
"end": 82,
"metadata": {
"e164": "+49301234567",
"line_type": "fixed_line"
}
}
],
"countries_detected": [
{
"code": "DE",
"confidence": 0.98
}
],
"privacy_preset": "aggressive",
"processing_time_ms": 21,
"api_version": "v1"
}POST /api/v1/validate
Validate a single value against a specific entity type and optional country.
Request body
ValidateRequest
| Field | Type | Required | Description |
|---|---|---|---|
value | string | Yes | Raw value to validate |
entity_type | string | Yes | Entity type to validate against |
country | string | null | No | ISO country code when validation should be country-specific |
{
"value": "44051401458",
"entity_type": "pesel",
"country": "PL"
}Response body
ValidateResponse
| Field | Type | Description |
|---|---|---|
value | string | Original input value |
entity_type | string | Entity type used for validation |
country | string | null | Country used during validation |
valid | boolean | Whether the value passed validation |
confidence | number | Confidence score from 0 to 1 |
metadata | object | Validation metadata such as checksum status or normalized values |
curl -X POST "https://api.fastpii.com/api/v1/validate" \
-H "Authorization: Bearer fpk_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"value": "44051401458",
"entity_type": "pesel",
"country": "PL"
}'import requests
response = requests.post(
"https://api.fastpii.com/api/v1/validate",
headers={
"Authorization": "Bearer fpk_your_api_key",
"Content-Type": "application/json",
},
json={
"value": "44051401458",
"entity_type": "pesel",
"country": "PL",
},
timeout=30,
)
print(response.json())Response:
{
"value": "44051401458",
"entity_type": "pesel",
"country": "PL",
"valid": true,
"confidence": 1.0,
"metadata": {
"checksum_valid": true,
"birth_date": "1944-05-14",
"gender": "male"
}
}GET /api/v1/detectors
List available detectors. You can filter the catalog by country code.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
country | string | No | ISO country code filter such as CZ, DE, FR, or PL |
Response body
DetectorsResponse
| Field | Type | Description |
|---|---|---|
detectors | DetectorInfo[] | Available detectors |
count | integer | Number of returned detectors |
DetectorInfo
| Field | Type | Description |
|---|---|---|
name | string | Stable detector name |
description | string | Human-readable detector summary |
region | string | Region or country code |
category | string | Detector category such as identity, contact, or financial |
curl -X GET "https://api.fastpii.com/api/v1/detectors?country=DE" \
-H "Authorization: Bearer fpk_your_api_key"import requests
response = requests.get(
"https://api.fastpii.com/api/v1/detectors",
headers={"Authorization": "Bearer fpk_your_api_key"},
params={"country": "DE"},
timeout=30,
)
print(response.json())Response:
{
"detectors": [
{
"name": "steuer_id",
"description": "German tax identification number with checksum validation.",
"region": "DE",
"category": "identity"
},
{
"name": "phone_de",
"description": "German landline and mobile phone number detection.",
"region": "DE",
"category": "contact"
},
{
"name": "address_de",
"description": "German address pattern detection with city and postal code support.",
"region": "DE",
"category": "location"
},
{
"name": "iban",
"description": "International bank account number detection and validation.",
"region": "DE",
"category": "financial"
}
],
"count": 4
}Error responses
The API uses standard HTTP status codes and returns a JSON error payload.
| Status | Meaning | Typical cause |
|---|---|---|
400 | Bad Request | Invalid JSON, missing required fields, or text outside allowed limits |
401 | Unauthorized | Missing API key or invalid bearer token |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Server Error | Unexpected server-side failure |
400 Bad Request
{
"error": {
"code": "invalid_request",
"message": "Field 'text' must contain between 1 and 50000 characters.",
"details": {
"field": "text"
}
}
}401 Unauthorized
{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key."
}
}429 Too Many Requests
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Retry after 12 seconds."
}
}500 Internal Server Error
{
"error": {
"code": "internal_error",
"message": "An unexpected error occurred while processing the request."
}
}Next steps
Use the hosted Detection API when you want managed production infrastructure, API keys, and centralized rate limiting. If you want embedded detection inside your Python app, continue with the SDK Detection guide.