> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orq.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# PII Redaction | Plugins | AI Studio

> Redact personally identifiable information before it reaches the provider, then restore the original values in the response, using the pii_redaction plugin in the AI Gateway.

## Use cases

* Keeping names, emails, and account numbers out of third-party provider logs.
* Meeting data-handling requirements without rewriting prompts in every service.
* Sending sensitive support tickets to a model while preserving the reply for the end user.
* Excluding raw PII from trace storage while still tracing the request end to end.

The `pii_redaction` plugin detects personally identifiable information in the request, replaces each value with a placeholder before the provider sees it, and restores the original values in the response. The provider receives only placeholders such as `<EMAIL_ADDRESS_1>` or `<PERSON_2>`.

<Note>This feature is in Beta.</Note>

<Note>**[Deployments](/docs/ai-studio/ai-engineering/deployments)** do not yet support PII redaction, at the workspace level or per request.</Note>

## Quick start

Add a `pii_redaction` entry to the `plugins` array.

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST https://api.orq.ai/v3/router/responses \
    -H "Authorization: Bearer $ORQ_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "openai/gpt-4o-mini",
      "input": "Email the invoice to jane.doe@example.com",
      "plugins": [{ "id": "pii_redaction", "language": "en" }]
    }'
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import OpenAI from 'openai';

  const client = new OpenAI({
    apiKey: process.env.ORQ_API_KEY,
    baseURL: 'https://api.orq.ai/v3/router',
  });

  const response = await client.responses.create({
    model: 'openai/gpt-4o-mini',
    input: 'Email the invoice to jane.doe@example.com',
    // @ts-ignore - orq.ai extension
    plugins: [{ id: 'pii_redaction', language: 'en' }],
  });

  console.log(response.output_text);
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  from openai import OpenAI
  import os

  client = OpenAI(
      api_key=os.environ.get("ORQ_API_KEY"),
      base_url="https://api.orq.ai/v3/router",
  )

  response = client.responses.create(
      model="openai/gpt-4o-mini",
      input="Email the invoice to jane.doe@example.com",
      extra_body={
          "plugins": [{"id": "pii_redaction", "language": "en"}]
      },
  )

  print(response.output_text)
  ```

  ```typescript TypeScript (Chat Completions) theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import OpenAI from 'openai';

  const client = new OpenAI({
    apiKey: process.env.ORQ_API_KEY,
    baseURL: 'https://api.orq.ai/v3/router',
  });

  const response = await client.chat.completions.create({
    model: 'openai/gpt-4o-mini',
    messages: [
      { role: 'user', content: 'Email the invoice to jane.doe@example.com' },
    ],
    // @ts-ignore - orq.ai extension
    plugins: [{ id: 'pii_redaction', language: 'en' }],
  });
  ```
</CodeGroup>

## Workspace-level redaction

Enable PII redaction for every request from **Organization** > **Plugins**, without passing a `plugins` array on each call. Once enabled, it applies automatically to all **AI Gateway** and **[Agents](/docs/ai-studio/ai-engineering/build-agents)** calls that don't already specify a `pii_redaction` plugin.

<Frame caption="The Plugins settings page showing the PII Redaction toggle, with PDF Inputs and Response Healing listed as coming soon.">
  <img src="https://mintcdn.com/orqai/Gu2Y226JznuIcKkW/images/plugins-411.png?fit=max&auto=format&n=Gu2Y226JznuIcKkW&q=85&s=a4502d9f0a2a89e0a965526704ba414b" alt="Plugins settings page with a PII Redaction card showing an enable toggle, and PDF Inputs and Response Healing cards labeled Coming soon." width="1439" height="502" data-path="images/plugins-411.png" />
</Frame>

A request cannot turn off or reduce the workspace-level redaction settings. It can only add stricter rules of its own, such as lowering the detection threshold to redact more.

## How it works

The plugin runs a redaction round-trip around the generation:

1. **Redact**: detected PII in the request is replaced with typed placeholders before the request leaves the **AI Gateway**.
2. **Generate**: the provider processes the placeholder text and returns a response that keeps the placeholders intact.
3. **Restore**: the original values are substituted back into the response before it returns to the caller.

On `embeddings`, `rerank`, and `images/generations`, the plugin redacts the input only. The `rerank` response restores the echoed document text; `embeddings` and image generation have no echoed text to restore.

## Configuration

| Parameter                    | Type      | Required | Description                                                                                           |
| ---------------------------- | --------- | -------- | ----------------------------------------------------------------------------------------------------- |
| `id`                         | string    | Yes      | Plugin discriminator. Must be `pii_redaction`.                                                        |
| `language`                   | string    | No       | Detector language: `en` or `nl`. Defaults to `en`.                                                    |
| `entities`                   | string\[] | No       | Restricts redaction to a subset of entity types. Omit to redact every type detected for the language. |
| `on_failure`                 | string    | No       | Behavior when redaction is unavailable: `block` or `passthrough`. Defaults to `block`.                |
| `threshold`                  | number    | No       | Detector confidence cutoff in `[0,1]`. Defaults to `0.5`.                                             |
| `persist_redacted_to_traces` | boolean   | No       | Store the redacted form in traces rather than the restored original. Defaults to `true`.              |

### Detection threshold

The `threshold` parameter sets the confidence score at which a detected value is counted as PII. The range is `0` to `1`; the default is `0.5`.

| Value | Behavior                                                              |
| ----- | --------------------------------------------------------------------- |
| `1`   | Very high confidence required: fewer detections, more missed values.  |
| `0`   | Almost no confidence required: more detections, more false positives. |

Scores are boosted for language-specific formats (for example, a Dutch BSN scores higher when the detected or selected language is Dutch). Adjust the threshold only when there is an observed problem: lower it if real PII is being missed, raise it if too many non-PII values are being redacted.

### Restrict to specific entities

Pass `entities` to redact only the listed types. The list is case-insensitive and must match the selected language catalog.

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST https://api.orq.ai/v3/router/responses \
    -H "Authorization: Bearer $ORQ_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "openai/gpt-4o-mini",
      "input": "Contact Jane Doe at jane.doe@example.com",
      "plugins": [{
        "id": "pii_redaction",
        "language": "en",
        "entities": ["EMAIL_ADDRESS"]
      }]
    }'
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import OpenAI from 'openai';

  const client = new OpenAI({
    apiKey: process.env.ORQ_API_KEY,
    baseURL: 'https://api.orq.ai/v3/router',
  });

  const response = await client.responses.create({
    model: 'openai/gpt-4o-mini',
    input: 'Contact Jane Doe at jane.doe@example.com',
    // @ts-ignore - orq.ai extension
    plugins: [
      { id: 'pii_redaction', language: 'en', entities: ['EMAIL_ADDRESS'] },
    ],
  });
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  from openai import OpenAI
  import os

  client = OpenAI(
      api_key=os.environ.get("ORQ_API_KEY"),
      base_url="https://api.orq.ai/v3/router",
  )

  response = client.responses.create(
      model="openai/gpt-4o-mini",
      input="Contact Jane Doe at jane.doe@example.com",
      extra_body={
          "plugins": [{"id": "pii_redaction", "language": "en", "entities": ["EMAIL_ADDRESS"]}]
      },
  )
  ```
