Anthropic Data Handling
Overview
Anthropic's data policies: API inputs/outputs are NOT used for model training (commercial API). Zero-day retention is available. This skill covers PII redaction before sending to Claude and compliance patterns.
Anthropic Data Policies
| Policy |
Details |
| Training data |
API data is NOT used for training (commercial API) |
| Data retention |
30-day default; 0-day available via agreement |
| Encryption |
TLS 1.2+ in transit, AES-256 at rest |
| SOC 2 Type II |
Certified |
| HIPAA BAA |
Available for eligible customers |
PII Redaction Before API Calls
import re
import anthropic
def redact_pii(text: str) -> tuple[str, dict]:
"""Redact PII before sending to Claude, return redaction map for restoration."""
redaction_map = {}
patterns = [
(r'\b\d{3}-\d{2}-\d{4}\b', 'SSN', '[SSN-REDACTED-{}]'),
(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', 'EMAIL', '[EMAIL-REDACTED-{}]'),
(r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b', 'PHONE', '[PHONE-REDACTED-{}]'),
(r'\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b', 'CARD', '[CARD-REDACTED-{}]'),
]
counter = 0
for pattern, label, replacement in patterns:
for match in re.finditer(pattern, text):
counter += 1
placeholder = replacement.format(counter)
redaction_map[placeholder] = match.group()
text = text.replace(match.group(), placeholder, 1)
return text, redaction_map
def restore_pii(text: str, redaction_map: dict) -> str:
"""Restore redacted PII in Claude's response."""
for placeholder, original in redaction_map.items():
text = text.replace(placeholder, original)
return text
# Usage
user_input = "Contact John at john@example.com or 555-123-4567"
safe_input, redactions = redact_pii(user_input)
# safe_input: "Contact John at [EMAIL-REDACTED-1] or [PHONE-REDACTED-2]"
client = anthropic.Anthropic()
msg = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=256,
messages=[{"role": "user", "content": safe_input}]
)
final_output = restore_pii(msg.content[0].text, redactions)
Audit Logging
import json
import logging
from datetime import datetime, timezone
audit_logger = logging.getLogger("claude.audit")
def audited_request(client, user_id: str, purpose: str, **kwargs):
"""Wrap Claude API calls with audit logging."""
# Log request metadata (never log content)
audit_logger.info(json.dumps({
"event": "claude.request",
"timestamp": datetime.now(timezone.utc).isoformat(),
"user_id": user_id,
"purpose": purpose,
"model": kwargs.get("model"),
"max_tokens": kwargs.get("max_tokens"),
}))
response = client.messages.create(**kwargs)
audit_logger.info(json.dumps({
"event": "claude.response",
"request_id": response._request_id,
"input_tokens": response.usage.input_tokens,
"output_tokens": response.usage.output_tokens,
"stop_reason": response.stop_reason,
}))
return response
Data Handling Checklist
Error Handling
| Risk |
Mitigation |
| PII in prompts |
Pre-call redaction pipeline |
| PII in responses |
Post-call output scanning |
| Audit log gaps |
Centralized logging with alerting |
| Data subject access request |
Searchable audit trail by user_id |
Prerequisites
- Define the data classification, processing purpose, legal basis or user consent, and retention owner before sending anything to the API.
- Provide an approved redaction policy, a secret-manager-backed API credential, and an allowlisted Anthropic workspace or service boundary.
- Prepare synthetic fixtures that exercise each PII class and a deletion test; do not use real customer records while validating the pipeline.
Instructions
- Classify the input and reject fields outside the approved purpose or destination. Apply deterministic redaction before constructing the request; keep any restoration map encrypted, access-controlled, and short-lived.
- Run the redaction, prompt, and response scanners against synthetic fixtures. A failed scan, missing consent, or unexpected content block is a hard stop; do not retry with the original data.
- Call the Messages API with the least-privileged credential and only the approved model, workspace, and retention configuration. Do not place prompts, responses, redaction maps, or secrets in logs, traces, metrics, or exception text.
- Scan the response before restoration or release. Record only aggregate counts, policy decisions, request identifier, and token metadata, then enforce the documented retention and deletion procedure.
- Verify deletion in the sandbox and retain a redacted audit receipt for the owner and compliance reviewer.
Output
Produce a redacted data-handling receipt containing the purpose, policy version, environment, workspace class, redaction and response-scan outcomes, request identifier, token counts, retention deadline, deletion result, and reviewer. Exclude names, contact details, prompt/response text, raw identifiers, redaction maps, and credentials.
Examples
For a synthetic fixture such as customer_id=fixture-017; email=test@example.invalid; purpose=classification, redact the email, call a sandbox workspace, assert raw_pii_sent=0 and sensitive_content_logged=0, and emit redaction=pass; output_scan=pass; retention=24h; deletion=verified. Never substitute a real person or production record in this example.
Resources
Next Steps
For enterprise access control, see anth-enterprise-rbac.
1---2name: anth-data-handling3description: Implement data privacy, PII handling, and compliance patterns for Claude API. Use when handling sensitive data, implementing PII redaction, or configuring data retention for GDPR/CCPA compliance with Claude. Trigger with phrases like "anthropic data privacy", "claude PII", "anthropic gdpr", "claude data handling", "redact data claude".4license: MIT5---6# Anthropic Data Handling
7
8## Overview
9
10Anthropic's data policies: API inputs/outputs are NOT used for model training (commercial API). Zero-day retention is available. This skill covers PII redaction before sending to Claude and compliance patterns.
11
12## Anthropic Data Policies
13
14| Policy | Details |
15|--------|---------|
16| Training data | API data is NOT used for training (commercial API) |
17| Data retention | 30-day default; 0-day available via agreement |
18| Encryption | TLS 1.2+ in transit, AES-256 at rest |
19| SOC 2 Type II | Certified |
20| HIPAA BAA | Available for eligible customers |
21
22## PII Redaction Before API Calls
23
24```python
25import re
26import anthropic
27
28def redact_pii(text: str) -> tuple[str, dict]:
29 """Redact PII before sending to Claude, return redaction map for restoration."""
30 redaction_map = {}
31 patterns = [
32 (r'\b\d{3}-\d{2}-\d{4}\b', 'SSN', '[SSN-REDACTED-{}]'),
33 (r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', 'EMAIL', '[EMAIL-REDACTED-{}]'),
34 (r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b', 'PHONE', '[PHONE-REDACTED-{}]'),
35 (r'\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b', 'CARD', '[CARD-REDACTED-{}]'),
36 ]
37
38 counter = 0
39 for pattern, label, replacement in patterns:
40 for match in re.finditer(pattern, text):
41 counter += 1
42 placeholder = replacement.format(counter)
43 redaction_map[placeholder] = match.group()
44 text = text.replace(match.group(), placeholder, 1)
45
46 return text, redaction_map
47
48def restore_pii(text: str, redaction_map: dict) -> str:
49 """Restore redacted PII in Claude's response."""
50 for placeholder, original in redaction_map.items():
51 text = text.replace(placeholder, original)
52 return text
53
54# Usage
55user_input = "Contact John at john@example.com or 555-123-4567"
56safe_input, redactions = redact_pii(user_input)
57# safe_input: "Contact John at [EMAIL-REDACTED-1] or [PHONE-REDACTED-2]"
58
59client = anthropic.Anthropic()
60msg = client.messages.create(
61 model="claude-sonnet-4-20250514",
62 max_tokens=256,
63 messages=[{"role": "user", "content": safe_input}]
64)
65final_output = restore_pii(msg.content[0].text, redactions)
66```
67
68## Audit Logging
69
70```python
71import json
72import logging
73from datetime import datetime, timezone
74
75audit_logger = logging.getLogger("claude.audit")
76
77def audited_request(client, user_id: str, purpose: str, **kwargs):
78 """Wrap Claude API calls with audit logging."""
79 # Log request metadata (never log content)
80 audit_logger.info(json.dumps({
81 "event": "claude.request",
82 "timestamp": datetime.now(timezone.utc).isoformat(),
83 "user_id": user_id,
84 "purpose": purpose,
85 "model": kwargs.get("model"),
86 "max_tokens": kwargs.get("max_tokens"),
87 }))
88
89 response = client.messages.create(**kwargs)
90
91 audit_logger.info(json.dumps({
92 "event": "claude.response",
93 "request_id": response._request_id,
94 "input_tokens": response.usage.input_tokens,
95 "output_tokens": response.usage.output_tokens,
96 "stop_reason": response.stop_reason,
97 }))
98
99 return response
100```
101
102## Data Handling Checklist
103
104- [ ] PII redacted before sending to Claude API
105- [ ] Audit logs capture who accessed what and when
106- [ ] Logs never contain message content or PII
107- [ ] Data retention policy matches your compliance needs
108- [ ] Zero-day retention enabled if required (contact Anthropic)
109- [ ] HIPAA BAA in place if handling PHI
110- [ ] User consent obtained for AI processing
111- [ ] Data deletion procedures documented
112
113## Error Handling
114
115| Risk | Mitigation |
116|------|------------|
117| PII in prompts | Pre-call redaction pipeline |
118| PII in responses | Post-call output scanning |
119| Audit log gaps | Centralized logging with alerting |
120| Data subject access request | Searchable audit trail by user_id |
121
122## Prerequisites
123
124- Define the data classification, processing purpose, legal basis or user consent, and retention owner before sending anything to the API.
125- Provide an approved redaction policy, a secret-manager-backed API credential, and an allowlisted Anthropic workspace or service boundary.
126- Prepare synthetic fixtures that exercise each PII class and a deletion test; do not use real customer records while validating the pipeline.
127
128## Instructions
129
1301. Classify the input and reject fields outside the approved purpose or destination. Apply deterministic redaction before constructing the request; keep any restoration map encrypted, access-controlled, and short-lived.
1312. Run the redaction, prompt, and response scanners against synthetic fixtures. A failed scan, missing consent, or unexpected content block is a hard stop; do not retry with the original data.
1323. Call the Messages API with the least-privileged credential and only the approved model, workspace, and retention configuration. Do not place prompts, responses, redaction maps, or secrets in logs, traces, metrics, or exception text.
1334. Scan the response before restoration or release. Record only aggregate counts, policy decisions, request identifier, and token metadata, then enforce the documented retention and deletion procedure.
1345. Verify deletion in the sandbox and retain a redacted audit receipt for the owner and compliance reviewer.
135
136## Output
137
138Produce a redacted data-handling receipt containing the purpose, policy version, environment, workspace class, redaction and response-scan outcomes, request identifier, token counts, retention deadline, deletion result, and reviewer. Exclude names, contact details, prompt/response text, raw identifiers, redaction maps, and credentials.
139
140## Examples
141
142For a synthetic fixture such as `customer_id=fixture-017; email=test@example.invalid; purpose=classification`, redact the email, call a sandbox workspace, assert `raw_pii_sent=0` and `sensitive_content_logged=0`, and emit `redaction=pass; output_scan=pass; retention=24h; deletion=verified`. Never substitute a real person or production record in this example.
143
144## Resources
145
146- [Anthropic Privacy Policy](https://www.anthropic.com/privacy)
147- Anthropic Security
148- Usage Policy
149
150## Next Steps
151
152For enterprise access control, see `anth-enterprise-rbac`.