HTTP service and Docker¶
The CLI is still the main surface. This page is the optional local HTTP wrapper around the same engine: POST /anonymize, POST /deanonymize, POST /verify, POST /report. There is no authentication. Bind to this machine or a compose network.
The HTTP layer is pdf-anonymizer-api. It depends on pdf-anonymizer-core only, not the CLI.
Install and run¶
The HTTP package depends on core only. It does not import the CLI.
--host defaults to 127.0.0.1 so other machines cannot connect. --host 0.0.0.0 is for a container that compose then publishes on localhost.
OpenAPI docs: http://127.0.0.1:8000/docs.
Docker¶
docker compose -f packages/pdf-anonymizer-api/docker-compose.yml up --build
curl http://127.0.0.1:8000/health
Dockerfile, compose, and the optional AppArmor profile live in packages/pdf-anonymizer-api/. Compose sets the build context to the repository root so the image can copy pdf-anonymizer-core as well. The image installs those two packages only (no CLI).
POST /anonymize defaults to use_llm: false (regex-only), so the container works without API keys. Pass use_llm: true and a provider key in the environment if you want the language model.
The AppArmor profile is packages/pdf-anonymizer-api/apparmor/docker-anonymizer. It is not enabled in compose. Load it on the host first, then add security_opt: ["apparmor:docker-anonymizer"]. That is a starting point for untrusted PDFs. It is not a complete sandbox.
Endpoints¶
| Method | Path | What it does |
|---|---|---|
GET |
/health |
{"status": "ok", "version": "<package version>"} |
POST |
/anonymize |
Mask a string. Returns text, mapping, and the entity list. |
POST |
/deanonymize |
Put originals back from a mapping. |
POST |
/verify |
Residual leftover scan. Does not rewrite. |
POST |
/report |
Linkage-risk score. Does not rewrite. |
Bodies are JSON. There is no file-upload path. Send extracted text. Size limit: 5,000,000 characters.
POST /anonymize¶
Default is regex-only (use_llm: false, use_ner: false, min_confidence: 0). That is a service default so Docker works without keys. The CLI run command is unchanged (best-speed still calls a language model unless you pass --no-llm).
curl -s http://127.0.0.1:8000/anonymize \
-H 'content-type: application/json' \
-d '{"text":"Pay DE89370400440532013000 to ada@example.com","use_llm":false}'
Response shape:
{
"anonymized_text": "Pay IBAN_1 to EMAIL_1",
"mapping": {
"DE89370400440532013000": "IBAN_1",
"ada@example.com": "EMAIL_1"
},
"entities": [
{
"text": "DE89370400440532013000",
"type": "IBAN",
"base_form": "DE89370400440532013000",
"score": 0.95,
"source": "regex"
},
{
"text": "ada@example.com",
"type": "EMAIL",
"base_form": "ada@example.com",
"score": 0.85,
"source": "regex"
}
]
}
source is which recognizer proposed the span. score is that recognizer’s 0–1 hint. Neither is a calibrated probability. Full table: Terminology.
Optional body fields: use_llm, use_ner, min_confidence, keep_list, deny_list, operators, seed_mapping, fake_secret, model_name, prompt_name (simple / detailed / hipaa), anonymized_entities, countries.
POST /deanonymize¶
curl -s http://127.0.0.1:8000/deanonymize \
-H 'content-type: application/json' \
-d '{"text":"Pay IBAN_1","mapping":{"DE89370400440532013000":"IBAN_1"}}'
The mapping may be original → stand-in (SDK direction) or stand-in → original (CLI file direction).
POST /verify and POST /report¶
Same reports as pdf-anonymizer verify and pdf-anonymizer report. They do not rewrite the string. verify accepts countries and optional use_llm / model_name.
Out of scope¶
- Authentication, TLS, and multi-tenant isolation. Put a reverse proxy in front if you need those.
- Spark / Ray / DuckDB UDFs.
- Uploading a PDF or Word file. Use the CLI
runcommand for files.