A step-by-step tutorial that takes you from zero to a working detection call in about five minutes: get an API key, send one POST request, and read back every sensitive entity in your text with its type, position, and confidence.
Every request is authenticated with an API key. Create an account on the Get Started page — after signing up you will find your key in the dashboard. It looks something like this:
Your API key: pk_a1b2c3d4e5f67890abcdef1234567890
Treat the key like a password: keep it in an environment variable or a secrets manager, never in client-side code or a public repository. If you just want to see detection results before signing up, the live demo runs without a key.
The API has a single endpoint that accepts a JSON body: POST https://piidetectionapi.com/api/moderate.php. Three fields are required — your api_key, the api_type (always "pii_detection"), and the text to scan (up to 50,000 characters per request). Paste this into a terminal, replacing YOUR_API_KEY:
curl -X POST https://piidetectionapi.com/api/moderate.php \ -H "Content-Type: application/json" \ -d '{ "api_key": "YOUR_API_KEY", "api_type": "pii_detection", "text": "Contact John Doe at [email protected] or 555-123-4567." }'
The API answers with a JSON object. The heart of it is detected_entities: one item per finding, with the entity type, the exact matched text, its character offsets in your input, and a confidence score:
{
"detected_entities": [
{"type": "PERSON_NAME", "text": "John Doe", "start": 8, "end": 16, "confidence": 0.95},
{"type": "EMAIL_ADDRESS", "text": "[email protected]", "start": 20, "end": 36, "confidence": 0.98},
{"type": "PHONE_NUMBER", "text": "555-123-4567", "start": 40, "end": 52, "confidence": 0.99}
],
"anonymized_text": "Contact [NAME] at [EMAIL] or [PHONE].",
"entities_detected": 3,
"processing_time_ms": 187,
"mask_mode_used": "replace",
"status": 200
}| Field | Meaning |
|---|---|
detected_entities | Array of findings. Each has type, text (exact match), start/end (character offsets in your input), and confidence (0–1). |
anonymized_text | Your input with detected values masked — the optional redaction step, controlled by mask_mode. |
entities_detected | Total number of findings. |
processing_time_ms | Server-side processing time in milliseconds. |
status | 200 on success; any other value comes with an error message. |
anonymized_text gives you a ready-made masked copy for free.In an application you will usually call the API from code. With Python's requests:
import requests
resp = requests.post(
"https://piidetectionapi.com/api/moderate.php",
json={
"api_key": "YOUR_API_KEY",
"api_type": "pii_detection",
"text": "Contact John Doe at [email protected] or 555-123-4567.",
},
timeout=30,
)
data = resp.json()
for e in data["detected_entities"]:
print(e["type"], e["text"], e["start"], e["end"], e["confidence"])And with JavaScript (Node 18+ or any modern runtime with fetch):
const resp = await fetch("https://piidetectionapi.com/api/moderate.php", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ api_key: process.env.PII_API_KEY, api_type: "pii_detection", text: "Contact John Doe at [email protected] or 555-123-4567.", }), }); const data = await resp.json(); console.log(data.entities_detected, "entities found"); data.detected_entities.forEach(e => console.log(`${e.type}: "${e.text}" @ ${e.start}-${e.end} (${e.confidence})`) );
By default every entity type is scanned. Two optional arrays give you precise control: entities is an allowlist, exclude_entities a blocklist. For a PCI sweep of support tickets, for example, you only need payment data and direct identifiers:
{
"api_key": "YOUR_API_KEY",
"api_type": "pii_detection",
"text": "Card 4111 1111 1111 1111, CVV 123, cardholder Jane Roe",
"entities": ["CREDIT_CARD_NUMBER", "CVV_NUMBER", "PERSON_NAME", "IBAN_CODE"]
}The full catalogue — from SSN and PASSPORT_NUMBER to DIAGNOSIS, API_KEY, and GPS_COORDINATES — is on the supported entity types reference, grouped by category with examples.
Two more optional fields shape the result. threshold (default 0.5) sets the minimum confidence a finding needs to be reported — raise it toward 0.8–0.9 when false positives are costly, lower it when you must not miss anything. mask_mode chooses how anonymized_text is built:
| mask_mode | Behavior | Example output |
|---|---|---|
replace (default) | Substitutes typed placeholders. | Contact [NAME] at [EMAIL] |
redact | Removes the sensitive values entirely. | Contact at ... |
hash | Replaces each value with a consistent hash, so the same person stays linkable across records without being identifiable. | Contact e3b0c44a at a5f2d1c9 |
{
"api_key": "YOUR_API_KEY",
"api_type": "pii_detection",
"text": "Escalated by Jane Roe ([email protected]) about Acme Corp invoice 4482.",
"threshold": 0.8,
"mask_mode": "replace",
"custom_instruction": "Do not flag the company name 'Acme Corp' or invoice numbers"
}status in every response: 400 means a malformed request (e.g. missing api_key), 401/403 an invalid key, 429 a rate limit. The error field explains what went wrong — log it, back off, and retry where appropriate.You now have a working detection pipeline: authenticate, POST text, parse detected_entities, and optionally use anonymized_text. From here: