Engineering Workspace

Privacy & PII de-identification

Detect and de-identify personal data in text before it reaches a model or leaves your boundary. The text path runs locally on CPU, regex and checksum recognizers, no model weights and no GPU.

Overview

HybrIE exposes its privacy primitives as three endpoints, reachable from the Stimulir Python SDK and the stimulir CLI. The text path uses built-in regex and checksum recognizers (email, phone, SSN, IBAN, credit-card via Luhn, API keys, JWT, and more), it is pure CPU, loads no model, and needs no GPU.

De-identify never echoes raw PII. deidentify returns only the redacted text, a redaction count, and the distinct entity-type labels detected, never the matched values. Use extract when you explicitly want the spans and their text.

Endpoints

POST/v1/privacy/deidentify
POST/v1/privacy/extract
GET/v1/privacy/capabilities

Through the SDK (api-key plane) these are served at /api/v1/privacy/*; the CLI reaches them via the console proxy at /api/v1/hybrie/privacy/*. Either way the work runs on the HybrIE runtime, you only hold an hyb_* key.

Anonymization methods

deidentify takes a method (applied to every detected entity) and optional per-entity-type overrides. A method is a string kind, or an object with parameters.

ParameterTypeDescription
replaceplaceholder?Replace with a placeholder; defaults to the typed token (<EMAIL>, <IBAN>, …).
redactn/aDrop the span entirely.
maskmask_char, keep_tailMask each character, keeping the last keep_tail characters visible.
hash_sha256 / hash_sha512salt? (base64)Replace with a hex digest; stable for the same input + salt.
encrypt / decryptkey (base64)AES-256-GCM with a 16/24/32-byte key. Treat keys as secrets, never log them.
keepn/aLeave the original text unchanged (Presidio-style passthrough).
replace_consistenttemplate?Stable numbered placeholder per value, e.g. <EMAIL_1>, <EMAIL_2>.

Python SDK

de-identify, override, extract
from stimulir import StimulirClient

client = StimulirClient()  # reads STIMULIR_API_KEY (hyb_*)

# Redact every detected entity with its typed placeholder
result = client.privacy.deidentify("Email me at sarah.johnson@example.com")
print(result["text"])          # "Email me at <EMAIL>"
print(result["redactions"])    # 1
print(result["entity_types"])  # ["email"]

# Pick a default method, override per entity type
client.privacy.deidentify(
    "card 4111 1111 1111 1111, reach me at a@b.com",
    method="redact",
    overrides={"email": {"kind": "mask", "mask_char": "*", "keep_tail": 4}},
)

# Detect without de-identifying (returns the full entity list)
entities = client.privacy.extract("SSN 123-45-6789 on file")

# What the runtime supports (methods + recognizer count)
client.privacy.capabilities()

Per-entity-type overrides

Keys are entity types in snake_case (email, phone_number,iban, credit_debit_card, …); any type not in overrides falls through to the top-level method.

CLI

stimulir privacy
# De-identify (default method is replace)
stimulir privacy deidentify --text "Email me at sarah.johnson@example.com"

# Mask, keeping the last 4 characters
stimulir privacy deidentify --text "card 4111 1111 1111 1111" \
  --method mask --mask-char "*" --keep-tail 4

# Detect PII entities (table, or --json)
stimulir privacy extract --text "SSN 123-45-6789 on file"

# Supported methods + recognizer count
stimulir privacy capabilities

Need the SDK or CLI? See Python SDK and CLI Installation.