CheckIDs Try the redaction API

Keep personal data out of LLM prompts under the GDPR

Support tickets, CRM notes and emails make great LLM input, and they are full of personal data. A practical guide to sending less of it to the model, with what the GDPR actually says and a working pattern.

This guide explains a technical pattern. It is not legal advice; involve your data protection officer for your own case.

Why it matters

Every prompt you send copies its contents to the model provider, and often into your own logs and monitoring. The GDPR's data minimisation principle in Article 5(1)(c) requires personal data to be

"adequate, relevant and limited to what is necessary in relation to the purposes for which they are processed ('data minimisation')"

For most LLM tasks (summarising a ticket, drafting a reply, classifying a complaint) the model does not need to know the customer's name, account number or national ID number. It needs to know that there is a customer and an account.

Pseudonymisation, not anonymisation

Replacing personal data with placeholders and keeping a map to restore it is pseudonymisation. Article 4(5) defines it as

"the processing of personal data in such a manner that the personal data can no longer be attributed to a specific data subject without the use of additional information, provided that such additional information is kept separately and is subject to technical and organisational measures to ensure that the personal data are not attributed to an identified or identifiable natural person"

Recital 26 is clear that pseudonymised data is still personal data for whoever can re-identify it:

"Personal data which have undergone pseudonymisation, which could be attributed to a natural person by the use of additional information should be considered to be information on an identifiable natural person."

So redacting does not take your processing out of the GDPR. What it does is reduce what you hand to the model provider, and keep the key to re-identification, the placeholder map, on your side.

The pattern: redact, prompt, restore

  1. Replace personal data with placeholders such as [PERSON_1] and [IBAN_1]. Keep the same placeholder for every mention of the same person, so the model can still follow the text.
  2. Send only the redacted text to the model.
  3. Put the real values back into the model's answer, on your side.
"""Redact a support ticket, let an LLM work on it, put the real values back.

    pip install requests
    RAPIDAPI_KEY=... python examples/llm_roundtrip.py
"""
import os

import requests

HOST = "eu-pii-redaction.p.rapidapi.com"
HEADERS = {
    "X-RapidAPI-Key": os.environ["RAPIDAPI_KEY"],
    "X-RapidAPI-Host": HOST,
}


def redact(text: str) -> tuple[str, dict[str, str]]:
    """Return the redacted text and a placeholder -> original value mapping."""
    r = requests.post(f"https://{HOST}/redact", json={"text": text}, headers=HEADERS, timeout=10)
    r.raise_for_status()
    body = r.json()
    originals: dict[str, str] = {}
    for e in body["entities"]:
        # The first mention is the fullest one ("Karina Dahl" before "Karina").
        originals.setdefault(e["placeholder"], text[e["start"]:e["end"]])
    return body["redacted"], originals


def restore(text: str, originals: dict[str, str]) -> str:
    for placeholder, value in originals.items():
        text = text.replace(placeholder, value)
    return text


def ask_llm(prompt: str) -> str:
    # Replace with your LLM client. For the demo, a canned reply that uses the placeholders.
    return ("Hi [PERSON_1], thanks for reaching out. We have refunded your order to [IBAN_1]; "
            "it should arrive within 3 working days.")


ticket = """Hi, my name is Karina Dahl. I was charged twice for order 88412.
Please refund to DK50 0040 0440 1162 43 or call me on +45 32 12 34 56.
Karina"""

redacted, originals = redact(ticket)
print("Sent to the LLM:\n" + redacted + "\n")
reply = ask_llm(f"Draft a short reply to this support ticket:\n\n{redacted}")
print("LLM reply, restored:\n" + restore(reply, originals))

The model sees Hi, my name is [PERSON_1]. … refund to [IBAN_1], and your customer reads a reply with their real name and account. You can try this on your own text without signing up.

What to watch out for

The EU PII Redaction API implements this pattern for European data: names, national ID numbers from 21 EU/EEA countries, IBANs, emails and phones, with one placeholder per person. See the quickstart.