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

# PII Redaction

export const LanguageTable = ({languages, columns = 3}) => {
  return <div className="grid gap-2" style={{
    gridTemplateColumns: `repeat(${columns}, 1fr)`
  }}>
      {languages.map(language => <div key={language.code} className="flex justify-between items-center">
          <span>{language.name}</span>
          <code className="text-sm bg-gray-100 px-2 py-1 rounded">
            {language.code}
          </code>
        </div>)}
    </div>;
};

export const EndpointCard = ({method = "API", title, children, href, arrow = true}) => {
  const METHOD_STYLES = {
    GET: {
      bg: "mint-bg-green-400/20 dark:mint-bg-green-400/20",
      text: "mint-text-green-700 dark:mint-text-green-400",
      border: "mint-border-green-300 dark:mint-border-green-700"
    },
    POST: {
      bg: "mint-bg-blue-400/20 dark:mint-bg-blue-400/20",
      text: "mint-text-blue-700 dark:mint-text-blue-400"
    },
    PUT: {
      bg: "mint-bg-yellow-400/20 dark:mint-bg-yellow-400/20",
      text: "mint-text-yellow-700 dark:mint-text-yellow-400"
    },
    PATCH: {
      bg: "mint-bg-orange-400/20 dark:mint-bg-orange-400/20",
      text: "mint-text-orange-700 dark:mint-text-orange-400"
    },
    DELETE: {
      bg: "mint-bg-red-400/20 dark:mint-bg-red-400/20",
      text: "mint-text-red-700 dark:mint-text-red-400"
    },
    API: {
      bg: "mint-bg-black",
      text: "mint-text-white"
    }
  };
  const MethodBadge = ({method}) => {
    const style = METHOD_STYLES[method?.toUpperCase()] ?? METHOD_STYLES.GET;
    return <span className={`
          method-pill rounded-lg font-semibold px-1.5 py-0.5 text-xs leading-5 ${style.bg} ${style.text}`}>
        {method?.toUpperCase()}
      </span>;
  };
  const content = <div className="flex items-center gap-4 bg-white dark:bg-background-dark border border-gray-200 dark:border-gray-700 rounded-xl p-5 hover:border-gray-400 dark:hover:border-gray-500 hover:shadow-md transition-all cursor-pointer card block font-normal group relative my-2 ring-2 ring-transparent rounded-2xl bg-white dark:bg-background-dark border border-gray-950/10 dark:border-white/10 overflow-hidden w-full cursor-pointer hover:!border-primary dark:hover:!border-primary-light">
      {}
      <div className="shrink-0">
        <MethodBadge method={method} />
      </div>
      {}
      <div className="flex-1 min-w-0">
        <p className="font-semibold text-gray-900 dark:text-white text-base leading-snug">{title}</p>
        {children && <p className="mt-1 text-sm text-gray-500 dark:text-gray-400 line-clamp-2">{children}</p>}
      </div>
    </div>;
  if (!href) return content;
  return <a href={href} className="block no-underline border-b-0 mb-2">
      {content}
    </a>;
};

<AccordionGroup>
  <Accordion title="Supported languages">
    <LanguageTable
      languages={[
  { name: "Global English", code: "en" },
  { name: "Australian English", code: "en_au" },
  { name: "British English", code: "en_uk" },
  { name: "US English", code: "en_us" },
  { name: "Spanish", code: "es" },
  { name: "French", code: "fr" },
  { name: "German", code: "de" },
  { name: "Italian", code: "it" },
  { name: "Portuguese", code: "pt" },
  { name: "Dutch", code: "nl" },
  { name: "Hindi", code: "hi" },
  { name: "Japanese", code: "ja" },
  { name: "Chinese", code: "zh" },
  { name: "Finnish", code: "fi" },
  { name: "Korean", code: "ko" },
  { name: "Polish", code: "pl" },
  { name: "Russian", code: "ru" },
  { name: "Turkish", code: "tr" },
  { name: "Ukrainian", code: "uk" },
  { name: "Vietnamese", code: "vi" },
  { name: "Afrikaans", code: "af" },
  { name: "Arabic", code: "ar" },
  { name: "Belarusian", code: "be" },
  { name: "Bulgarian", code: "bg" },
  { name: "Burmese", code: "my" },
  { name: "Catalan", code: "ca" },
  { name: "Croatian", code: "hr" },
  { name: "Czech", code: "cs" },
  { name: "Danish", code: "da" },
  { name: "Estonian", code: "et" },
  { name: "Georgian", code: "ka" },
  { name: "Greek", code: "el" },
  { name: "Hebrew", code: "he" },
  { name: "Hungarian", code: "hu" },
  { name: "Icelandic", code: "is" },
  { name: "Indonesian", code: "id" },
  { name: "Khmer", code: "km" },
  { name: "Latvian", code: "lv" },
  { name: "Lithuanian", code: "lt" },
  { name: "Luxembourgish", code: "lb" },
  { name: "Malay", code: "ms" },
  { name: "Norwegian", code: "no" },
  { name: "Persian", code: "fa" },
  { name: "Romanian", code: "ro" },
  { name: "Slovak", code: "sk" },
  { name: "Slovenian", code: "sl" },
  { name: "Swahili", code: "sw" },
  { name: "Swedish", code: "sv" },
  { name: "Tagalog", code: "tl" },
  { name: "Tamil", code: "ta" },
]}
      columns={4}
    />

    <br />
  </Accordion>

  <Accordion title="Supported models">
    <LanguageTable
      languages={[
  { name: "Universal-3 Pro", code: "universal-3-pro" },
  { name: "Universal-2", code: "universal-2" },
]}
      columns={2}
    />

    <br />
  </Accordion>

  <Accordion title="Supported regions">US & EU</Accordion>
