Enterprise-grade PII detection and anonymisation across 10 global compliance frameworks.
Every request requires an API key passed via the X-Api-Key header. When you omit the frameworks field, the API automatically uses all frameworks your plan includes.
curl -X POST https://api.comply-tech.co.uk/api/v1/anonymise \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Contact John Smith at
john.smith@example.com",
"contentType": "text",
"strategy": "Redact"
}'
{
"requestId": "A3F9C2B1",
"processedAt": "2026-02-23T10:00:00Z",
"anonymisedContent": "Contact [NAME REDACTED]
at [EMAIL REDACTED]",
"summary": {
"totalPiiDetected": 2,
"totalReplaced": 2,
"byCategory": { "Name": 1, "Email": 1 },
"byFramework": { "GDPR": 2 },
"bySeverity": { "Medium": 2 },
"averageConfidence": 0.94,
"lowestConfidence": 0.90,
"highestConfidence": 0.98,
"matches": [
{
"category": "Email",
"originalValue": "john.smith@example.com",
"startIndex": 30,
"endIndex": 52,
"confidence": 0.98,
"framework": "GDPR",
"severity": "Medium"
}
]
},
"risk": {
"score": 16,
"level": "Low",
"frameworksAffected": 1,
"categoriesFound": 2
},
"metadata": {
"processingTimeMs": 3,
"engineVersion": "1.1.0",
"patternsEvaluated": 2,
"contentLength": 52,
"contentType": "text",
"fieldsProcessed": 1,
"minConfidenceApplied": 0.0
}
}
| Method | Format | Example |
|---|---|---|
| Header (recommended) | X-Api-Key: {key} | X-Api-Key: ct_live_abc123... |
| Query parameter | ?api_key={key} | ?api_key=ct_live_abc123... |
Every authenticated response includes rate limit and quota information in HTTP headers.
| Header | Example | Description |
|---|---|---|
| X-RateLimit-Limit | 60 | Requests allowed per minute |
| X-RateLimit-Remaining | 55 | Requests remaining in current window |
| X-RateLimit-Reset | 42 | Seconds until window resets |
| X-Quota-Limit | 25000 | Monthly field quota |
| X-Quota-Used | 1234 | Fields processed this month |
| X-Quota-Remaining | 23766 | Fields remaining this month |
| Plan | Monthly Fields | Rate Limit | Frameworks | Price |
|---|---|---|---|---|
| Free | 2,000 | 10 req/min | GDPR | £0 |
| Starter | 25,000 | 60 req/min | GDPR, CCPA | £29/mo |
| Pro | 150,000 | 120 req/min | GDPR, CCPA, HIPAA, PCI-DSS, LGPD, PIPEDA | £99/mo |
| Enterprise | Custom | 300 req/min | All 10 frameworks | £499+/mo |
Usage is measured by the number of fields scanned, not raw request count:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| content | string | Yes | — | Text, JSON string, or CSV. Max 500 KB. |
| contentType | string | No | "text" | "text", "json", or "csv" |
| strategy | string | No | "Redact" | "Redact", "Mask", or "Pseudonymise" |
| frameworks | string[] | No | all for plan | Compliance frameworks to apply |
| targetCategories | string[] | No | all | Restrict to specific PII categories |
| includeReport | bool | No | true | Include detection summary in response |
| minimumConfidence | number | No | 0.0 | Only process matches at or above this confidence (0.0–1.0) |
| allowList | string[] | No | [] | Known-safe values to exclude |
summary is null when includeReport: false. risk and metadata are always included.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| content | string | Yes | — | Content to scan |
| contentType | string | No | "text" | "text", "json", or "csv" |
| frameworks | string[] | No | all for plan | Compliance frameworks to apply |
| minimumConfidence | number | No | 0.0 | Filter out matches below this threshold |
| allowList | string[] | No | [] | Known-safe values to exclude |
| Field | Description |
|---|---|
| plan | Your plan tier (Free, Starter, Pro, Enterprise) |
| monthlyQuota | Total monthly field quota (-1 = unlimited) |
| currentMonthUsage.fieldsProcessed | Fields processed so far this month |
| currentMonthUsage.requests | Number of API requests this month |
| quotaRemaining | Fields remaining (-1 = unlimited) |
| rateLimitPerMinute | Your per-minute request limit |
| periodStart / periodEnd | Current billing period (UTC) |
Use /api/v1/frameworks/{name} to get details for a specific framework. Name is case-insensitive.
Every anonymise/detect request is logged with a SHA-256 content hash for non-repudiation.
| Param | Type | Default | Description |
|---|---|---|---|
| page | int | 1 | Page number |
| pageSize | int | 20 | Items per page (max 100) |
Submit up to 100 anonymise/detect requests in a single call. Returns a job ID immediately (202 Accepted). Poll GET /api/v1/batch/{jobId} for results, or provide a webhookUrl for completion notification.
| Field | Type | Required | Description |
|---|---|---|---|
| items | array | Yes | 1–100 items to process |
| items[].type | string | Yes | "anonymise" or "detect" |
| items[].request | object | Yes | Same schema as the respective endpoint |
| webhookUrl | string | No | HTTPS URL to receive POST on completion |
| Status | Meaning |
|---|---|
| pending | Job queued, not yet started |
| processing | At least one item is being processed |
| completed | All items finished (individual items may have status: "failed") |
| Header | Description |
|---|---|
| X-ComplyTech-Signature | Lowercase-hex HMAC-SHA256 of the raw JSON body. The HMAC key is the uppercase-hex SHA-256 digest of your raw API key (not the raw key itself). |
| X-ComplyTech-Event | Event type (batch.completed) |
import hashlib, hmac
# The signing key is the UPPERCASE hex SHA-256 of your raw API key
key_hash = hashlib.sha256(raw_api_key.encode()).hexdigest().upper()
# Signature is lowercase hex
expected = hmac.new(key_hash.encode(), payload_bytes, hashlib.sha256).hexdigest()
assert hmac.compare_digest(expected, request.headers["X-ComplyTech-Signature"])
{
"status": "healthy",
"product": "ComplyTech PII Anonymisation API",
"version": "1.0.0",
"timestamp": "2026-02-23T10:00:00Z",
"checks": {
"database": "ok"
}
}
status is "healthy" when the database is reachable and "degraded" otherwise (checks.database becomes "unavailable"). The endpoint always returns HTTP 200 regardless, for liveness-probe compatibility. There is no documentation field.
Free-form text. Suitable for log files, emails, support tickets, and notes.
{
"content": "Patient John Doe, DOB 12/05/1980, MRN 00123456",
"contentType": "text",
"frameworks": ["HIPAA"],
"strategy": "Redact"
}
Pass a JSON object as a string. All string values are scanned recursively. The response anonymisedContent is a valid JSON string with PII replaced.
{
"content": "{\"firstName\":\"Alice\",\"email\":\"alice@corp.com\",
\"address\":{\"street\":\"10 Downing St\"}}",
"contentType": "json",
"frameworks": ["GDPR"],
"strategy": "Pseudonymise"
}
CSV with a header row. Each cell is scanned independently; column headers are preserved.
{
"content": "name,email,phone\n
John Smith,john@example.com,07700900123\n
Jane Doe,jane@example.com,07700900456",
"contentType": "csv",
"frameworks": ["GDPR"],
"strategy": "Mask"
}
| Strategy | What it does | Input | Output |
|---|---|---|---|
| Redact | Replaces PII with a clear label | john@example.com | [EMAIL REDACTED] |
| Mask | Partially hides the value | john@example.com | j***@*******.com |
| Pseudonymise | Replaces with realistic fake data | john@example.com | sarah.jones@outlook.com |
ComplyTech supports 10 global compliance frameworks. Access is gated by your plan tier. You can combine multiple frameworks in one request.
| Framework | Region | Plan Required | Key PII Covered |
|---|---|---|---|
| GDPR | European Union | Free+ | Name, Email, Phone, DOB, Address, National ID, IP, Passport, Biometrics, GUIDs, Coordinates, Crypto |
| CCPA | California, USA | Starter+ | Name, Email, SSN, Driver's Licence, IP, DOB, GUIDs, Coordinates, Crypto |
| HIPAA | United States | Pro+ | Name, MRN, DOB, Phone, Email, Device ID, Biometrics, Health Plan IDs, GUIDs, Coordinates |
| PCI-DSS | Global | Pro+ | Credit Card, Bank Account, Sort Code, IBAN, Crypto |
| LGPD | Brazil | Pro+ | Name, Email, Phone, CPF, Address, DOB, IP, Credit Card, Passport, Biometrics |
| PIPEDA | Canada | Pro+ | Name, Email, Phone, SIN, Address, DOB, IP, Credit Card, MRN, Biometrics |
| DPDPA | India | Enterprise | Name, Email, Phone, Aadhaar, Address, DOB, IP, Credit Card, Passport, Biometrics |
| POPIA | South Africa | Enterprise | Name, Email, Phone, SA ID, Address, DOB, IP, Credit Card, Passport, Biometrics |
| PDPA | Singapore / Thailand | Enterprise | Name, Email, Phone, NRIC, Address, DOB, IP, Credit Card, Passport, Coordinates |
| APPI | Japan | Enterprise | Name, Email, Phone, My Number, Address, DOB, IP, Credit Card, Passport, Biometrics |
Context-prefixed dates — with keywords such as DOB:, Date of Birth:, or born — are detected with high confidence (0.92). Standalone dates without context are detected at lower confidence (0.60).
| Format | Example | Confidence |
|---|---|---|
| Slash separator | DOB: 12/03/1985 | 0.92 |
| Dash separator | born 12-03-1985 | 0.92 |
| Dot separator | DOB: 12.03.1985 | 0.92 |
| ISO YYYY-MM-DD | Date of Birth: 1985-03-12 | 0.92 |
| Written month (UK) | born 12 March 1985 | 0.92 |
| Written month (US) | DOB: March 12, 1985 | 0.92 |
| Abbreviated month | DOB: 12 Mar 1985 | 0.92 |
| Ordinal suffixes | born 1st January 1990 | 0.92 |
| Standalone (no context) | 12.03.1985, 1985-03-12 | 0.60 |
Every response includes a risk object that quantifies the compliance exposure of the scanned content.
| Field | Description |
|---|---|
| score | 0–100. Weighted sum: Critical=25pts, High=15pts, Medium=8pts, Low=3pts per match. Capped at 100. |
| level | None (0) • Low (1–25) • Medium (26–50) • High (51–75) • Critical (76–100) |
| bySeverity | Match count per severity tier |
| frameworksAffected | Number of distinct compliance frameworks with findings |
| categoriesFound | Number of distinct PII categories found |
Each PII match includes a severity field based on the category's sensitivity:
| Severity | Categories | Rationale |
|---|---|---|
| Critical | CreditCardNumber, SSN, BankAccountNumber, IBAN, NationalId, Passport, Biometric, Password, ApiKey, CPF, Aadhaar, SIN, SA ID, My Number, NRIC | Direct financial loss or identity theft risk |
| High | MedicalRecordNumber, HealthPlanBeneficiary, DriverLicence, DOB, AccountNumber, SortCode, TaxId, CryptocurrencyAddress | Healthcare / financial / strongly identifying |
| Medium | Name, Email, Phone, Address, IpAddress, DeviceIdentifier, GeoCoordinate | Personally identifying but not directly exploitable |
| Low | Url, Guid | Indirect identifiers |
Every PII match has a confidence score between 0.0 and 1.0. Use minimumConfidence to control the precision/recall tradeoff:
| Threshold | Effect |
|---|---|
| 0.0 (default) | All matches returned — maximum recall, may include false positives |
| 0.7 | Drops low-confidence patterns like standalone dates and 9-digit numbers |
| 0.85 | High-precision mode — only well-established patterns |
| 0.95 | Strictest — only very high confidence matches (email, SSN, credit cards, IPs) |
Exclude known-safe values from detection. Useful for internal data that looks like PII but isn't.
| Format | Example | Effect |
|---|---|---|
| Exact match | "test@example.com" | This specific value is ignored |
| Domain suffix | "@mycompany.com" | Any email ending with this domain is ignored |
| Substring | "192.168." | Any value containing this string is ignored. Substring matching applies only to entries that contain punctuation (dots, dashes, @, slashes, etc.). Entries composed purely of letters, digits, and spaces — e.g. a name like "Ann" or "John Smith" — are matched exactly and will not suppress longer values that merely contain them. This prevents an entry like "Ann" from accidentally suppressing every value containing the substring "ann". |
{
"content": "Contact support@mycompany.com or john@gmail.com",
"strategy": "Redact",
"allowList": ["@mycompany.com"]
}
// Output: "Contact support@mycompany.com or [EMAIL REDACTED]"
Your API key can have a persistent allow list configured via PATCH /admin/keys/{id}.
Use these values in the targetCategories field to restrict detection to specific types.
All errors follow the same shape:
{
"code": "ERROR_CODE",
"message": "Human-readable description.",
"detail": "Optional additional context."
}
| HTTP | Code | Meaning |
|---|---|---|
| 400 | EMPTY_CONTENT | Content field is blank |
| 400 | CONTENT_TOO_LARGE | Content exceeds 500 KB |
| 400 | FRAMEWORK_NOT_AVAILABLE | Requested framework not in your plan tier |
| 400 | NO_FRAMEWORKS | No valid frameworks specified |
| 400 | EMPTY_BATCH | Batch request contains no items |
| 400 | BATCH_TOO_LARGE | Batch exceeds 100 items |
| 400 | INVALID_ITEM_TYPE | Batch item type must be "anonymise" or "detect" |
| 400 | INVALID_WEBHOOK_URL | webhookUrl is not a valid HTTPS URL |
| 401 | MISSING_API_KEY | No API key provided |
| 403 | INVALID_API_KEY | Key does not exist or has been revoked |
| 403 | KEY_EXPIRED | Key has passed its expiry date |
| 404 | JOB_NOT_FOUND | Batch job ID does not exist or belongs to another key |
| 429 | QUOTA_EXCEEDED | Monthly field quota exhausted. Resets 1st of next month. |
| 429 | RATE_LIMIT_EXCEEDED | Too many requests per minute |
| 500 | PROCESSING_ERROR | Unexpected server error — contact support |
curl https://api.comply-tech.co.uk/api/v1/usage \
-H "X-Api-Key: YOUR_API_KEY"
curl -X POST https://api.comply-tech.co.uk/api/v1/detect \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "John Smith, john@email.com, 07700900123",
"contentType": "text",
"frameworks": ["GDPR"]
}'
curl -X POST https://api.comply-tech.co.uk/api/v1/anonymise \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Patient: Jane Doe, DOB: 1980-05-12,
Card: 4111111111111111",
"contentType": "text",
"frameworks": ["HIPAA", "PCI_DSS"],
"strategy": "Redact"
}'
curl -X POST https://api.comply-tech.co.uk/api/v1/anonymise \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Patient born 12 March 1985,
DOB: 1985-03-12,
recorded as 12.03.1985",
"contentType": "text",
"frameworks": ["GDPR"],
"strategy": "Redact"
}'
curl -X POST https://api.comply-tech.co.uk/api/v1/anonymise \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Order 123456789 for John Smith,
email john@corp.com",
"contentType": "text",
"frameworks": ["GDPR"],
"strategy": "Redact",
"minimumConfidence": 0.85
}'
curl -X POST https://api.comply-tech.co.uk/api/v1/anonymise \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "admin@mycompany.com forwarded
john@gmail.com patient data",
"contentType": "text",
"frameworks": ["GDPR"],
"strategy": "Redact",
"allowList": ["@mycompany.com"]
}'
curl -X POST https://api.comply-tech.co.uk/api/v1/batch \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"type": "anonymise",
"request": {
"content": "Email: john@test.com",
"strategy": "Redact"
}
},
{
"type": "detect",
"request": {
"content": "SSN: 123-45-6789",
"frameworks": ["CCPA"]
}
}
],
"webhookUrl": "https://your-server.com/webhooks/complytech"
}'
curl "https://api.comply-tech.co.uk/api/v1/audit?page=1&pageSize=10" \
-H "X-Api-Key: YOUR_API_KEY"
curl https://api.comply-tech.co.uk/api/v1/batch/1 \
-H "X-Api-Key: YOUR_API_KEY"
Content submitted to /anonymise and /detect is processed in memory and never persisted. The audit log stores only a SHA-256 hash of the input plus metadata (request ID, endpoint, content type, match/field counts, timing) — never the raw content or detected values. Application logs never contain raw content or matched PII values.
Batch requests store raw item content transiently while queued and purge it immediately after each item is processed (a sweep also purges any stragglers every 5 minutes); note that anonymised results are retained in the job record so you can poll for them.
No third-party services are called during detection or anonymisation — all processing is in-process (regex + local dictionary + local faker). The only outbound traffic is optional batch webhooks to your URL and nightly encrypted database backups.
Questions? Contact us at contact@comply-tech.co.uk