</CodeGroup>

## Failure modes

The `on_failure` policy decides what happens when the detection service cannot run:

| Mode          | Behavior                                                                         |
| ------------- | -------------------------------------------------------------------------------- |
| `block`       | Fails closed. The request is rejected and nothing reaches the provider. Default. |
| `passthrough` | Fails open. The original, un-redacted text is sent to the provider.              |

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST https://api.orq.ai/v3/router/responses \
    -H "Authorization: Bearer $ORQ_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "openai/gpt-4o-mini",
      "input": "Email the invoice to jane.doe@example.com",
      "plugins": [{ "id": "pii_redaction", "language": "en", "on_failure": "passthrough" }]
    }'
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import OpenAI from 'openai';

  const client = new OpenAI({
    apiKey: process.env.ORQ_API_KEY,
    baseURL: 'https://api.orq.ai/v3/router',
  });

  const response = await client.responses.create({
    model: 'openai/gpt-4o-mini',
    input: 'Email the invoice to jane.doe@example.com',
    // @ts-ignore - orq.ai extension
    plugins: [{ id: 'pii_redaction', language: 'en', on_failure: 'passthrough' }],
  });
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  from openai import OpenAI
  import os

  client = OpenAI(
      api_key=os.environ.get("ORQ_API_KEY"),
      base_url="https://api.orq.ai/v3/router",
  )

  response = client.responses.create(
      model="openai/gpt-4o-mini",
      input="Email the invoice to jane.doe@example.com",
      extra_body={
          "plugins": [{"id": "pii_redaction", "language": "en", "on_failure": "passthrough"}]
      },
  )
  ```
</CodeGroup>

## Supported languages

The detectable entity catalog differs per language.

<AccordionGroup>
  <Accordion title="English (en)">
    `AGE`, `API_KEY`, `BANK_ROUTING`, `BIC`, `BIOMETRIC_ID`, `BLOOD_TYPE`,
    `BSN`, `CREDIT_CARD`, `CRYPTO`, `DATE_TIME`, `DEVICE_ID`, `EDUCATION_LEVEL`,
    `EMAIL`, `EMAIL_ADDRESS`, `EMPLOYMENT_STATUS`, `GENDER`, `HEALTH_PLAN_ID`,
    `HTTP_COOKIE`, `IBAN_CODE`, `ID`, `ID_CARD`, `IMEI`, `IP_ADDRESS`,
    `JOBTITLE`, `JWT`, `KVK_NUMBER`, `LANGUAGE`, `LICENSE_NUMBER`,
    `LICENSE_PLATE`, `LOCATION`, `MAC_ADDRESS`, `MEDICAL_LICENSE`,
    `MEDICAL_RECORD`, `NRP`, `ORGANIZATION`, `PASSPORT`, `PASSWORD`, `PERSON`,
    `PHONE_NUMBER`, `PIN`, `POLITICAL_VIEW`, `RACE_ETHNICITY`,
    `RELIGIOUS_BELIEF`, `SEXUALITY`, `TAX_ID`, `TITLE`, `UK_NHS`, `URL`,
    `US_BANK_NUMBER`, `US_DRIVER_LICENSE`, `US_ITIN`, `US_PASSPORT`, `US_SSN`,
    `UUID`, `VEHICLE_ID`
  </Accordion>

  <Accordion title="Dutch (nl)">
    `AGE`, `API_KEY`, `BANK_ROUTING`, `BIC`, `BIOMETRIC_ID`, `BLOOD_TYPE`,
    `BSN`, `CREDIT_CARD`, `CRYPTO`, `DATE_TIME`, `DEVICE_ID`, `EDUCATION_LEVEL`,
    `EMAIL`, `EMAIL_ADDRESS`, `EMPLOYMENT_STATUS`, `GENDER`, `HEALTH_PLAN_ID`,
    `HTTP_COOKIE`, `IBAN_CODE`, `ID`, `ID_CARD`, `IMEI`, `IP_ADDRESS`,
    `KVK_NUMBER`, `LANGUAGE`, `LICENSE_NUMBER`, `LICENSE_PLATE`, `LOCATION`,
    `MAC_ADDRESS`, `MEDICAL_RECORD`, `NRP`, `ORGANIZATION`, `PASSPORT`,
    `PASSWORD`, `PERSON`, `PHONE_NUMBER`, `PIN`, `POLITICAL_VIEW`,
    `RACE_ETHNICITY`, `RELIGIOUS_BELIEF`, `SEXUALITY`, `TAX_ID`, `TITLE`, `URL`,
    `US_DRIVER_LICENSE`, `US_SSN`, `VEHICLE_ID`
  </Accordion>
</AccordionGroup>

## Tracing

Redaction is traced in-process as child spans of the request: `pii-redact` for the input pass and `pii-restore` for the output pass. Each span carries the detector `language`, the failure policy, the requested entity count, the placeholder count, and the outcome. `persist_redacted_to_traces` controls whether the redacted (placeholder) form or the restored original is stored in trace content; it defaults to `true` (redacted form stored).
