Skip to main content

Python SDK for the raipii PII detection and sanitization API

Project description

raipii Python SDK

Detect and sanitize PII before it reaches your LLM. Replace real data with tokens or realistic fakes. Restore original values after the model responds.

PyPI version Python 3.8+


Install

pip install raipii

Requires Python 3.8+. The only dependency is requests.


Quick start

import raipii

ps = raipii.Raipii(api_key="ps_live_...")

# 1. Sanitize — strip PII before sending to your LLM
result = ps.sanitize(
    "Hi, I'm John Smith — john@acme.com, SSN 392-45-7810",
    mode="fake_substitute",
)
print(result.sanitized_text)
# "Hi, I'm Michael Torres — m.torres@email.net, SSN 847-23-1956"

# 2. Call your LLM with the sanitized prompt
llm_response = your_llm(result.sanitized_text)

# 3. Restore — put original values back in the response
original = ps.restore(llm_response, result.session_id)
print(original.restored_text)
# "Hi, I'm John Smith — john@acme.com, SSN 392-45-7810"

Set RAIPII_API_KEY in your environment to avoid passing the key in code:

export RAIPII_API_KEY=ps_live_...
ps = raipii.Raipii()  # reads RAIPII_API_KEY automatically

Get a free API key (2M chars/month) at raipii.com.


Sanitize modes

token (default)

Replaces PII with labelled placeholder tokens. Safe, lossless, fully reversible.

result = ps.sanitize(
    "Schedule a call with Jane Doe at jane@corp.com on 555-867-5309",
    mode="token",
)
print(result.sanitized_text)
# "Schedule a call with [PERSON_1] at [EMAIL_1] on [PHONE_1]"

# Each token maps back to its original value on restore
restored = ps.restore(llm_response, result.session_id)

fake_substitute

Replaces PII with realistic Faker-generated values. The LLM sees natural data and produces better output. All substitutions are reversed on restore.

result = ps.sanitize(
    "Write a summary for John Smith, DOB 1985-03-12, SSN 392-45-7810",
    mode="fake_substitute",
)
print(result.sanitized_text)
# "Write a summary for Michael Torres, DOB 1991-07-24, SSN 847-23-1956"

restored = ps.restore(llm_response, result.session_id)
# LLM response has fake values swapped back to real ones

redact

Replaces PII with [REDACTED]. One-way — there is nothing to restore. Use when the LLM response must never reference PII at all.

result = ps.sanitize(
    "Patient John Smith, MRN 00123456, DOB 1985-03-12",
    mode="redact",
)
print(result.sanitized_text)
# "Patient [REDACTED], MRN [REDACTED], DOB [REDACTED]"

Detect only

Scan text for PII without modifying it. Useful for logging, compliance auditing, or deciding whether to sanitize.

result = ps.detect("My SSN is 392-45-7810 and email is john@acme.com")

print(result.pii_detected)   # True
print(result.risk_level)     # "HIGH"

for entity in result.entities_found:
    print(f"  {entity.type}: {entity.value!r} at {entity.position} ({entity.confidence:.0%} confidence)")
# US_SSN: '392-45-7810' at (10, 21) (100% confidence)
# EMAIL:  'john@acme.com' at (35, 48) (100% confidence)

Risk levels: NONELOWMEDIUMHIGH

Risk Triggered by
HIGH SSN, credit card, MRN, bank account, tax ID
MEDIUM Person name, email, date of birth, address
LOW Any other detected entity
NONE No PII found

Detected entity types

Type Example Tier
PERSON John Smith All tiers
EMAIL john@acme.com All tiers
PHONE 555-867-5309 All tiers
US_SSN 392-45-7810 All tiers
CREDIT_CARD 4111 1111 1111 1111 All tiers
DATE_OF_BIRTH 1985-03-12 All tiers
ADDRESS 123 Main St, Austin TX Growth+
IP_ADDRESS 192.168.1.1 All tiers
MEDICAL_RECORD_NUMBER MRN 00123456 All tiers
BANK_ACCOUNT 12345678 All tiers
TAX_ID 12-3456789 All tiers
IBAN GB29 NWBK 6016 1331 9268 19 All tiers
JWT eyJhbGci... All tiers
AWS_KEY AKIA... All tiers

Starter tier detects structured PII reliably. Growth and Business tiers add enhanced contextual detection with higher accuracy for unstructured entities such as names and addresses.


Multi-turn conversations

Keep consistent fake substitutions across all turns of a conversation. The same entity always maps to the same fake value within a session.

conv = ps.conversations.create(ttl=86400)  # 24hr TTL