</AccordionGroup>

The PII Redaction model lets you minimize sensitive information about individuals by automatically identifying and removing it from your transcript.

Personal Identifiable Information (PII) is any information that can be used to identify a person, such as a name, email address, or phone number. To redact PII from text rather than audio, see [Redact PII from Text Using LLM Gateway](/guides/llm-gateway-pii-redaction).

When you enable the PII Redaction model, your transcript will look like this:

* With `hash` substitution: `Hi, my name is ####!`
* With `entity_name` substitution: `Hi, my name is [PERSON_NAME]!`

You can also [Create redacted audio files](#create-redacted-audio-files) to replace sensitive information in the audio with a beeping sound or silence.

<Warning>
  **Redacted Properties**

  PII only redacts words in the `text` property. Properties from other features
  may still include PII, such as `entities` from [Entity
  Detection](/speech-understanding/entity-detection) or `summary` from
  [Summarization](/speech-understanding/summarization).
</Warning>

## Quickstart

<Tabs groupId="language">
  <Tab language="python" title="Python" default>
    Enable Topic Detection by setting `redact_pii` to `True` in the JSON payload.

    Set `redact_pii_policies` to specify the information you want to redact. For the full list of policies, see [PII policies](#pii-policies).

    Set `redact_pii_sub` to specify the replacement for redacted information.

    ```python {19-21} expandable theme={null}
    import requests
    import time

    base_url = "https://api.assemblyai.com"

    headers = {
        "authorization": "<YOUR_API_KEY>"
    }

    with open("./local_file.mp3", "rb") as f:
        response = requests.post(base_url + "/v2/upload",
                                headers=headers,
                                data=f)

    upload_url = response.json()["upload_url"]

    data = {
        "audio_url": upload_url, # You can also use a URL to an audio or video file on the web
        "speech_models": ["universal-3-pro", "universal-2"],
        "language_detection": True,
        "redact_pii": True,
        "redact_pii_policies": ["person_name", "organization", "occupation"],
        "redact_pii_sub": "hash"
    }

    url = base_url + "/v2/transcript"
    response = requests.post(url, json=data, headers=headers)

    transcript_id = response.json()['id']
    polling_endpoint = base_url + "/v2/transcript/" + transcript_id

    print(f"Transcript ID: {transcript_id}")

    while True:
        transcription_result = requests.get(polling_endpoint, headers=headers).json()

        if transcription_result['status'] == 'completed':
            print(transcription_result['text'])
            break
        elif transcription_result['status'] == 'error':
            raise RuntimeError(f"Transcription failed: {transcription_result['error']}")
        else:
            time.sleep(3)
    ```
  </Tab>

  <Tab language="python-sdk" title="Python SDK">
    Enable PII Redaction on the `TranscriptionConfig` using the `set_redact_pii()`
    method.

    Set `policies` to specify the information you want to redact. For the full list of policies, see [PII policies](#pii-policies).

    ```python {8-15} expandable theme={null}
    import assemblyai as aai

    aai.settings.api_key = "<YOUR_API_KEY>"

    # audio_file = "./local_file.mp3"
    audio_file = "https://assembly.ai/wildfires.mp3"

    config = aai.TranscriptionConfig(
        speech_models=["universal-3-pro", "universal-2"],
        language_detection=True,
    ).set_redact_pii(
        policies=[
            aai.PIIRedactionPolicy.person_name,
            aai.PIIRedactionPolicy.organization,
            aai.PIIRedactionPolicy.occupation,
        ],
        substitution=aai.PIISubstitutionPolicy.hash,
    )

    transcript = aai.Transcriber().transcribe(audio_file, config)
    print(f"Transcript ID: {transcript.id}")

    print(transcript.text)
    ```
  </Tab>

  <Tab language="javascript" title="JavaScript">
    Enable Topic Detection by setting `redact_pii` to `true` in the JSON payload.

    Set `redact_pii_policies` to specify the information you want to redact. For the full list of policies, see [PII policies](#pii-policies).

    Set `redact_pii_sub` to specify the replacement for redacted information.

    ```javascript {19-21} expandable theme={null}
    import fs from "fs-extra";

    const baseUrl = "https://api.assemblyai.com";

    const headers = {
      authorization: "<YOUR_API_KEY>",
    };

    const path = "./my-audio.mp3";
    const audioData = await fs.readFile(path);
    let res = await fetch(`${baseUrl}/v2/upload`, {
      method: "POST",
      headers,
      body: audioData,
    });
    if (!res.ok) throw new Error(`Error: ${res.status}`);
    const uploadResponse = await res.json();
    const uploadUrl = uploadResponse.upload_url;

    const data = {
      audio_url: uploadUrl, // You can also use a URL to an audio or video file on the web
      speech_models: ["universal-3-pro", "universal-2"],
      language_detection: true,
      redact_pii: true,
      redact_pii_policies: ["person_name", "organization", "occupation"],
      redact_pii_sub: "hash",
    };

    const url = `${baseUrl}/v2/transcript`;
    res = await fetch(url, {
      method: "POST",
      headers: { ...headers, "Content-Type": "application/json" },
      body: JSON.stringify(data),
    });
    if (!res.ok) throw new Error(`Error: ${res.status}`);
    const response = await res.json();

    const transcriptId = response.id;
    console.log("Transcript ID: ", transcriptId);

    const pollingEndpoint = `${baseUrl}/v2/transcript/${transcriptId}`;

    while (true) {
      res = await fetch(pollingEndpoint, { headers });
      if (!res.ok) throw new Error(`Error: ${res.status}`);
      const transcriptionResult = await res.json();

      if (transcriptionResult.status === "completed") {
        console.log(transcriptionResult.text);
        break;
      } else if (transcriptionResult.status === "error") {
        throw new Error(`Transcription failed: ${transcriptionResult.error}`);
      } else {
        await new Promise((resolve) => setTimeout(resolve, 3000));
      }
    }
    ```
  </Tab>

  <Tab language="javascript-sdk" title="JavaScript SDK">
    Enable PII Redaction by setting `redact_pii` to `true` in the transcription
    config.

    Use `redact_pii_policies` to specify the information you want to
    redact. For the full list of policies, see [PII policies](#pii-policies).

    ```javascript {12-14} expandable theme={null}
    import { AssemblyAI } from "assemblyai";

    const client = new AssemblyAI({
      apiKey: "<YOUR_API_KEY>",
    });

    // const audioFile = './local_file.mp3'
    const audioFile = "https://assembly.ai/wildfires.mp3";

    const params = {
      audio: audioFile,
      speech_models: ["universal-3-pro", "universal-2"],
      language_detection: true,
      redact_pii: true,
      redact_pii_policies: ["person_name", "organization", "occupation"],
      redact_pii_sub: "hash",
    };

    const run = async () => {
      const transcript = await client.transcripts.transcribe(params);

      console.log(transcript.text);
    };

    run();
    ```
  </Tab>
</Tabs>

### Example output

```plain theme={null}
Smoke from hundreds of wildfires in Canada is triggering air quality alerts
throughout the US. Skylines from Maine to Maryland to Minnesota are gray and
smoggy. And in some places, the air quality warnings include the warning to stay
inside. We wanted to better understand what's happening here and why, so we
called ##### #######, an ######### ######### in the ########## ## #############
###### ### ########### at ##### ####### ##########. Good morning, #########.
Good morning. So what is it about the conditions right now that have caused this
round of wildfires to affect so many people so far away? Well, there's a couple
of things. The season has been pretty dry already, and then the fact that we're
getting hit in the US. Is because there's a couple of weather systems that ...
```

<Tip>
  **PII Redaction Using LLM Gateway**

  If you would like the option to use LLM Gateway for custom PII redaction,
  check out this guide [Redact PII from Text Using LLM
  Gateway](/guides/llm-gateway-pii-redaction).
</Tip>

## Create redacted audio files

In addition to redacting sensitive information from the transcription text, you can also generate a version of the original audio file with the PII "beeped" out. You can optionally use silence instead of a beep by setting `override_audio_redaction_method` to `"silence"` within `redact_pii_audio_options`.

<Tip>
  **Redacted Audio Endpoint**

  Retrieve the redacted audio file using the `transcript_id` for a transcript where `redact_pii_audio` was enabled during submission:

  <EndpointCard title="Get redacted audio" href="/api-reference/transcripts/get-redacted-audio" method="GET">
    View the endpoint reference.
  </EndpointCard>

  Redacted audio files are only available for 24 hours. Make sure to download the file within this time frame.
</Tip>

<Tabs groupId="language">
  <Tab value="python" title="Python" default>
    To create a redacted version of the audio file, set `redact_pii_audio` to `True` on the JSON payload.
    Set `redact_pii_audio_quality` to specify the quality of the redacted audio file.

    Use the transcript ID to poll the [GET redacted audio endpoint](/api-reference/transcripts/get-redacted-audio) every few seconds to check the status of the redacted audio. Once the status is `redacted_audio_ready`, you can retrieve the audio URL from the API response.

    ```python {6-10,14-25} expandable theme={null}
    data = {
        "audio_url": upload_url, # You can also use a URL to an audio or video file on the web
        "redact_pii": True,
        "redact_pii_policies": ["person_name", "organization", "occupation"],
        "redact_pii_sub": "hash",
        "redact_pii_audio": True,
        "redact_pii_audio_quality": "wav", # Optional. Defaults to "mp3"
        "redact_pii_audio_options": {
            "override_audio_redaction_method": "silence" # Optional. Omit for default (beep)
        }
    }

    # ...
    redacted_audio_polling_endpoint = base_url + "/v2/transcript/" + transcript_id + "/redacted-audio"

    while True:
        redacted_audio_result = requests.get(redacted_audio_polling_endpoint, headers=headers).json()

        if redacted_audio_result['status'] == 'redacted_audio_ready':
            print(redacted_audio_result['redacted_audio_url'])
            break
        elif redacted_audio_result['status'] == 'error':
            raise RuntimeError(f"Transcription failed: {redacted_audio_result['error']}")
        else:
            time.sleep(3)
    ```
  </Tab>

  <Tab value="python-sdk" title="Python SDK">
    To create a redacted version of the audio file, use the `set_redact_pii()` method on the `TranscriptionConfig` with `redact_audio` to `True`.

    Use `get_redacted_audio_url()` on the transcript to get the URL to the redacted audio file.

    ```python {7-8,13} theme={null}
    config = aai.TranscriptionConfig().set_redact_pii(
        policies=[
            aai.PIIRedactionPolicy.person_name,
            aai.PIIRedactionPolicy.organization,
            aai.PIIRedactionPolicy.occupation,
        ],
        redact_audio=True,
        redact_audio_options={"override_audio_redaction_method": "silence"}  # Optional. Omit for default (beep)
    )

    transcript = aai.Transcriber().transcribe(audio_url, config)

    print(transcript.get_redacted_audio_url())
    ```
  </Tab>

  <Tab value="javascript" title="JavaScript" default>
    To create a redacted version of the audio file, set `redact_pii_audio` to `true` on the JSON payload.
    Set `redact_pii_audio_quality` to specify the quality of the redacted audio file.

    Use the transcript ID to poll the [GET redacted audio endpoint](/api-reference/transcripts/get-redacted-audio) every few seconds to check the status of the redacted audio. Once the status is `redacted_audio_ready`, you can retrieve the audio URL from the API response.

    ```javascript {6-10,14,17-29} expandable theme={null}
    const data = {
      audio_url: uploadUrl, // You can also use a URL to an audio or video file on the web
      redact_pii: true,
      redact_pii_policies: ["person_name", "organization", "occupation"],
      redact_pii_sub: "hash",
      redact_pii_audio: true,
      redact_pii_audio_quality: "wav", // Optional. Defaults to "mp3"
      redact_pii_audio_options: {
        override_audio_redaction_method: "silence", // Optional. Omit for default (beep)
      },
    };

    // ...
    const redactedAudioPollingEndpoint = `${baseUrl}/v2/transcript/${transcriptId}/redacted-audio`;

    while (true) {
      let res = await fetch(redactedAudioPollingEndpoint, { headers });
      if (!res.ok) throw new Error(`Error: ${res.status}`);
      const redactedAudioResult = await res.json();

      if (redactedAudioResult.status === "redacted_audio_ready") {
        console.log(redactedAudioResult.redacted_audio_url);
        break;
      } else if (redactedAudioResult.status === "error") {
        throw new Error(`Transcription failed: ${redactedAudioResult.error}`);
      } else {
        await new Promise((resolve) => setTimeout(resolve, 3000));
      }
    }
    ```
  </Tab>

  <Tab language="javascript-sdk" title="JavaScript SDK">
    To create a redacted version of the audio file, set `redact_pii_audio` to
    `true` in the transcription config. Use `redact_pii_audio_quality` to specify
    the quality of the redacted audio file.

    Use redactedAudio() on the transcript to get the URL to the redacted audio file.

    ```javascript {5-9, 15-17} expandable theme={null}
    const params = {
      audio: audioFile,
      redact_pii: true,
      redact_pii_policies: ["person_name", "organization", "occupation"],
      redact_pii_audio: true,
      redact_pii_audio_quality: "wav", // Optional. Defaults to "mp3"
      redact_pii_audio_options: {
        override_audio_redaction_method: "silence", // Optional. Omit for default (beep)
      },
    };

    const run = async () => {
      const transcript = await client.transcripts.transcribe(params);

      const { status, redacted_audio_url } = await client.transcripts.redactedAudio(
        transcript.id
      );

      console.log(`Status: ${status}, Redacted audio URL: ${redacted_audio_url}`);
    };

    run();
    ```

    You can also retrieve the redacted audio file itself using `redactedAudioFile()`.
    The following code writes the redacted audio file to a local file, using `writeFile()` from Node.js.

    ```javascript theme={null}
    import fs from "fs/promises";

    ...

    const audioFile = await client.transcripts.redactedAudioFile(transcript.id);
    await fs.writeFile('./redacted-audio.wav', audioFile.body, 'binary');
    ```
  </Tab>
</Tabs>

<Warning>
  **Maximum Audio File Size**

  You can only create redacted versions of audio files if the original file is
  smaller than 1 GB. For files over 1 GB, see the [Downsampling guide](/pre-recorded-audio/guides/downsampling) to reduce file size before redaction.
</Warning>

<Info>
  **Redacted Audio for Silent Files**

  By default, audio redaction provides redacted audio URLs only when speech is detected. However, if your use-case specifically requires redacted audio files even for silent audio files without any dialogue, you can now opt to receive these URLs. Enable this by setting the optional parameter `"return_redacted_no_speech_audio": true` within `redact_pii_audio_options` in your `POST` request body.

  <Accordion title="Example request body">
    ```json theme={null}
    {
        "audio_url": "YOUR_AUDIO_URL",
        "redact_pii": true,
        "redact_pii_audio": true,
        "redact_pii_audio_options": {
              "return_redacted_no_speech_audio": true
         },
         "redact_pii_policies": ["credit_card_number"]
    }
    ```
  </Accordion>
</Info>

### Example output

```plain theme={null}
https://s3.us-west-2.amazonaws.com/api.assembly.ai.usw2/redacted-audio/ac06721c-d1ea-41a7-95f7-a9463421e6b1.mp3?AWSAccessKeyId=...
```

## Return the unredacted transcript

If your workflow needs both the redacted and unredacted transcripts, you can request both in a single transcription call by setting `redact_pii_return_unredacted` to `true`. This avoids the need to send a second API request without redaction.

<Warning>
  **This is an opt-in convenience feature**

  Enabling PII Redaction by itself does **not** return the unredacted transcript — the default behavior is to redact `text`, `words`, and `utterances` and return only the redacted versions. The unredacted transcript is only returned when you explicitly set `redact_pii_return_unredacted` to `true`, and `redact_pii` must also be `true` (otherwise the request is rejected with a 400).

  Only use this feature if your workflow specifically requires access to both the redacted and unredacted transcripts from the same request. If you only need the redacted transcript, leave this parameter off. When `redact_pii_return_unredacted` is `false` or omitted, the three `unredacted_*` fields are not included in the response at all.
</Warning>

When `redact_pii_return_unredacted` is `true`, the response includes three additional fields alongside their redacted counterparts:

| Field                   | Type               | Description                                                                  |
| ----------------------- | ------------------ | ---------------------------------------------------------------------------- |
| `unredacted_text`       | string             | The original transcript text before PII redaction was applied.               |
| `unredacted_words`      | array of Word      | The original word objects before redaction. Same shape as `words`.           |
| `unredacted_utterances` | array of Utterance | The original utterance objects before redaction. Same shape as `utterances`. |

<Tabs groupId="language">
  <Tab value="python" title="Python" default>
    Set `redact_pii_return_unredacted` to `True` alongside the existing PII parameters. The completed transcript will include `unredacted_text`, `unredacted_words`, and `unredacted_utterances` in addition to the redacted versions.

    ```python {6} theme={null}
    data = {
        "audio_url": upload_url, # You can also use a URL to an audio or video file on the web
        "redact_pii": True,
        "redact_pii_policies": ["person_name", "phone_number", "email_address"],
        "redact_pii_sub": "entity_name",
        "redact_pii_return_unredacted": True
    }

    # ...
    # After polling completes:
    print("Redacted:  ", transcription_result["text"])
    print("Original:  ", transcription_result["unredacted_text"])
    ```
  </Tab>

  <Tab value="python-sdk" title="Python SDK">
    Pass `return_unredacted=True` to `set_redact_pii()`. The transcript object will include `unredacted_text`, `unredacted_words`, and `unredacted_utterances`.

    ```python {11} theme={null}
    config = aai.TranscriptionConfig(
        speech_models=["universal-3-pro", "universal-2"],
        language_detection=True,
    ).set_redact_pii(
        policies=[
            aai.PIIRedactionPolicy.person_name,
            aai.PIIRedactionPolicy.phone_number,
            aai.PIIRedactionPolicy.email_address,
        ],
        substitution=aai.PIISubstitutionPolicy.entity_name,
        return_unredacted=True,
    )

    transcript = aai.Transcriber().transcribe(audio_file, config)

    print("Redacted:  ", transcript.text)
    print("Original:  ", transcript.unredacted_text)
    ```
  </Tab>

  <Tab value="javascript" title="JavaScript">
    Set `redact_pii_return_unredacted` to `true` alongside the existing PII parameters. The completed transcript will include `unredacted_text`, `unredacted_words`, and `unredacted_utterances` in addition to the redacted versions.

    ```javascript {6} theme={null}
    const data = {
      audio_url: uploadUrl, // You can also use a URL to an audio or video file on the web
      redact_pii: true,
      redact_pii_policies: ["person_name", "phone_number", "email_address"],
      redact_pii_sub: "entity_name",
      redact_pii_return_unredacted: true,
    };

    // ...
    // After polling completes:
    console.log("Redacted:  ", transcriptionResult.text);
    console.log("Original:  ", transcriptionResult.unredacted_text);
    ```
  </Tab>

  <Tab value="javascript-sdk" title="JavaScript SDK">
    Set `redact_pii_return_unredacted` to `true` in the transcription config. The transcript object will include `unredacted_text`, `unredacted_words`, and `unredacted_utterances`.

    ```javascript {8} theme={null}
    const params = {
      audio: audioFile,
      speech_models: ["universal-3-pro", "universal-2"],
      language_detection: true,
      redact_pii: true,
      redact_pii_policies: ["person_name", "phone_number", "email_address"],
      redact_pii_sub: "entity_name",
      redact_pii_return_unredacted: true,
    };

    const run = async () => {
      const transcript = await client.transcripts.transcribe(params);

      console.log("Redacted:  ", transcript.text);
      console.log("Original:  ", transcript.unredacted_text);
    };

    run();
    ```
  </Tab>
</Tabs>

### Example response

```json theme={null}
{
  "text": "[PERSON_NAME] called from [PHONE_NUMBER]...",
  "words": [{ "text": "[PERSON_NAME]", "start": 250, "end": 650, "confidence": 0.98 }],
  "utterances": [{ "text": "[PERSON_NAME] called from [PHONE_NUMBER]...", "start": 250, "end": 4820, "speaker": "A" }],
  "redact_pii_return_unredacted": true,
  "unredacted_text": "Mary called from 555-0123...",
  "unredacted_words": [{ "text": "Mary", "start": 250, "end": 650, "confidence": 0.98 }],
  "unredacted_utterances": [{ "text": "Mary called from 555-0123...", "start": 250, "end": 4820, "speaker": "A" }]
}
```

## Static Entity Redaction

PII Redaction detects broad categories of sensitive information (names, phone numbers, and the other [PII policies](#pii-policies)) using an AI model. **Static Entity Redaction** complements this for cases where you need to redact specific, predefined terms that may not fit into general PII categories — for example a proprietary product name, an internal project codename, or an org-specific identifier.

You supply a map of `redact_static_entities`, where each key is a label and each value is a list of **exact terms** to redact. Any matching term in the transcript is replaced with that label, on top of the standard PII redaction.

<Warning>
  Static Entity Redaction matches the exact terms you provide (tolerant of casing, surrounding punctuation, and minor spacing/hyphenation variation from the transcription), rather than inferring a category. For example, listing `["Bearclaw"]` redacts `Bearclaw`, `bearclaw`, `Bearclaw's`, `Bear-claw`, and `Bear claw` — but a different internal tool name you didn't list is not redacted. You define and manage the term list.

  `redact_static_entities` requires `redact_pii` to be `true`. It runs as the final step of redaction, after the standard PII pass.
</Warning>

The substitution follows your existing `redact_pii_sub` setting:

* `entity_name` — the matched term is replaced with `[LABEL]` (the uppercased map key).
* `hash` — the matched term's characters are replaced with `#`.

When [redacted audio](#create-redacted-audio-files) is enabled (`redact_pii_audio: true`), the matched terms are also bleeped from the audio output alongside standard PII.

<Tabs groupId="language">
  <Tab value="python" title="Python" default>
    Pass `redact_static_entities` alongside your existing PII parameters. Each key is the redaction label; each value is the list of terms to match.

    ```python {6-9} theme={null}
    data = {
        "audio_url": upload_url, # You can also use a URL to an audio or video file on the web
        "redact_pii": True,
        "redact_pii_policies": ["person_name", "phone_number"],
        "redact_pii_sub": "entity_name",
        "redact_static_entities": {
            "INTERNAL_TOOL": ["Bearclaw", "Cubclaw"],
            "PROJECT": ["Universal-3 Pro"]
        }
    }
    ```
  </Tab>

  <Tab value="javascript" title="JavaScript">
    Pass `redact_static_entities` alongside your existing PII parameters. Each key is the redaction label; each value is the list of terms to match.

    ```javascript {6-9} theme={null}
    const data = {
      audio_url: uploadUrl, // You can also use a URL to an audio or video file on the web
      redact_pii: true,
      redact_pii_policies: ["person_name", "phone_number"],
      redact_pii_sub: "entity_name",
      redact_static_entities: {
        INTERNAL_TOOL: ["Bearclaw", "Cubclaw"],
        PROJECT: ["Universal-3 Pro"],
      },
    };
    ```
  </Tab>
</Tabs>

### Example response

Matched terms appear redacted inline in `text`, `words`, and `utterances`, exactly like standard PII. There are no additional response fields. For the transcript *"Our internal tool Bearclaw is powered by Universal-3 Pro."* with the request above:

```json theme={null}
{
  "text": "Our internal tool [INTERNAL_TOOL] is powered by [PROJECT].",
  "words": [{ "text": "[INTERNAL_TOOL]", "start": 820, "end": 1180, "confidence": 0.98 }],
  "utterances": [{ "text": "Our internal tool [INTERNAL_TOOL] is powered by [PROJECT].", "start": 250, "end": 3120, "speaker": "A" }]
}
```

## API reference

### Request

```bash {6-13} theme={null}
curl https://api.assemblyai.com/v2/transcript \
--header "Authorization: <YOUR_API_KEY>" \
--header "Content-Type: application/json" \
--data '{
  "audio_url": "YOUR_AUDIO_URL",
  "redact_pii": true,
  "redact_pii_policies": ["us_social_security_number", "credit_card_number"],
  "redact_pii_sub": "hash",
  "redact_pii_audio": true,
  "redact_pii_audio_quality": "mp3",
  "redact_pii_audio_options": {
    "override_audio_redaction_method": "silence"
  }
}'
```

| Key                                                        | Type    | Description                                                                                                                                                                                                                       |
| ---------------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `redact_pii`                                               | boolean | Enable PII Redaction.                                                                                                                                                                                                             |
| `redact_pii_policies`                                      | array   | [PII policies](#pii-policies) for what information to redact.                                                                                                                                                                     |
| `redact_pii_sub`                                           | string  | Method used to substitute PII in the transcript. Can be `entity_name` or `hash`.                                                                                                                                                  |
| `redact_pii_audio`                                         | boolean | Create a [redacted version of the audio file](#create-redacted-audio-files).                                                                                                                                                      |
| `redact_pii_audio_quality`                                 | string  | Quality of the redacted PII audio file. Can be `mp3` or `wav`.                                                                                                                                                                    |
| `redact_pii_audio_options`                                 | object  | Options for PII-redacted audio. See [Create redacted audio files](#create-redacted-audio-files).                                                                                                                                  |
| `redact_pii_audio_options.override_audio_redaction_method` | string  | The method used to redact audio. Set to `silence` to replace PII with silence instead of the default beep.                                                                                                                        |
| `redact_pii_return_unredacted`                             | boolean | Opt-in. When `true`, [returns the unredacted transcript](#return-the-unredacted-transcript) alongside the redacted one. Requires `redact_pii: true`. Defaults to `false`, in which case only the redacted transcript is returned. |
| `redact_static_entities`                                   | object  | A map of `{ "LABEL": ["term", ...] }` for [Static Entity Redaction](#static-entity-redaction). Each listed term is redacted (using `redact_pii_sub`) wherever it appears, on top of standard PII. Requires `redact_pii: true`.    |

### Response

```js theme={null}
{
  text: "Smoke from hundreds of wildfires in Canada is triggering air quality alerts throughout the US. Skylines from Maine to Maryland to Minnesota are gray and smoggy. And in some places, the air quality warnings include the warning to stay inside. We wanted to better understand what's happening here and why, so we called ##### #######, an ######### ######### in the ########## ## ############# ###### ### ########### at ##### ####### ##########. Good morning, #########. Good morning. So what is it about the conditions right now that have caused this round of wildfires to affect so many people so far away? Well, there's a couple of things. The season has been pretty dry already, and then the fact that we're getting hit in the US. Is because there's a couple of weather systems that are essentially channeling the smoke from those Canadian wildfires through Pennsylvania into the Mid Atlantic and the Northeast and kind of just dropping the smoke there. So what is it in this haze that makes it harmful? And I'm assuming it is is it is the levels outside right now in Baltimore are considered unhealthy. And most of that is due to what's called particulate matter, which are tiny particles, microscopic smaller than the width of your hair, that can get into your lungs and impact your respiratory system, your cardiovascular system, and even your neurological your brain. What makes this particularly harmful? Is it the volume of particulate? Is it something in particular? What is it exactly? Can you just drill down on that a little bit more? Yeah. So the concentration of particulate matter I was looking at some of the monitors that we have was reaching levels of what are, in ####### speak, 150 micrograms per meter cubed, which is more than ten times what the annual average should be, and about four times higher than what you're supposed to have on a 24 hours average. And so the concentrations of these particles in the air are just much, much higher than we typically see. And exposure to those high levels can lead to a host of health problems. And who is most vulnerable? I noticed that in New York City, for example, they're canceling outdoor activities, and so here it is in the early days of summer, and they have to keep all the kids inside. So who tends to be vulnerable in a situation like this? It's the youngest. So children, obviously, whose bodies are still developing. The elderly who know their bodies are more in decline, and they're more susceptible to the health impacts of breathing, the poor air quality. And then people who have preexisting health conditions, people with respiratory conditions or heart conditions can be triggered by high levels of air pollution. Could this get worse? That's a good in some areas, it's much worse than others. And it just depends on kind of where the smoke is concentrated. I think New York has some of the higher concentrations right now, but that's going to change as that air moves away from the New York area. But over the course of the next few days, we will see different areas being hit at different times with the highest concentrations. I was going to ask you, more fires start burning, I don't expect the concentrations to go up too much higher. I was going to ask you and you started to answer this, but how much longer could this last? Or forgive me if I'm asking you to speculate, but what do you think? Well, I think the fires are going to burn for a little bit longer, but the key for us in the US. Is the weather system changing. And so right now, it's kind of the weather systems that are pulling that air into our mid Atlantic and Northeast region. As those weather systems change and shift, we'll see that smoke going elsewhere and not impact us in this region as much. And so I think that's going to be the defining factor. And I think the next couple of days we're going to see a shift in that weather pattern and start to push the smoke away from where we are. And finally, with the impacts of climate change, we are seeing more wildfires. Will we be seeing more of these kinds of wide ranging air quality consequences or circumstances? I mean, that is one of the predictions for climate change. Looking into the future, the fire season is starting earlier and lasting longer and we're seeing more frequent fires. So, yeah, this is probably something that we'll be seeing more frequently. This tends to be much more of an issue in the Western US. So the Eastern US getting hit right now is a little bit new. But yeah, I think with climate change moving forward, this is something that is going to happen more frequently. That's ##### #######, ######### ######### in the ########## ## ############# ###### ### ########### at ##### ####### ##########. ######## #####, thanks so much for joining us and sharing this expertise with us. Thank you for having me.",
}
```

| Key    | Type   | Description                   |
| ------ | ------ | ----------------------------- |
| `text` | string | Transcript with redacted PII. |

The response also includes the request parameters used to generate the transcript.

### Request for Redacted Audio

In the request URL, replace transcript\_id with the ID of the transcript where `redact_pii_audio` is set to `true`.

```bash {6-10} theme={null}
curl https://api.assemblyai.com/v2/transcript/transcript_id/redacted-audio \
--header "Authorization: <YOUR_API_KEY>"
```

### Response for Redacted Audio

```js theme={null}
{
  status: "redacted_audio_ready",
  redacted_audio_url:
    "https://s3.us-west-2.amazonaws.com/api.assembly.ai.usw2/redacted-audio/785efd9e-0e20-45e1-967b-3db17770ed9f.wav?AWSAccessKeyId=aws-access-key0id&Signature=signature&x-amz-security-token=security-token&Expires=1698966551",
}
```

| Key                  | Type   | Description                         |
| -------------------- | ------ | ----------------------------------- |
| `status`             | string | The status of the redacted audio.   |
| `redacted_audio_url` | string | The URL of the redacted audio file. |

### PII policies

| Policy name                 | Description                                                                                                    | Example                                                          |
| --------------------------- | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `account_number`            | Customer account or membership identification number                                                           | `Policy No. 10042992; Member ID: HZ-5235-001`                    |
| `banking_information`       | Banking information, including account and routing numbers                                                     |                                                                  |
| `blood_type`                | Blood type                                                                                                     | O-, AB positive                                                  |
| `credit_card_cvv`           | Credit card verification code                                                                                  | CVV: 080                                                         |
| `credit_card_expiration`    | Expiration date of a credit card                                                                               |                                                                  |
| `credit_card_number`        | Credit card number                                                                                             |                                                                  |
| `date`                      | Specific calendar date                                                                                         | December 18                                                      |
| `date_interval`             | Broader time periods, including date ranges, months, seasons, years, and decades                               | 2020-2021, 5-9 May, January 1984                                 |
| `date_of_birth`             | Date of birth                                                                                                  | Date of Birth: March 7, 1961                                     |
| `drivers_license`           | Driver's license number                                                                                        | DL# 356933-540                                                   |
| `drug`                      | Medications, vitamins, or supplements                                                                          | Advil, Acetaminophen, Panadol                                    |
| `duration`                  | Measurements of time expressed as a numerical value plus a unit                                                | 8 months, 2 years                                                |
| `email_address`             | Email address                                                                                                  | [support@assemblyai.com](mailto:support@assemblyai.com)          |
| `event`                     | Name of an event or holiday                                                                                    | Olympics, Yom Kippur                                             |
| `filename`                  | Names of computer files, including the extension or filepath                                                   | Taxes/2012/brad-tax-returns.pdf                                  |
| `gender_sexuality`          | Terms indicating gender identity or sexual orientation, including slang terms                                  | female, bisexual, trans                                          |
| `healthcare_number`         | Healthcare numbers and health plan beneficiary numbers                                                         | Policy No.: 5584-486-674-YM                                      |
| `injury`                    | Bodily injury                                                                                                  | I broke my arm, I have a sprained wrist                          |
| `ip_address`                | Internet IP address, including IPv4 and IPv6 formats                                                           | 192.168.0.1                                                      |
| `language`                  | Name of a natural language                                                                                     | Spanish, French                                                  |
| `location`                  | Any Location reference including mailing address, postal code, city, state, province, country, or coordinates. | Lake Victoria, 145 Windsor St., 90210                            |
| `marital_status`            | Terms indicating marital status                                                                                | Single, common-law, ex-wife, married                             |
| `medical_condition`         | Name of a medical condition, disease, syndrome, deficit, or disorder                                           | chronic fatigue syndrome, arrhythmia, depression                 |
| `medical_process`           | Medical process, including treatments, procedures, and tests                                                   | heart surgery, CT scan                                           |
| `money_amount`              | Name and/or amount of currency                                                                                 | 15 pesos, \$94.50                                                |
| `nationality`               | Terms indicating nationality, ethnicity, or race                                                               | American, Asian, Caucasian                                       |
| `number_sequence`           | Numerical PII (including alphanumeric strings) that doesn't fall under other categories                        |                                                                  |
| `occupation`                | Job title or profession                                                                                        | professor, actors, engineer, CPA                                 |
| `organization`              | Name of an organization                                                                                        | CNN, McDonalds, University of Alaska, Northwest General Hospital |
| `passport_number`           | Passport numbers, issued by any country                                                                        | PA4568332, NU3C6L86S12                                           |
| `password`                  | Account passwords, PINs, access keys, or verification answers                                                  | 27%alfalfa, temp1234, My mother's maiden name is Smith           |
| `person_age`                | Number associated with an age                                                                                  | 27, 75                                                           |
| `person_name`               | Name of a person                                                                                               | Bob, Doug Jones, Dr. Kay Martinez, MD                            |
| `phone_number`              | Telephone or fax number                                                                                        |                                                                  |
| `physical_attribute`        | Distinctive bodily attributes, including race                                                                  | I'm 190cm tall                                                   |
| `political_affiliation`     | Terms referring to a political party, movement, or ideology                                                    | Republican, Liberal                                              |
| `religion`                  | Terms indicating religious affiliation                                                                         | Hindu, Catholic                                                  |
| `statistics`                | Medical statistics                                                                                             | 18%, 18 percent                                                  |
| `time`                      | Expressions indicating clock times                                                                             | 19:37:28, 10pm EST                                               |
| `url`                       | Internet addresses                                                                                             | [https://www.assemblyai.com/](https://www.assemblyai.com/)       |
| `us_social_security_number` | Social Security Number or equivalent                                                                           |                                                                  |
| `username`                  | Usernames, login names, or handles                                                                             | @AssemblyAI                                                      |
| `vehicle_id`                | Vehicle identification numbers (VINs), vehicle serial numbers, and license plate numbers                       | 5FNRL38918B111818, BIF7547                                       |
| `zodiac_sign`               | Names of Zodiac signs                                                                                          | Aries, Taurus                                                    |

## Troubleshooting

<Accordion title="Why is the PII not redacted in my transcription?" theme="dark" iconColor="white">
  Make sure that at least one [PII policy](#pii-policies) has been specified in
  your request, using the `redact_pii_policies` parameter. If you're still
  experiencing issues, please reach out to our support team for assistance.
</Accordion>

<Accordion title="Why is my webhook not being sent?" theme="dark" iconColor="white">
  There could be several reasons why your webhook isn't being sent, such as a
  misconfigured URL, an unreachable endpoint, or an issue with the
  authentication headers. Double-check your request and ensure that the{" "}
  `webhook_url` parameter is included with a valid URL that can be reached by
  AssemblyAI's API. If you're using custom authentication headers, ensure that
  the `webhook_auth_header_name` and `webhook_auth_header_value` parameters are
  included and are correct. If you're still having issues, please contact our
  support team for assistance.
</Accordion>

<Accordion title="Why does my redacted audio file sound worse than the original?" theme="dark" iconColor="white">
  By default, the API returns redacted audio files in MP3 format, a lossy
  format. Lossy formats remove audio information to reduce file size, which may
  cause a reduction in quality. The difference may be particularly noticeable if
  the submitted audio is in a lossless file format. To retain as much quality as
  possible, you can instead return your redacted audio files in a lossless
  format, by setting `redact_pii_audio_quality` to `wav`.
</Accordion>
