Metadata-Version: 2.4
Name: xybern-redact
Version: 0.1.1
Summary: Python SDK for Xybern Redact — anonymize PII before it reaches any LLM
Project-URL: Homepage, https://xybern.com
Project-URL: Docs, https://docs.xybern.com/redact/quick-start
Project-URL: Issues, https://github.com/xybern-ai/xybern-redact/issues
Author-email: Xybern <charalambos.theodorou@xybern.com>
License: MIT
Keywords: ai,anonymization,gdpr,llm,pii,privacy,redact
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.9
Requires-Dist: httpx>=0.24.0
Description-Content-Type: text/markdown

<p align="center">
  <img src="https://raw.githubusercontent.com/xybern-ai/xybern-redact/main/logo.png" alt="Xybern Redact" width="120" />
</p>

# xybern-redact

Python SDK for [Xybern Redact](https://xybern.com) — anonymize PII before it reaches any LLM and restore real values in the response.

```bash
pip install xybern-redact
```

## Requirements

- Python 3.9+
- A Xybern workspace with an API key (`xr_live_...`) — get one at [xybern.com](https://xybern.com)

## Quick start

```python
from xybern_redact import RedactClient

client = RedactClient(api_key="xr_live_YOUR_KEY")

result = client.anonymize("Michael Chen signed the contract on 12 March 2024.")
print(result.text)
# "Morgan Ross signed the contract on 11 April 2024."

print(result.entity_count)   # 2
print(result.entities)       # {"PERSON": 1, "DATE": 1}
```

## Anonymize then call any LLM yourself

```python
from xybern_redact import RedactClient
from anthropic import Anthropic

redact = RedactClient(api_key="xr_live_YOUR_KEY")
llm    = Anthropic(api_key="sk-ant-...")

# Strip PII before sending
anon = redact.anonymize("Summarise the contract signed by Michael Chen at Goldman Sachs.")

# Call the LLM with the clean text
response = llm.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=512,
    messages=[{"role": "user", "content": anon.text}],
)

# Restore real names in the response
original = redact.deanonymize(response.content[0].text, anon.entity_map)
print(original)
# Michael Chen and Goldman Sachs are restored.
```

## Use the built-in proxy

The proxy handles anonymization and de-anonymization automatically:

```python
response = client.chat(
    model="claude-sonnet-4-6",
    messages=[{"role": "user", "content": "Summarise the contract signed by Michael Chen."}],
)
print(response.content)
# Response already has real names restored.
```

## Anonymize a file

```python
result = client.anonymize_file("contract.pdf")

with open("contract_clean.pdf", "wb") as f:
    f.write(result.content)

print(f"{result.entity_count} entities anonymized")
```

## Multi-turn conversations

```python
thread = "session_abc123"

r1 = client.anonymize("Michael Chen signed.", thread_id=thread)
r2 = client.anonymize("Chen reviewed the annexes.", thread_id=thread)

# Both map "Chen" to the same pseudonym across the thread.
```

## Error handling

```python
from xybern_redact import RedactClient, AuthenticationError, APIError

try:
    client = RedactClient(api_key="xr_live_YOUR_KEY")
    result = client.anonymize(text)
except AuthenticationError:
    print("Invalid or missing API key.")
except APIError as e:
    print(f"Server error {e.status_code}: {e}")
```

## Context manager

```python
with RedactClient(api_key="xr_live_YOUR_KEY") as client:
    result = client.anonymize("...")
```

## Links

- [Documentation](https://docs.xybern.com/redact/quick-start)
- [Changelog](https://docs.xybern.com/changelog)
- [Xybern](https://xybern.com)