# Turn 1
turn1 = ps.sanitize(
    "My name is John Smith. What should I know about my account?",
    mode="fake_substitute",
    conversation_id=conv.conversation_id,
)
llm_reply_1 = your_llm(turn1.sanitized_text)
response1 = ps.restore(llm_reply_1, turn1.session_id)

# Turn 2 — "John Smith" maps to the SAME fake name as turn 1
turn2 = ps.sanitize(
    "What were you saying about John Smith earlier?",
    mode="fake_substitute",
    conversation_id=conv.conversation_id,
)
llm_reply_2 = your_llm(turn2.sanitized_text)
response2 = ps.restore(llm_reply_2, turn2.session_id)

Error handling

from raipii import (
    AuthenticationError,
    QuotaExceededError,
    NotFoundError,
    ValidationError,
    RateLimitError,
    ServiceUnavailableError,
)

try:
    result = ps.sanitize(text)
except AuthenticationError:
    # Invalid or missing API key
    print("Check your API key at raipii.com")
except QuotaExceededError:
    # Monthly character limit reached
    print("Upgrade your plan at raipii.com")
except NotFoundError:
    # Session expired or not found
    print("Session expired — re-sanitize the original text")
except RateLimitError:
    # Too many requests — SDK retries automatically, this means retries exhausted
    print("Rate limit hit")
except ServiceUnavailableError:
    # Detection backend temporarily unavailable — SDK retried 3 times
    print("Service unavailable, try again shortly")
except ValidationError as e:
    print(f"Bad request: {e}")

All exceptions inherit from raipii.RaipiiError and expose .status_code and .response.


Retry behaviour

The SDK automatically retries on 429 Too Many Requests and 503 Service Unavailable with exponential backoff:

Attempt Delay
1st retry 1s
2nd retry 2s
3rd retry 4s

Default max_retries=3. Override:

ps = raipii.Raipii(api_key="...", max_retries=5)
ps_no_retry = raipii.Raipii(api_key="...", max_retries=0)

Client options

ps = raipii.Raipii(
    api_key="ps_live_...",    # or RAIPII_API_KEY env var
    base_url="https://api.raipii.com",  # override for testing
    timeout=30,               # request timeout in seconds
    max_retries=3,            # retries on 429/503
)

Return types

SanitizeResult

Field Type Description
session_id str Pass to restore()
sanitized_text str Text with PII replaced
entities_found list[EntityFound] Each detected entity
char_count int Characters processed
usage.chars_billed int Characters billed
conversation_id str | None Echo of the conversation_id passed in

RestoreResult

Field Type Description
restored_text str Text with original PII restored
substitutions_reversed int Number of tokens replaced
usage.chars_billed int Characters billed

DetectResult

Field Type Description
entities_found list[DetectedEntity] Detected PII entities
pii_detected bool True if any PII found
risk_level str NONE / LOW / MEDIUM / HIGH
usage.chars_billed int Characters billed

Caveats

  • Session TTL — sessions expire after session_ttl seconds (default 1hr). Calling restore() after expiry raises NotFoundError. Store the session_id and call restore promptly after getting the LLM response.
  • redact mode has no restore[REDACTED] tokens contain no reversible information. Calling restore() on a redact session returns the text unchanged.
  • Conversation TTL — conversation sessions expire after their TTL (default 24hr). After expiry, new turns start a fresh mapping.
  • Characters billed — both sanitize and restore bill by character count of the input text. detect also bills. Free tier: 2M chars/month.
  • Starter tier detects structured PII reliably. Upgrade to Growth for enhanced contextual detection of names and addresses in free-form text.

Get an API key

Free tier — 2M characters/month, no credit card required: raipii.com

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

raipii-0.1.0.tar.gz (9.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

raipii-0.1.0-py3-none-any.whl (9.5 kB view details)

Uploaded Python 3

File details

Details for the file raipii-0.1.0.tar.gz.

File metadata

  • Download URL: raipii-0.1.0.tar.gz
  • Upload date:
  • Size: 9.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for raipii-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b346d07643b70b9934a75996a26cffccb00d4e90aaac4394ec4d97d9d987965c
MD5 ef5585519c2c83d2c68dbd2fe6f9f479
BLAKE2b-256 4835f059be93f80dce51efe359e2998777131f305252e9d46732a85de5da3bd7

See more details on using hashes here.

File details

Details for the file raipii-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: raipii-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 9.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for raipii-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 62f15bbe25a0d623954dabcd0c19484112c9400cf4ad3796662c48eb8bb8c568
MD5 55eebc9f34c07e33c4ea50936a215831
BLAKE2b-256 0d1687bd8e196f272490979f045b2b7ae9d934e4ee5312dcc51b57b94350db0a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page