Skip to content

Placeholder Format

Detected entities are replaced with numbered placeholders. Understanding the format is necessary for de-anonymization.

Format

[ENTITY_NAME_N]
  • ENTITY_NAME — the entity type (e.g. PERSON_NAME, EMAIL_ADDRESS, ORGANIZATION)
  • N — a globally incrementing number starting from 1 (or start_index if provided)

Numbering

Placeholders are numbered globally per request, not per entity type.

json
{
  "text": "John (j@co.com) and Jane (jane@co.com) work at Acme."
}

Result:

json
{
  "anonymized_text": "[PERSON_NAME_1] ([EMAIL_ADDRESS_2]) and [PERSON_NAME_3] ([EMAIL_ADDRESS_4]) work at [ORGANIZATION_5]."
}

Custom Start Index

Pass start_index to control where numbering begins, useful for chunked processing:

json
{
  "text": "And Jane works at Google.",
  "start_index": 5
}
json
{
  "anonymized_text": "And [PERSON_NAME_6] works at [ORGANIZATION_7]."
}

De-anonymisation

The map field in every response maps original values to placeholders:

json
{
  "map": {
    "John Doe": "[PERSON_NAME_1]",
    "555-1234": "[PHONE_NUMBER_2]"
  }
}

Reverse the mapping in Python:

python
anonymized = "Call [PERSON_NAME_1] at [PHONE_NUMBER_2]."
de_map = {
    "[PERSON_NAME_1]": "John Doe",
    "[PHONE_NUMBER_2]": "555-1234"
}

original = anonymized
for placeholder, original_text in de_map.items():
    original = original.replace(placeholder, original_text)

Reverse in JavaScript:

javascript
let original = "Call [PERSON_NAME_1] at [PHONE_NUMBER_2].";
const deMap = {
  "[PERSON_NAME_1]": "John Doe",
  "[PHONE_NUMBER_2]": "555-1234"
};

for (const [placeholder, originalText] of Object.entries(deMap)) {
  original = original.replaceAll(placeholder, originalText);
}

Notes

  • Placeholder numbering is not deterministic across requests — the same text may produce different numbers.
  • For file anonymization, the de_anonymization_map in the job response provides the full mapping.

Next: Self-Hosting

Questa AI documentation.