{"openapi":"3.1.0","info":{"title":"PII Guard API","version":"3.1.0","description":"Detect, redact and reversibly anonymize personal data in text.","contact":{"email":"support@efficientstack.com"}},"servers":[{"url":"https://pii.api.efficientstack.com"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}}},"paths":{"/v1/detect":{"post":{"operationId":"detect","summary":"Detect","description":"Locates personal data and returns spans with confidence scores. The document is never modified.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string"},"texts":{"type":"array"},"language":{"type":"string"},"score_threshold":{"type":"number"},"entities":{"type":"array"},"allow_list":{"type":"array"},"mode":{"type":"\"full\""},"include_text":{"type":"boolean"}}},"example":{"text":"Maria Gonzalez paid with card 4111 1111 1111 1111 from 203.0.113.44.","score_threshold":0.4}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"id":"req_9f2c4a71d0e84b12","object":"detection","task":"detect","mode":"full","results":[{"entities":[{"entity_type":"PERSON","start":0,"end":15,"score":0.85,"recognizer":"NerRecognizer"},{"entity_type":"CREDIT_CARD","start":29,"end":48,"score":1,"recognizer":"CreditCardRecognizer"}],"counts":{"PERSON":1,"CREDIT_CARD":1,"IP_ADDRESS":1}}],"summary":{"items":1,"entities":3,"has_pii":true,"counts":{"PERSON":1,"CREDIT_CARD":1,"IP_ADDRESS":1}},"usage":{"requests":1,"items":1,"characters":66,"entities":3,"latency_ms":268,"amount":0.0007,"currency":"USD"}}}}},"402":{"description":"Account limit reached"}}}},"/v1/redact":{"post":{"operationId":"redact","summary":"Redact","description":"Detects and transforms in a single pass. Returns redacted_text per document plus an audit trail of every operator applied.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string"},"texts":{"type":"array"},"language":{"type":"string"},"score_threshold":{"type":"number"},"entities":{"type":"array"},"allow_list":{"type":"array"},"mode":{"type":"\"full\""},"include_text":{"type":"boolean"},"operators":{"type":"object"}}},"example":{"text":"Contact daniel.okafor@acme.io or +44 20 7946 0958.","operators":{"EMAIL_ADDRESS":{"type":"mask","masking_char":"*","chars_to_mask":8,"from_end":false},"DEFAULT":{"type":"replace","new_value":"<REDACTED>"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"id":"req_1a7d55c0b93e4f88","object":"transformation","task":"redact","results":[{"redacted_text":"Contact ********okafor@acme.io or <REDACTED>.","applied":[{"entity_type":"EMAIL_ADDRESS","operator":"mask","start":8,"end":30,"text":"********okafor@acme.io"}],"entities":[]}],"summary":{"items":1,"entities":2,"has_pii":true,"counts":{"EMAIL_ADDRESS":1,"PHONE_NUMBER":1}}}}}},"402":{"description":"Account limit reached"}}}},"/v1/anonymize":{"post":{"operationId":"anonymize","summary":"Anonymize","description":"Same shape as redact, intended for reversible encrypt operators. Your encryption key is used in memory for the request and never stored.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string"},"texts":{"type":"array"},"language":{"type":"string"},"score_threshold":{"type":"number"},"entities":{"type":"array"},"allow_list":{"type":"array"},"mode":{"type":"\"full\""},"include_text":{"type":"boolean"},"operators":{"type":"object"}}},"example":{"text":"SSN 078-05-1120","operators":{"US_SSN":{"type":"encrypt","key":"0123456789abcdef"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true}}}},"402":{"description":"Account limit reached"}}}},"/v1/deanonymize":{"post":{"operationId":"deanonymize","summary":"Deanonymize","description":"Reverses an encrypt anonymization. operators is required and must carry the same key.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string"},"operators":{"type":"object"}}},"example":{}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true}}}},"402":{"description":"Account limit reached"}}}},"/v1/jobs":{"post":{"operationId":"jobs-create","summary":"Create job (async)","description":"Queues a large batch and returns immediately with a job id. Use this for very large batches or when your client cannot hold a long-lived connection.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"task":{"type":"string"},"text":{"type":"string"},"texts":{"type":"array"},"language":{"type":"string"},"score_threshold":{"type":"number"},"entities":{"type":"array"},"allow_list":{"type":"array"},"mode":{"type":"\"full\""},"include_text":{"type":"boolean"}}},"example":{}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"object":"job","id":"e3f1b8a2","status":"queued","task":"detect","items":240,"poll_url":"/v1/jobs/e3f1b8a2"}}}},"402":{"description":"Account limit reached"}}}},"/v1/jobs/{id}":{"get":{"operationId":"jobs-get","summary":"Retrieve job","description":"Polls a queued job. Jobs are scoped to the API key that created them and expire after 24 hours.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true}}}},"402":{"description":"Account limit reached"}}}},"/v1/entities":{"get":{"operationId":"entities","summary":"List entity types","description":"Every entity type the service can detect, per language.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true}}}},"402":{"description":"Account limit reached"}}}},"/v1/info":{"get":{"operationId":"info","summary":"Service info","description":"Languages, entity types, the request limits that apply to your key, and your rate card.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true}}}},"402":{"description":"Account limit reached"}}}},"/v1/health":{"get":{"operationId":"health","summary":"Health","description":"Returns operational, or 503 with degraded. Safe to poll from an uptime monitor.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"ok":true}}}},"402":{"description":"Account limit reached"}}}},"/v1/usage":{"get":{"operationId":"usage","summary":"Usage","description":"Current billing-period counters for the calling key: requests, documents, characters, amount charged and remaining allowances.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"example":{"object":"usage","period":"2026-08","resets_at":1756684800,"totals":{"requests":18420,"items":41003,"characters":9884211,"errors":12,"amount":22.71,"currency":"USD","avg_latency_ms":241},"limits":{"monthly_requests":null,"monthly_items":null,"monthly_amount":500,"max_batch":256,"max_characters_per_request":200000}}}}},"402":{"description":"Account limit reached"}}}}}}